From 05487918f66b4ed7a1aee9c8ccddb94e0c5b837d Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:54:03 +0000 Subject: [PATCH] SDK regeneration --- .github/workflows/ci.yml | 4 +- .gitignore | 1 + .mock/definition/__package__.yml | 2895 ++++++++++ .mock/definition/accessGroups.yml | 80 + .mock/definition/api.yml | 13 + .mock/definition/assets.yml | 450 ++ .mock/definition/collections.yml | 186 + .mock/definition/collections/fields.yml | 189 + .mock/definition/collections/items.yml | 1644 ++++++ .mock/definition/components.yml | 485 ++ .mock/definition/ecommerce.yml | 42 + .mock/definition/forms.yml | 329 ++ .mock/definition/inventory.yml | 122 + .mock/definition/orders.yml | 1571 ++++++ .mock/definition/pages.yml | 472 ++ .mock/definition/pages/scripts.yml | 134 + .mock/definition/products.yml | 503 ++ .mock/definition/scripts.yml | 222 + .mock/definition/sites.yml | 510 ++ .mock/definition/sites/activityLogs.yml | 71 + .mock/definition/sites/plans.yml | 45 + .mock/definition/sites/redirects.yml | 209 + .mock/definition/sites/scripts.yml | 213 + .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 | 4807 ++++++++++++----- src/webflow/__init__.py | 107 +- 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 | 1307 ++++- 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 | 3625 ++++++++++--- .../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 | 1474 +++++ .../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 | 1209 ++++- 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 | 1144 +++- .../pages/resources/scripts/client.py | 533 +- 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 | 33 +- src/webflow/resources/scripts/client.py | 509 +- src/webflow/resources/sites/__init__.py | 5 +- src/webflow/resources/sites/client.py | 1404 ++++- .../resources/sites/resources/__init__.py | 4 +- .../sites/resources/activity_logs/client.py | 155 +- .../sites/resources/plans/__init__.py} | 3 - .../resources/sites/resources/plans/client.py | 237 + .../sites/resources/redirects/__init__.py | 2 + .../sites/resources/redirects/client.py | 1009 ++++ .../sites/resources/scripts/client.py | 684 ++- 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 | 89 +- 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 | 81 +- 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 | 54 +- src/webflow/types/assets.py | 34 +- 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 | 55 +- src/webflow/types/collection_item.py | 64 +- .../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 | 41 + src/webflow/types/component_properties.py | 35 + src/webflow/types/component_property.py | 47 + src/webflow/types/component_property_type.py | 5 + .../{error_details_item.py => conflict.py} | 2 +- 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 | 47 +- src/webflow/types/image_node_image.py | 26 + src/webflow/types/invalid_domain.py | 2 +- src/webflow/types/invalid_scopes.py | 5 + 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 | 78 +- .../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 | 42 +- ..._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 | 31 + src/webflow/types/text_node.py | 47 +- src/webflow/types/text_node_text.py | 31 + 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 | 36 +- 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 | 816 +++ 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 | 409 ++ tests/test_collections.py | 188 + tests/test_components.py | 266 + tests/test_ecommerce.py | 20 + tests/test_forms.py | 279 + tests/test_inventory.py | 32 + tests/test_orders.py | 2327 ++++++++ tests/test_pages.py | 403 ++ tests/test_products.py | 467 ++ 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 + 321 files changed, 44161 insertions(+), 8604 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 rename src/webflow/types/{error_details_item.py => conflict.py} (54%) create mode 100644 src/webflow/types/error_code.py create mode 100644 src/webflow/types/image_node_image.py create mode 100644 src/webflow/types/invalid_scopes.py 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 bb1b2d3..14569f6 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..6ccd505 --- /dev/null +++ b/.mock/definition/__package__.yml @@ -0,0 +1,2895 @@ +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: 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 +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: double + docs: The limit used for pagination + offset: + type: double + docs: The offset used for pagination + total: + type: double + 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: 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 + 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: string + docs: The date the item was last published + lastUpdated: + type: string + docs: The date the item was last updated + createdOn: + type: string + 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 + 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: 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: + 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 + 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: + 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: integer + 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: string + docs: Unique identifier for this asset + contentType: + type: string + docs: File format type + size: + type: integer + docs: size in bytes + siteId: + type: string + docs: Unique identifier for the site that hosts this asset + hostedUrl: + type: string + docs: Link to the asset + validation: + format: uri + originalFileName: + type: string + docs: Original file name at the time of upload + displayName: + type: string + docs: Display name of the asset + lastUpdated: + type: datetime + docs: Date the asset metadata was last updated + createdOn: + type: datetime + docs: Date the asset metadata was created + 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 + - user_account_added + - user_account_updated + - user_account_deleted + - collection_item_created + - collection_item_changed + - collection_item_deleted + - collection_item_unpublished + 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 + 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: + 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 + 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 + 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: 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: + 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 + 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..1cebe0c --- /dev/null +++ b/.mock/definition/assets.yml @@ -0,0 +1,450 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/assets + method: GET + auth: true + 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 + 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 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 + 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 + 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 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 + 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: 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 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 + 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: 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..7267390 --- /dev/null +++ b/.mock/definition/collections/items.yml @@ -0,0 +1,1644 @@ +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: Filter by the exact name of the item(s) + slug: + type: optional + docs: Filter by the exact 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. + + + 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: 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 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 + 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 all published items in 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: Filter by the exact name of the item(s) + slug: + type: optional + docs: Filter by the exact 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 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) + + + + 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: + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + 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: + - lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + 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. + + + Using this endpoint to delete published item(s) will unpublish the + item(s) from the live site and set the item(s) `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: 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 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 + body: + properties: + items: optional> + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItemListNoPagination + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.ConflictError + - 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. + + + + - 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 + 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. + + 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.ConflictError + - 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..be9d6dc --- /dev/null +++ b/.mock/definition/components.yml @@ -0,0 +1,485 @@ +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 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. 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 default property values of a component definition in a + specificed locale. + + + Before making updates, 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. + + + 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. 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..df35732 --- /dev/null +++ b/.mock/definition/forms.yml @@ -0,0 +1,329 @@ +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 + delete-submission: + path: /form_submissions/{form_submission_id} + method: DELETE + auth: true + 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 + 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..46cf60c --- /dev/null +++ b/.mock/definition/pages.yml @@ -0,0 +1,472 @@ +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 content from a static page. This includes text nodes, image nodes, + and component instances with [property + overrides](https://help.webflow.com/hc/en-us/articles/33961219350547-Component-properties#how-to-modify-property-values-on-component-instances). + + + To retrieve the static content of a component instance, use the [Get + Component + Content](/data/reference/pages-and-components/components/get-content) + endpoint. + + + If you do not include a `localeId` 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..e0ed659 --- /dev/null +++ b/.mock/definition/pages/scripts.yml @@ -0,0 +1,134 @@ +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 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 + 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: | + Apply scripts to a page. + + + 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 + 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 a custom code block that the App created on a page. + + + 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..d70f0ff --- /dev/null +++ b/.mock/definition/products.yml @@ -0,0 +1,503 @@ +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: + required: + key: value + 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: + required: optional + 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..bf507a7 --- /dev/null +++ b/.mock/definition/scripts.yml @@ -0,0 +1,222 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/registered_scripts + method: GET + auth: true + 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 + 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: | + 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 + 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: > + 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 + 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..75ce7d3 --- /dev/null +++ b/.mock/definition/sites.yml @@ -0,0 +1,510 @@ +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..182384a --- /dev/null +++ b/.mock/definition/sites/activityLogs.yml @@ -0,0 +1,71 @@ +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. + + + 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 + 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..d72210a --- /dev/null +++ b/.mock/definition/sites/plans.yml @@ -0,0 +1,45 @@ +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. + + + 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 + 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..7ded8da --- /dev/null +++ b/.mock/definition/sites/redirects.yml @@ -0,0 +1,209 @@ +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. + + + 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 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. + + + 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 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. + + + 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 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. + + + 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 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..80535b1 --- /dev/null +++ b/.mock/definition/sites/scripts.yml @@ -0,0 +1,213 @@ +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 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 + 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: | + Apply registered scripts 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: 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: > + Remove scripts from a site applied by the App. This endpoint will not + remove scripts from the site's registered scripts. + + + 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 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 + 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..f31342a --- /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: + 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 + 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..74ac5df 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,11 @@ 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 +156,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 +180,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 +224,7 @@ client.sites.list()
-
client.sites.get(...) +
client.sites.list()
@@ -193,7 +236,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 +253,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 +274,6 @@ client.sites.get(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -251,7 +286,7 @@ client.sites.get(
-
client.sites.get_custom_domain(...) +
client.sites.get(...)
@@ -263,7 +298,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 +315,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 +358,7 @@ client.sites.get_custom_domain(
-
client.sites.publish(...) +
client.sites.delete(...)
@@ -333,7 +370,11 @@ 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 +389,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 +420,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 +432,7 @@ client.sites.publish(
-## Sites ActivityLogs -
client.sites.activity_logs.list(...) +
client.sites.update(...)
@@ -420,7 +444,11 @@ 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 +463,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 +494,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 +502,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 +522,7 @@ client.sites.activity_logs.list(
-## Collections -
client.collections.list(...) +
client.sites.get_custom_domain(...)
@@ -507,7 +534,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 +551,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 +594,7 @@ client.collections.list(
-
client.collections.create(...) +
client.sites.publish(...)
@@ -577,7 +606,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 +625,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 +656,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 +664,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 +684,8 @@ client.collections.create(
-
client.collections.get(...) +## Collections +
client.collections.list(...)
@@ -674,7 +697,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 +714,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 +737,7 @@ client.collections.get(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -732,7 +757,7 @@ client.collections.get(
-
client.collections.delete_collection(...) +
client.collections.create(...)
@@ -744,7 +769,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 +786,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 +812,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 +856,7 @@ client.collections.delete_collection(
-
client.collections.delete(...) +
client.collections.get(...)
@@ -814,7 +868,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 +885,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 +916,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 +928,7 @@ client.collections.delete(
-## Collections Fields -
client.collections.fields.create(...) +
client.collections.delete(...)
@@ -894,7 +940,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 +957,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 +988,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 +1000,8 @@ client.collections.fields.create(
-
client.collections.fields.update(...) +## Pages +
client.pages.list(...)
@@ -1001,7 +1013,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 +1030,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 +1054,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 +1062,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 +1070,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 +1078,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 +1098,7 @@ client.collections.fields.update(
-## Collections Items -
client.collections.items.list_items(...) +
client.pages.get_metadata(...)
@@ -1108,7 +1110,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 +1127,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 +1151,7 @@ client.collections.items.list_items(
-**collection_id:** `str` — Unique identifier for a Collection +**page_id:** `str` — Unique identifier for a Page
@@ -1154,7 +1159,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 +1167,1591 @@ 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 content from a static page. This includes text nodes, image nodes, and component instances with [property overrides](https://help.webflow.com/hc/en-us/articles/33961219350547-Component-properties#how-to-modify-property-values-on-component-instances). + +To retrieve the static content of a component instance, use the [Get Component Content](/data/reference/pages-and-components/components/get-content) endpoint. + +If you do not include a `localeId` 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 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` +
+
+
+
+ +#### 🔌 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 default property values of a component definition in a specificed locale. + +Before making updates, 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. + +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` +
+
+
+
+ +#### 🔌 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 + +
+
+ +
+
+ +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` +
+
+
+
+ +#### 🔌 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 + +
+
+ +
+
+ +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` +
+
+
+
+ +#### 🔌 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 + +
+
+ +
+
+ +**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 + +
+
+ +
+
+ +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` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.register_inline( + site_id="580e63e98c9a982ac9b8b741", + 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 of assets uploaded to a 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 + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +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` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.create( + site_id="580e63e98c9a982ac9b8b741", + 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 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. + +
+
+
+
+ + +
+
+
+ +
client.assets.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get details about an asset + +Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.get( + asset_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters +
-**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1222,7 +2771,7 @@ client.collections.items.list_items(
-
client.collections.items.create_item(...) +
client.assets.delete(...)
@@ -1234,7 +2783,9 @@ client.collections.items.list_items(
-Create Item in a Collection.

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

Required scope | `CMS:write` +Delete an Asset + +Required Scope: `assets: write`
@@ -1249,25 +2800,13 @@ 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.assets.delete( + asset_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -1284,7 +2823,7 @@ client.collections.items.create_item(
-**collection_id:** `str` — Unique identifier for a Collection +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1292,31 +2831,71 @@ client.collections.items.create_item(
-**id:** `str` — Unique identifier for the Item +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + + +
+
client.assets.update(...)
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item - +#### 📝 Description + +
+
+ +
+
+ +Update details of an Asset. + +Required scope | `assets:write`
+
+
+ +#### 🔌 Usage
-**last_published:** `typing.Optional[str]` — The date the item was last published - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.update( + asset_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+#### ⚙️ Parameters +
-**last_updated:** `typing.Optional[str]` — The date the item was last updated +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1324,7 +2903,7 @@ client.collections.items.create_item(
-**created_on:** `typing.Optional[str]` — The date the item was created +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -1332,7 +2911,7 @@ client.collections.items.create_item(
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +**display_name:** `typing.Optional[str]` — A human readable name for the asset
@@ -1340,15 +2919,71 @@ client.collections.items.create_item(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +**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 import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.list_folders( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters
-**field_data:** `typing.Optional[CollectionItemFieldData]` +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -1368,7 +3003,7 @@ client.collections.items.create_item(
-
client.collections.items.list_items_live(...) +
client.assets.create_folder(...)
@@ -1380,7 +3015,9 @@ client.collections.items.create_item(
-List of all live Items within a Collection.

Required scope | `CMS:read` +Create an Asset Folder within a given site + +Required scope | `assets:write`
@@ -1395,13 +3032,14 @@ 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_folder( + site_id="580e63e98c9a982ac9b8b741", + display_name="my asset folder", ) ``` @@ -1418,7 +3056,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 +3064,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. +**display_name:** `str` — A human readable name for the Asset Folder
@@ -1434,7 +3072,7 @@ client.collections.items.list_items_live(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**parent_folder:** `typing.Optional[str]` — An (optional) pointer to a parent Asset Folder (or null for root)
@@ -1442,23 +3080,71 @@ client.collections.items.list_items_live(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + +
+ +
client.assets.get_folder(...)
-**name:** `typing.Optional[str]` — The name of the item(s) - +#### 📝 Description + +
+
+ +
+
+ +Get details about a specific Asset Folder + +Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.get_folder( + asset_folder_id="6390c49774a71f0e3c1a08ee", +) + +``` +
+
+#### ⚙️ Parameters + +
+
+
-**slug:** `typing.Optional[str]` — The slug of the item +**asset_folder_id:** `str` — Unique identifier for an Asset Folder
@@ -1466,15 +3152,72 @@ client.collections.items.list_items_live(
-**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + +
+
+
+ +## Webhooks +
client.webhooks.list(...) +
+
+ +#### 📝 Description
-**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc +
+
+ +List all App-created Webhooks registered for a given site + +Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.list( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -1494,7 +3237,7 @@ client.collections.items.list_items_live(
-
client.collections.items.create_item_live(...) +
client.webhooks.create(...)
@@ -1506,7 +3249,12 @@ 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` +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`
@@ -1521,24 +3269,25 @@ 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 +import datetime + +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.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", ), ) @@ -1556,7 +3305,7 @@ client.collections.items.create_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id_:** `str` — Unique identifier for a Site
@@ -1564,7 +3313,7 @@ client.collections.items.create_item_live(
-**id:** `str` — Unique identifier for the Item +**id:** `typing.Optional[str]` — Unique identifier for the Webhook registration
@@ -1572,7 +3321,7 @@ client.collections.items.create_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item +**trigger_type:** `typing.Optional[TriggerType]`
@@ -1580,7 +3329,7 @@ client.collections.items.create_item_live(
-**last_published:** `typing.Optional[str]` — The date the item was last published +**url:** `typing.Optional[str]` — URL to send the Webhook payload to
@@ -1588,7 +3337,7 @@ client.collections.items.create_item_live(
-**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
@@ -1596,7 +3345,7 @@ client.collections.items.create_item_live(
-**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
@@ -1604,7 +3353,7 @@ client.collections.items.create_item_live(
-**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.
@@ -1612,7 +3361,7 @@ client.collections.items.create_item_live(
-**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
@@ -1620,7 +3369,7 @@ client.collections.items.create_item_live(
-**field_data:** `typing.Optional[CollectionItemFieldData]` +**created_on:** `typing.Optional[dt.datetime]` — Date the Webhook registration was created
@@ -1640,7 +3389,7 @@ client.collections.items.create_item_live(
-
client.collections.items.create_item_for_multiple_locales(...) +
client.webhooks.get(...)
@@ -1652,7 +3401,9 @@ client.collections.items.create_item_live(
-Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` +Get a specific Webhook instance + +Required scope: `sites:read`
@@ -1667,14 +3418,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.webhooks.get( + webhook_id="580e64008c9a982ac9b8b754", ) ``` @@ -1691,7 +3441,7 @@ client.collections.items.create_item_for_multiple_locales(
-**collection_id:** `str` — Unique identifier for a Collection +**webhook_id:** `str` — Unique identifier for a Webhook
@@ -1699,63 +3449,71 @@ 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.webhooks.delete(...)
-**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 - -
-
-
-**created_on:** `typing.Optional[str]` — The date the item was created - +Remove a Webhook + +Required scope: `sites:read` +
+
+#### 🔌 Usage +
-**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 - +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.delete( + webhook_id="580e64008c9a982ac9b8b754", +) + +``` +
+
+#### ⚙️ Parameters + +
+
+
-**field_data:** `typing.Optional[BulkCollectionItemFieldData]` +**webhook_id:** `str` — Unique identifier for a Webhook
@@ -1775,7 +3533,8 @@ client.collections.items.create_item_for_multiple_locales(
-
client.collections.items.get_item(...) +## Forms +
client.forms.list(...)
@@ -1787,7 +3546,9 @@ client.collections.items.create_item_for_multiple_locales(
-Get details of a selected Collection Item.

Required scope | `CMS:read` +List forms for a given site. + +Required scope | `forms:read`
@@ -1802,14 +3563,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.forms.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -1826,7 +3586,7 @@ client.collections.items.get_item(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -1834,7 +3594,7 @@ client.collections.items.get_item(
-**item_id:** `str` — Unique identifier for an Item +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -1842,7 +3602,7 @@ client.collections.items.get_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. +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -1862,7 +3622,7 @@ client.collections.items.get_item(
-
client.collections.items.delete_item(...) +
client.forms.get(...)
@@ -1874,7 +3634,9 @@ client.collections.items.get_item(
-Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` +Get information about a given form. + +Required scope | `forms:read`
@@ -1889,14 +3651,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.forms.get( + form_id="580e63e98c9a982ac9b8b741", ) ``` @@ -1913,23 +3674,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. +**form_id:** `str` — Unique identifier for a Form
@@ -1949,7 +3694,7 @@ client.collections.items.delete_item(
-
client.collections.items.update_item(...) +
client.forms.list_submissions(...)
@@ -1961,7 +3706,9 @@ client.collections.items.delete_item(
-Update a selected Item in a Collection.

Required scope | `CMS:write` +List form submissions for a given form + +Required scope | `forms:read`
@@ -1976,26 +3723,13 @@ Update a selected Item in a Collection.

Required scope | `CMS:write`
```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( - 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.list_submissions( + form_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2012,7 +3746,7 @@ client.collections.items.update_item(
-**collection_id:** `str` — Unique identifier for a Collection +**form_id:** `str` — Unique identifier for a Form
@@ -2020,7 +3754,7 @@ client.collections.items.update_item(
-**item_id:** `str` — Unique identifier for an Item +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -2028,7 +3762,7 @@ client.collections.items.update_item(
-**id:** `str` — Unique identifier for the Item +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2036,55 +3770,71 @@ client.collections.items.update_item(
-**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 -
+
+
client.forms.get_submission(...)
-**last_updated:** `typing.Optional[str]` — The date the item was last updated - -
-
+#### 📝 Description
-**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 - +Get information about a given form submissio. + +Required scope | `forms:read` +
+
+#### 🔌 Usage +
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.get_submission( + form_submission_id="580e63e98c9a982ac9b8b741", +) + +```
+
+
+ +#### ⚙️ Parameters
-**field_data:** `typing.Optional[CollectionItemFieldData]` +
+
+ +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -2104,7 +3854,7 @@ client.collections.items.update_item(
-
client.collections.items.get_item_live(...) +
client.forms.delete_submission(...)
@@ -2116,7 +3866,10 @@ client.collections.items.update_item(
-Get details of a selected Collection live Item.

Required scope | `CMS:read` +Delete a form submission + + +Required scope | `forms:write`
@@ -2131,14 +3884,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.forms.delete_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2155,23 +3907,7 @@ client.collections.items.get_item_live(
-**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. +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -2191,7 +3927,7 @@ client.collections.items.get_item_live(
-
client.collections.items.delete_item_live(...) +
client.forms.update_submission(...)
@@ -2203,7 +3939,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` +Update hidden fields on a form submission + +Required scope | `forms:write`
@@ -2218,14 +3956,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.update_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2242,15 +3979,7 @@ client.collections.items.delete_item_live(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -2258,7 +3987,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. +**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
@@ -2278,7 +4007,8 @@ client.collections.items.delete_item_live(
-
client.collections.items.update_item_live(...) +## Users +
client.users.list(...)
@@ -2290,7 +4020,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 a list of users for a site + +Required scope | `users:read`
@@ -2305,83 +4037,30 @@ 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", - ), -) - -``` -
-
- - - -#### ⚙️ Parameters - -
-
- -
-
- -**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item - -
-
- -
-
+client.users.list( + site_id="580e63e98c9a982ac9b8b741", +) -**id:** `str` — Unique identifier for the Item - +```
- -
-
- -**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item -
+#### ⚙️ Parameters +
-**last_published:** `typing.Optional[str]` — The date the item was last published - -
-
-
-**last_updated:** `typing.Optional[str]` — The date the item was last updated +**site_id:** `str` — Unique identifier for a Site
@@ -2389,7 +4068,7 @@ client.collections.items.update_item_live(
-**created_on:** `typing.Optional[str]` — The date the item was created +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -2397,7 +4076,7 @@ client.collections.items.update_item_live(
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2405,15 +4084,13 @@ client.collections.items.update_item_live(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft - -
-
+**sort:** `typing.Optional[UsersListRequestSort]` -
-
+Sort string to use when ordering users + +Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). -**field_data:** `typing.Optional[CollectionItemFieldData]` +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -2433,7 +4110,7 @@ client.collections.items.update_item_live(
-
client.collections.items.publish_item(...) +
client.users.get(...)
@@ -2445,7 +4122,9 @@ client.collections.items.update_item_live(
-Publish an item or multiple items.

Required scope | `cms:write` +Get a User by ID + +Required scope | `users:read`
@@ -2460,14 +4139,14 @@ 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.users.get( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2484,7 +4163,7 @@ client.collections.items.publish_item(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -2492,7 +4171,7 @@ client.collections.items.publish_item(
-**item_ids:** `typing.Sequence[str]` +**user_id:** `str` — Unique identifier for a User
@@ -2512,8 +4191,7 @@ client.collections.items.publish_item(
-## Pages -
client.pages.list(...) +
client.users.delete(...)
@@ -2525,7 +4203,9 @@ client.collections.items.publish_item(
-List of all pages for a site

Required scope | `pages:read` +Delete a User by ID + +Required scope | `users:write`
@@ -2540,13 +4220,14 @@ 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.users.delete( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2571,23 +4252,7 @@ client.pages.list(
-**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 +**user_id:** `str` — Unique identifier for a User
@@ -2607,7 +4272,7 @@ client.pages.list(
-
client.pages.get_metadata(...) +
client.users.update(...)
@@ -2619,7 +4284,12 @@ client.pages.list(
-Get metadata information for a single page

Required scope | `pages:read` +Update a User by ID + + Required scope | `users:write` + +The email and password +fields cannot be updated using this endpoint
@@ -2634,13 +4304,21 @@ Get metadata information for a single page

Required scope | `pages:re
```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_metadata( - 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"], ) ``` @@ -2657,7 +4335,23 @@ client.pages.get_metadata(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**user_id:** `str` — Unique identifier for a User + +
+
+ +
+
+ +**data:** `typing.Optional[UsersUpdateRequestData]`
@@ -2665,7 +4359,8 @@ client.pages.get_metadata(
-**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**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. +
@@ -2685,7 +4380,7 @@ client.pages.get_metadata(
-
client.pages.update_page_settings(...) +
client.users.invite(...)
@@ -2697,7 +4392,11 @@ client.pages.get_metadata(
-Update Page-level metadata, including SEO and Open Graph fields.

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`
@@ -2712,41 +4411,15 @@ 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.invite( + site_id="580e63e98c9a982ac9b8b741", + email="some.one@home.com", + access_groups=["webflowers"], ) ``` @@ -2763,7 +4436,7 @@ client.pages.update_page_settings(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -2771,7 +4444,7 @@ client.pages.update_page_settings(
-**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**email:** `str` — Email address of user to send invite to
@@ -2779,7 +4452,8 @@ client.pages.update_page_settings(
-**id:** `typing.Optional[str]` — Unique identifier for the Page +**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. +
@@ -2787,79 +4461,72 @@ client.pages.update_page_settings(
-**site_id:** `typing.Optional[str]` — Unique identifier for the Site +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
- -
-
- -**title:** `typing.Optional[str]` — Title of the Page -
-
-
-**slug:** `typing.Optional[str]` — slug of the Page (derived from title) -
+
+## AccessGroups +
client.access_groups.list(...)
-**parent_id:** `typing.Optional[str]` — Identifier of the parent folder - -
-
+#### 📝 Description
-**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 - +Get a list of access groups for a site + +Required scope | `users:read`
+ + + +#### 🔌 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.access_groups.list( + site_id="580e63e98c9a982ac9b8b741", +) + +```
+ + + +#### ⚙️ Parameters
-**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) +**site_id:** `str` — Unique identifier for a Site
@@ -2867,7 +4534,7 @@ 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) +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -2875,7 +4542,7 @@ client.pages.update_page_settings(
-**seo:** `typing.Optional[PageSeo]` — SEO-related fields for the Page +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2883,7 +4550,10 @@ client.pages.update_page_settings(
-**open_graph:** `typing.Optional[PageOpenGraph]` — Open Graph fields for the Page +**sort:** `typing.Optional[AccessGroupsListRequestSort]` + +Sort string to use when ordering access groups +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -2903,7 +4573,8 @@ client.pages.update_page_settings(
-
client.pages.get_content(...) +## Products +
client.products.list(...)
@@ -2915,7 +4586,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` +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`
@@ -2930,13 +4606,13 @@ 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 client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.get_content( - page_id="page_id", +client.products.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2953,7 +4629,7 @@ client.pages.get_content(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -2961,7 +4637,7 @@ client.pages.get_content(
-**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
@@ -2977,14 +4653,6 @@ client.pages.get_content(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -2997,7 +4665,7 @@ client.pages.get_content(
-
client.pages.update_static_content(...) +
client.products.create(...)
@@ -3009,7 +4677,20 @@ client.pages.get_content(
-Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages: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`
@@ -3024,29 +4705,13 @@ 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.products.create( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3063,7 +4728,15 @@ client.pages.update_static_content(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]`
@@ -3071,7 +4744,7 @@ client.pages.update_static_content(
-**locale:** `str` — The locale identifier. +**product:** `typing.Optional[Product]`
@@ -3079,7 +4752,7 @@ client.pages.update_static_content(
-**nodes:** `typing.Sequence[DomWriteNodesItem]` +**sku:** `typing.Optional[Sku]`
@@ -3099,8 +4772,7 @@ client.pages.update_static_content(
-## Pages Scripts -
client.pages.scripts.get_custom_code(...) +
client.products.get(...)
@@ -3112,7 +4784,10 @@ 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` +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. + +Required scope | `ecommerce:read`
@@ -3127,13 +4802,14 @@ 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.products.get( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -3150,7 +4826,15 @@ client.pages.scripts.get_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product
@@ -3170,7 +4854,7 @@ client.pages.scripts.get_custom_code(
-
client.pages.scripts.upsert_custom_code(...) +
client.products.update(...)
@@ -3182,7 +4866,11 @@ 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` +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`
@@ -3197,27 +4885,14 @@ 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.update( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -3234,7 +4909,7 @@ client.pages.scripts.upsert_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -3242,7 +4917,7 @@ client.pages.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
@@ -3250,7 +4925,7 @@ client.pages.scripts.upsert_custom_code(
-**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated +**publish_status:** `typing.Optional[PublishStatus]`
@@ -3258,7 +4933,15 @@ client.pages.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]`
@@ -3278,7 +4961,7 @@ client.pages.scripts.upsert_custom_code(
-
client.pages.scripts.delete_custom_code(...) +
client.products.create_sku(...)
@@ -3290,7 +4973,11 @@ 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 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`
@@ -3305,13 +4992,15 @@ Delete the custom code block that an app has created for a page

In or
```python -from webflow.client import Webflow +from webflow import Sku, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.delete_custom_code( - page_id="page_id", +client.products.create_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[Sku()], ) ``` @@ -3328,7 +5017,31 @@ client.pages.scripts.delete_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**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]`
@@ -3348,8 +5061,7 @@ client.pages.scripts.delete_custom_code(
-## Sites Scripts -
client.sites.scripts.get_custom_code(...) +
client.products.update_sku(...)
@@ -3361,7 +5073,11 @@ 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` +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`
@@ -3376,13 +5092,16 @@ Get all registered scripts that have been applied to a specific Site. ```python -from webflow.client import Webflow +from webflow import Sku, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.get_custom_code( - site_id="site_id", +client.products.update_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", + sku=Sku(), ) ``` @@ -3407,6 +5126,38 @@ client.sites.scripts.get_custom_code(
+**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.
@@ -3419,7 +5170,8 @@ client.sites.scripts.get_custom_code(
-
client.sites.scripts.upsert_custom_code(...) +## Orders +
client.orders.list(...)
@@ -3431,7 +5183,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.
Required scope | `custom_code:write` +List all orders created for a given site. + +Required scope | `ecommerce:read`
@@ -3446,27 +5200,13 @@ 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.orders.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3491,7 +5231,7 @@ client.sites.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page +**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status
@@ -3499,7 +5239,7 @@ client.sites.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
@@ -3507,7 +5247,7 @@ client.sites.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)
@@ -3527,7 +5267,7 @@ client.sites.scripts.upsert_custom_code(
-
client.sites.scripts.delete_custom_code(...) +
client.orders.get(...)
@@ -3539,7 +5279,10 @@ 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` +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. + +Required scope | `ecommerce:read`
@@ -3554,13 +5297,14 @@ Delete the custom code block that an app created for a Site

```python -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", +client.orders.get( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -3585,6 +5329,14 @@ client.sites.scripts.delete_custom_code(
+**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3597,7 +5349,7 @@ client.sites.scripts.delete_custom_code(
-
client.sites.scripts.list_custom_code_blocks(...) +
client.orders.update(...)
@@ -3609,7 +5361,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` +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`
@@ -3624,13 +5380,14 @@ 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 +**order_id:** `str` — Unique identifier for an Order
@@ -3663,7 +5420,31 @@ client.sites.scripts.list_custom_code_blocks(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**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
@@ -3683,8 +5464,7 @@ client.sites.scripts.list_custom_code_blocks(
-## Scripts -
client.scripts.list(...) +
client.orders.update_fulfill(...)
@@ -3696,7 +5476,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` +Updates an order's status to fulfilled + +Required scope | `ecommerce:write`
@@ -3711,13 +5493,14 @@ 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.update_fulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -3742,6 +5525,22 @@ client.scripts.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.
@@ -3754,7 +5553,7 @@ client.scripts.list(
-
client.scripts.register_hosted(...) +
client.orders.update_unfulfill(...)
@@ -3766,7 +5565,9 @@ 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` +Updates an order's status to unfulfilled + +Required scope | `ecommerce:write`
@@ -3781,66 +5582,31 @@ 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.update_unfulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) -``` -
-
- - - -#### ⚙️ 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 -
+#### ⚙️ Parameters +
-**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 +5614,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 +5634,7 @@ client.scripts.register_hosted(
-
client.scripts.register_inline(...) +
client.orders.refund(...)
@@ -3880,7 +5646,10 @@ 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 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`
@@ -3895,16 +5664,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.refund( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -3929,31 +5696,7 @@ client.scripts.register_inline(
-**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) +**order_id:** `str` — Unique identifier for an Order
@@ -3961,7 +5704,7 @@ client.scripts.register_inline(
-**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer +**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund
@@ -3981,8 +5724,8 @@ client.scripts.register_inline(
-## Assets -
client.assets.list(...) +## Inventory +
client.inventory.list(...)
@@ -3994,7 +5737,9 @@ client.scripts.register_inline(
-List assets for a given site

Required scope | `assets:read` +List the current inventory levels for a particular SKU item. + +Required scope | `ecommerce:read`
@@ -4009,13 +5754,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.inventory.list( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -4032,7 +5778,15 @@ client.assets.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item
@@ -4052,7 +5806,7 @@ client.assets.list(
-
client.assets.create(...) +
client.inventory.update(...)
@@ -4064,7 +5818,13 @@ 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 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`
@@ -4079,15 +5839,15 @@ 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.inventory.update( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + inventory_type="infinite", ) ``` @@ -4104,7 +5864,7 @@ client.assets.create(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -4112,7 +5872,7 @@ client.assets.create(
-**file_name:** `str` — file name including file extension +**item_id:** `str` — Unique identifier for an Item
@@ -4120,7 +5880,15 @@ client.assets.create(
-**file_hash:** `str` — MD5 hash of the file +**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite + +
+
+ +
+
+ +**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative.
@@ -4128,7 +5896,7 @@ client.assets.create(
-**parent_folder:** `typing.Optional[str]` — id of the Asset folder (optional) +**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value.
@@ -4148,7 +5916,8 @@ client.assets.create(
-
client.assets.get(...) +## Ecommerce +
client.ecommerce.get_settings(...)
@@ -4160,7 +5929,9 @@ client.assets.create(
-Get an Asset

Required scope | `assets:read` +Retrieve ecommerce settings for a site. + +Required scope | `ecommerce:read`
@@ -4175,13 +5946,13 @@ 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.ecommerce.get_settings( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -4198,7 +5969,7 @@ client.assets.get(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**site_id:** `str` — Unique identifier for a Site
@@ -4218,7 +5989,8 @@ client.assets.get(
-
client.assets.delete(...) +## Collections Fields +
client.collections.fields.create(...)
@@ -4230,7 +6002,16 @@ client.assets.get(
-Delete an Asset +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`
@@ -4245,13 +6026,17 @@ 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.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", ) ``` @@ -4268,7 +6053,39 @@ client.assets.delete(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**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
@@ -4288,7 +6105,7 @@ client.assets.delete(
-
client.assets.update(...) +
client.collections.fields.delete(...)
@@ -4300,7 +6117,9 @@ client.assets.delete(
-Update an Asset

Required scope | `assets:write` +Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + +Required scope | `cms:write`
@@ -4315,14 +6134,14 @@ 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.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4339,7 +6158,7 @@ client.assets.update(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**collection_id:** `str` — Unique identifier for a Collection
@@ -4347,7 +6166,7 @@ client.assets.update(
-**display_name:** `str` — file name including file extension +**field_id:** `str` — Unique identifier for a Field in a collection
@@ -4367,7 +6186,7 @@ client.assets.update(
-
client.assets.list_folders(...) +
client.collections.fields.update(...)
@@ -4379,7 +6198,9 @@ client.assets.update(
-List Asset Folders within a given site

Required scope | `assets:read` +Update a custom field in a collection. + +Required scope | `cms:write`
@@ -4394,13 +6215,17 @@ 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.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", ) ``` @@ -4417,7 +6242,39 @@ client.assets.list_folders(
-**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
@@ -4437,7 +6294,8 @@ client.assets.list_folders(
-
client.assets.create_folder(...) +## Collections Items +
client.collections.items.list_items(...)
@@ -4449,7 +6307,9 @@ client.assets.list_folders(
-Create an Asset Folder within a given site

Required scope | `assets:write` +List of all Items within a Collection. + +Required scope | `CMS:read`
@@ -4464,14 +6324,13 @@ 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.items.list_items( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4488,7 +6347,7 @@ client.assets.create_folder(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -4496,7 +6355,7 @@ client.assets.create_folder(
-**display_name:** `str` — A human readable name for the Asset Folder +**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.
@@ -4504,7 +6363,7 @@ client.assets.create_folder(
-**parent_folder:** `typing.Optional[str]` — An (optional) pointer to a parent Asset Folder (or null for root) +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -4512,69 +6371,39 @@ client.assets.create_folder(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
-
-
- - - - -
- -
client.assets.get_folder(...) -
-
- -#### 📝 Description - -
-
-Get details about a specific Asset Folder

Required scope | `assets:read` -
-
+**name:** `typing.Optional[str]` — Filter by the exact name of the item(s) +
-#### 🔌 Usage - -
-
-
-```python -from webflow.client import Webflow - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.assets.get_folder( - asset_folder_id="asset_folder_id", -) - -``` -
-
+**slug:** `typing.Optional[str]` — Filter by the exact slug of the item +
-#### ⚙️ Parameters -
+**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value + +
+
+
-**asset_folder_id:** `str` — Unique identifier for an Asset Folder +**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc
@@ -4594,8 +6423,7 @@ client.assets.get_folder(
-## Webhooks -
client.webhooks.list(...) +
client.collections.items.create_item(...)
@@ -4607,7 +6435,12 @@ client.assets.get_folder(
-List all App-created Webhooks registered for a given site

Required scope | `sites:read` +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`
@@ -4622,13 +6455,38 @@ List all App-created Webhooks registered for a given site

Required sc
```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.list( - site_id="site_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", + ), + ), + ], + ), ) ``` @@ -4645,7 +6503,15 @@ client.webhooks.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request:** `ItemsCreateItemRequest`
@@ -4665,7 +6531,7 @@ client.webhooks.list(
-
client.webhooks.create(...) +
client.collections.items.delete_items(...)
@@ -4677,7 +6543,11 @@ 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` +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`
@@ -4692,16 +6562,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.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4718,24 +6585,7 @@ client.webhooks.create(
-**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 - +**collection_id:** `str` — Unique identifier for a Collection
@@ -4743,11 +6593,7 @@ client.webhooks.create(
-**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. ** - +**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]]`
@@ -4767,7 +6613,7 @@ Filter for selecting which events you want Webhooks to be triggered for.
-
client.webhooks.get(...) +
client.collections.items.update_items(...)
@@ -4779,7 +6625,13 @@ Filter for selecting which events you want Webhooks to be triggered for.
-Get a specific Webhook instance +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`
@@ -4794,13 +6646,51 @@ Get a specific Webhook instance
```python -from webflow.client import Webflow +from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.webhooks.get( - webhook_id="webhook_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", + ), + ), + ], ) ``` @@ -4817,7 +6707,15 @@ client.webhooks.get(
-**webhook_id:** `str` — Unique identifier for a Webhook +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -4837,7 +6735,7 @@ client.webhooks.get(
-
client.webhooks.delete(...) +
client.collections.items.list_items_live(...)
@@ -4849,7 +6747,9 @@ client.webhooks.get(
-Remove a Webhook +List all published items in a collection. + +Required scope | `CMS:read`
@@ -4864,13 +6764,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.list_items_live( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4887,7 +6787,7 @@ client.webhooks.delete(
-**webhook_id:** `str` — Unique identifier for a Webhook +**collection_id:** `str` — Unique identifier for a Collection
@@ -4895,70 +6795,39 @@ client.webhooks.delete(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**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.
-
-
- - - - -
-## Forms -
client.forms.list(...)
-#### 📝 Description - -
-
+**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
-List forms for a given site

Required scope | `forms:read` -
-
+**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +
-#### 🔌 Usage - -
-
-
-```python -from webflow.client import Webflow - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.forms.list( - site_id="site_id", -) - -``` -
-
+**name:** `typing.Optional[str]` — Filter by the exact name of the item(s) +
-#### ⚙️ Parameters -
-
-
- -**site_id:** `str` — Unique identifier for a Site +**slug:** `typing.Optional[str]` — Filter by the exact slug of the item
@@ -4966,7 +6835,7 @@ client.forms.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value
@@ -4974,7 +6843,7 @@ client.forms.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc
@@ -4994,7 +6863,7 @@ client.forms.list(
-
client.forms.get(...) +
client.collections.items.create_item_live(...)
@@ -5006,7 +6875,13 @@ client.forms.list(
-Get information about a given form

Required scope | `forms:read` +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) + + +Required scope | `CMS:write`
@@ -5021,13 +6896,40 @@ Get information about 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.get( - form_id="form_id", +client.collections.items.create_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + request=MultipleLiveItems( + items=[ + CollectionItem( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Senior Data Analyst", + slug="senior-data-analyst", + ), + ), + CollectionItem( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Product Manager", + slug="product-manager", + ), + ), + ], + ), ) ``` @@ -5044,7 +6946,15 @@ client.forms.get(
-**form_id:** `str` — Unique identifier for a Form +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request:** `ItemsCreateItemLiveRequest`
@@ -5064,7 +6974,7 @@ client.forms.get(
-
client.forms.list_submissions(...) +
client.collections.items.delete_items_live(...)
@@ -5076,7 +6986,13 @@ client.forms.get(
-List form submissions for a given form

Required scope | `forms:read` +Remove an item or multiple items (up to 100 items) from the live site. + +Using this endpoint to delete published item(s) will unpublish the item(s) from the live site and set the item(s) `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`
@@ -5091,13 +7007,13 @@ List form submissions for 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.list_submissions( - form_id="form_id", +client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -5114,7 +7030,15 @@ client.forms.list_submissions(
-**form_id:** `str` — Unique identifier for a Form +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]]`
@@ -5134,7 +7058,7 @@ client.forms.list_submissions(
-
client.forms.get_submission(...) +
client.collections.items.update_items_live(...)
@@ -5146,7 +7070,11 @@ client.forms.list_submissions(
-Get information about a given form submission

Required scope | `forms:read` +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`
@@ -5161,13 +7089,51 @@ Get information about a given form submission

Required scope | `forms:
```python -from webflow.client import Webflow +from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.get_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", + ), + ), + ], ) ``` @@ -5184,7 +7150,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[CollectionItemWithIdInput]]`
@@ -5204,7 +7178,7 @@ client.forms.get_submission(
-
client.forms.update_submission(...) +
client.collections.items.create_items(...)
@@ -5216,7 +7190,14 @@ client.forms.get_submission(
-Update hidden fields on a form submission

Required scope | `forms:write` +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`
@@ -5231,13 +7212,25 @@ Update hidden fields on a form submission

Required scope | `forms:writ
```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.forms.update_submission( - form_submission_id="form_submission_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", + ), ) ``` @@ -5254,7 +7247,31 @@ client.forms.update_submission(
-**form_submission_id:** `str` — Unique identifier for a Form Submission +**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.
@@ -5262,7 +7279,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 +**is_draft:** `typing.Optional[bool]` — Indicates whether the item is in draft state.
@@ -5282,8 +7299,7 @@ client.forms.update_submission(
-## Users -
client.users.list(...) +
client.collections.items.get_item(...)
@@ -5295,7 +7311,9 @@ client.forms.update_submission(
-Get a list of users for a site

Required scope | `users:read` +Get details of a selected Collection Item. + +Required scope | `CMS:read`
@@ -5310,13 +7328,14 @@ Get a list of users 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.users.list( - site_id="site_id", +client.collections.items.get_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5333,15 +7352,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 +**collection_id:** `str` — Unique identifier for a Collection
@@ -5349,7 +7360,7 @@ client.users.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**item_id:** `str` — Unique identifier for an Item
@@ -5357,13 +7368,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`) +**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.
@@ -5383,7 +7388,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-
client.users.get(...) +
client.collections.items.delete_item(...)
@@ -5395,7 +7400,9 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Get a User by ID

Required scope | `users:read` +Delete an item from a collection. + +Required scope | `CMS:write`
@@ -5410,14 +7417,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.delete_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5434,7 +7441,7 @@ client.users.get(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5442,7 +7449,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 +7477,7 @@ client.users.get(
-
client.users.delete(...) +
client.collections.items.update_item(...)
@@ -5474,7 +7489,9 @@ client.users.get(
-Delete a User by ID

Required scope | `users:write` +Update a selected Item in a Collection. + +Required scope | `CMS:write`
@@ -5489,14 +7506,20 @@ Delete a User by ID

Required scope | `users:write`
```python -from webflow.client import Webflow +from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.delete( - site_id="site_id", - user_id="user_id", +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", + ), ) ``` @@ -5513,7 +7536,7 @@ client.users.delete(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5521,7 +7544,7 @@ client.users.delete(
-**user_id:** `str` — Unique identifier for a User +**item_id:** `str` — Unique identifier for an Item
@@ -5529,79 +7552,39 @@ client.users.delete(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**id:** `typing.Optional[str]` — Unique identifier for the Item
-
-
- - - - -
-
client.users.update(...)
-#### 📝 Description - -
-
+**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
-Update a User by ID

Required scope | `users:write` - - -
-
+**last_published:** `typing.Optional[str]` — The date the item was last published +
-#### 🔌 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"], -) - -``` -
-
+**last_updated:** `typing.Optional[str]` — The date the item was last updated +
-#### ⚙️ Parameters -
-
-
- -**site_id:** `str` — Unique identifier for a Site +**created_on:** `typing.Optional[str]` — The date the item was created
@@ -5609,7 +7592,7 @@ client.users.update(
-**user_id:** `str` — Unique identifier for a User +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived
@@ -5617,7 +7600,7 @@ client.users.update(
-**data:** `typing.Optional[UsersUpdateRequestData]` +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft
@@ -5625,8 +7608,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. - +**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]`
@@ -5646,7 +7628,7 @@ client.users.update(
-
client.users.invite(...) +
client.collections.items.get_item_live(...)
@@ -5658,7 +7640,9 @@ client.users.update(
-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` +Get details of a selected Collection live Item. + +Required scope | `CMS:read`
@@ -5673,15 +7657,14 @@ Create and invite a user with an email address. The user will be sent and invite
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.invite( - site_id="site_id", - email="some.one@home.com", - access_groups=["webflowers"], +client.collections.items.get_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5698,7 +7681,7 @@ client.users.invite(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5706,7 +7689,7 @@ client.users.invite(
-**email:** `str` — Email address of user to send invite to +**item_id:** `str` — Unique identifier for an Item
@@ -5714,8 +7697,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. - +**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.
@@ -5735,8 +7717,7 @@ client.users.invite(
-## AccessGroups -
client.access_groups.list(...) +
client.collections.items.delete_item_live(...)
@@ -5748,7 +7729,11 @@ client.users.invite(
-Get a list of access groups for a site

Required scope | `users:read` +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`
@@ -5763,13 +7748,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.delete_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5786,15 +7772,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 +7780,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 +7788,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 +7808,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-## Products -
client.products.list(...) +
client.collections.items.update_item_live(...)
@@ -5846,9 +7820,9 @@ 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. +Update a selected live Item in a Collection. The updates for this Item will be published to the live site. -Required scope | `ecommerce:read` +Required scope | `CMS:write`
@@ -5863,13 +7837,20 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.list( - 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", + ), ) ``` @@ -5886,7 +7867,7 @@ client.products.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5894,7 +7875,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 +7883,7 @@ client.products.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -5910,77 +7891,31 @@ client.products.list(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item
-
-
- - - - -
- -
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` -
-
+**last_published:** `typing.Optional[str]` — The date the item was last published +
-#### 🔌 Usage - -
-
-
-```python -from webflow.client import Webflow - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.products.create( - site_id="site_id", -) - -``` -
-
+**last_updated:** `typing.Optional[str]` — The date the item was last updated +
-#### ⚙️ Parameters -
-
-
- -**site_id:** `str` — Unique identifier for a Site +**created_on:** `typing.Optional[str]` — The date the item was created
@@ -5988,7 +7923,7 @@ client.products.create(
-**publish_status:** `typing.Optional[PublishStatus]` +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived
@@ -5996,7 +7931,7 @@ client.products.create(
-**product:** `typing.Optional[Product]` +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft
@@ -6004,7 +7939,7 @@ client.products.create(
-**sku:** `typing.Optional[Sku]` +**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]`
@@ -6024,7 +7959,7 @@ client.products.create(
-
client.products.get(...) +
client.collections.items.publish_item(...)
@@ -6036,9 +7971,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 +7988,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 +8012,7 @@ client.products.get(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -6085,7 +8020,7 @@ client.products.get(
-**product_id:** `str` — Unique identifier for a Product +**item_ids:** `typing.Sequence[str]`
@@ -6105,7 +8040,8 @@ client.products.get(
-
client.products.update(...) +## Pages Scripts +
client.pages.scripts.get_custom_code(...)
@@ -6117,9 +8053,9 @@ 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 scripts applied to a page. -Required scope | `ecommerce:write` +Required scope | `custom_code:read`
@@ -6134,14 +8070,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 +8093,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 +8113,7 @@ client.products.update(
-
client.products.create_sku(...) +
client.pages.scripts.upsert_custom_code(...)
@@ -6222,11 +8125,13 @@ client.products.update(
-Create additional SKUs to cover every variant of your Product. The Default SKU already counts as one of the variants. +Apply scripts 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`. + + 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 | `ecommerce:write` +Required scope | `custom_code:write`
@@ -6241,16 +8146,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 +8182,7 @@ client.products.create_sku(
-**site_id:** `str` — Unique identifier for a Site +**page_id:** `str` — Unique identifier for a Page
@@ -6275,7 +8190,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 +8198,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 +8206,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 +8226,7 @@ client.products.create_sku(
-
client.products.update_sku(...) +
client.pages.scripts.delete_custom_code(...)
@@ -6323,9 +8238,11 @@ 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 a custom code block that the App created on a page. -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`
@@ -6340,17 +8257,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 +8280,7 @@ client.products.update_sku(
-**site_id:** `str` — Unique identifier for a Site +**page_id:** `str` — Unique identifier for a Page
@@ -6375,31 +8288,76 @@ 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. + +This endpoint requires an Enterprise workspace. + +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 +8377,7 @@ client.products.update_sku(
-## Orders -
client.orders.list(...) +
client.sites.redirects.create(...)
@@ -6432,9 +8389,13 @@ 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. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write`
@@ -6449,13 +8410,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 +8444,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 +8452,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 +8460,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 +8480,7 @@ client.orders.list(
-
client.orders.get(...) +
client.sites.redirects.delete(...)
@@ -6528,9 +8492,13 @@ client.orders.list(
-Retrieve a single product by its id. All of its SKUs will also be retrieved. +Remove a URL redirection rule from a site. -Required scope | `ecommerce:read` +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`
@@ -6545,14 +8513,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 +8545,7 @@ client.orders.get(
-**order_id:** `str` — Unique identifier for an Order +**redirect_id:** `str` — Unique identifier site rediect
@@ -6597,7 +8565,7 @@ client.orders.get(
-
client.orders.update(...) +
client.sites.redirects.update(...)
@@ -6609,9 +8577,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. +Update a URL redirection rule from a site. -Required scope | `ecommerce:write` +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write`
@@ -6626,14 +8596,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 +8631,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 +8639,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 +8647,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 +8655,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 +8675,8 @@ client.orders.update(
-
client.orders.update_fulfill(...) +## Sites Plans +
client.sites.plans.get_site_plan(...)
@@ -6722,9 +8688,11 @@ client.orders.update(
-Updates an order's status to fulfilled +Get site plan details for the specified Site. -Required scope | `ecommerce:write` +This endpoint requires an Enterprise workspace. + +Required scope | `sites:read`
@@ -6739,14 +8707,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 +8738,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 +8750,8 @@ client.orders.update_fulfill(
-
client.orders.update_unfulfill(...) +## Sites ActivityLogs +
client.sites.activity_logs.list(...)
@@ -6811,9 +8763,11 @@ client.orders.update_fulfill(
-Updates an order's status to unfulfilled +Retrieve Activity Logs for a specific Site. -Required scope | `ecommerce:write` +This endpoint requires an Enterprise workspace. + +Required scope: `site_activity:read`
@@ -6828,14 +8782,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 +8813,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 +8841,8 @@ client.orders.update_unfulfill(
-
client.orders.refund(...) +## Sites Scripts +
client.sites.scripts.get_custom_code(...)
@@ -6892,10 +8854,13 @@ 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 scripts applied to a site by the App. -Required scope | `ecommerce:write` + + 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`
@@ -6910,14 +8875,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 +8906,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 +8918,7 @@ client.orders.refund(
-## Inventory -
client.inventory.list(...) +
client.sites.scripts.upsert_custom_code(...)
@@ -6983,9 +8930,13 @@ client.orders.refund(
-List the current inventory levels for a particular SKU item. +Apply registered scripts to a site. -Required scope | `ecommerce:read` + + 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`
@@ -7000,14 +8951,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 +8987,7 @@ client.inventory.list(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -7032,7 +8995,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 +9031,7 @@ client.inventory.list(
-
client.inventory.update(...) +
client.sites.scripts.delete_custom_code(...)
@@ -7064,9 +9043,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. +Remove scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. -Required scope | `ecommerce:write` +Required scope | `custom_code:write`
@@ -7081,16 +9060,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 +9083,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 +9103,7 @@ client.inventory.update(
-## Ecommerce -
client.ecommerce.get_settings(...) +
client.sites.scripts.list_custom_code_blocks(...)
@@ -7172,9 +9115,15 @@ client.inventory.update(
-Retrieve ecommerce settings for a site. +Get a list of scripts that have been applied to a site and/or individual pages. -Required scope | `ecommerce:read` + + 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`
@@ -7189,13 +9138,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 +9169,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..22d950e 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -16,13 +16,32 @@ 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, + Conflict, ConflictErrorBody, CustomCodeBlock, CustomCodeBlockType, @@ -34,7 +53,7 @@ DuplicateUserEmail, EcommerceSettings, Error, - ErrorDetailsItem, + ErrorCode, Field, FieldType, ForbiddenErrorBody, @@ -47,18 +66,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 +100,6 @@ OrderTotalsExtrasItem, OrderTotalsExtrasItemType, Page, - PageDetails, - PageDetailsOpenGraph, - PageDetailsSeo, PageList, PageOpenGraph, PageSeo, @@ -93,6 +112,8 @@ ProductFieldDataEcProductType, ProductFieldDataTaxCategory, PublishStatus, + Redirect, + Redirects, RegisteredScriptList, ScriptApply, ScriptApplyList, @@ -100,9 +121,14 @@ Scripts, Site, SiteActivityLogItem, + SiteActivityLogItemEvent, SiteActivityLogItemResourceOperation, SiteActivityLogItemUser, SiteActivityLogResponse, + SiteDataCollectionType, + SitePlan, + SitePlanId, + SitePlanName, Sites, Sku, SkuFieldData, @@ -120,7 +146,10 @@ StripeCardBrand, StripeCardExpires, StripeDetails, + Text, TextNode, + TextNodeText, + TextNodeWrite, TriggerType, User, UserAccessGroupsItem, @@ -132,6 +161,7 @@ UserStatus, UsersNotEnabled, Webhook, + WebhookFilter, WebhookList, ) from .errors import ( @@ -145,17 +175,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 +204,7 @@ users, webhooks, ) +from .client import AsyncWebflow, Webflow from .environment import WebflowEnvironment from .version import __version__ @@ -183,19 +220,43 @@ "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", + "Conflict", "ConflictError", "ConflictErrorBody", "CustomCodeBlock", @@ -203,13 +264,12 @@ "CustomCodeHostedResponse", "CustomCodeInlineResponse", "Dom", - "DomWriteNodesItem", "Domain", "Domains", "DuplicateUserEmail", "EcommerceSettings", "Error", - "ErrorDetailsItem", + "ErrorCode", "Field", "FieldType", "ForbiddenError", @@ -223,21 +283,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 +322,7 @@ "OrdersListRequestStatus", "OrdersRefundRequestReason", "Page", - "PageDetails", - "PageDetailsOpenGraph", - "PageDetailsSeo", + "PageDomWriteNodesItem", "PageList", "PageOpenGraph", "PageSeo", @@ -275,6 +336,8 @@ "ProductFieldDataTaxCategory", "ProductsCreateSkuResponse", "PublishStatus", + "Redirect", + "Redirects", "RegisteredScriptList", "ScriptApply", "ScriptApplyList", @@ -282,10 +345,16 @@ "Scripts", "Site", "SiteActivityLogItem", + "SiteActivityLogItemEvent", "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "SiteDataCollectionType", + "SitePlan", + "SitePlanId", + "SitePlanName", "Sites", + "SitesPublishResponse", "Sku", "SkuFieldData", "SkuFieldDataCompareAtPrice", @@ -302,7 +371,10 @@ "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "Text", "TextNode", + "TextNodeText", + "TextNodeWrite", "TooManyRequestsError", "TriggerType", "UnauthorizedError", @@ -318,13 +390,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..148a193 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 of assets uploaded to a 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,18 @@ 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` + 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 ---------- @@ -94,13 +156,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 +174,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 +188,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 +265,9 @@ def create( def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset

Required scope | `assets:read` + Get details about an asset + + Required scope | `assets:read` Parameters ---------- @@ -167,31 +284,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 +366,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 +382,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 details of 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 +488,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 +576,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 +595,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 +682,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 +707,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 +798,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 +817,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 +902,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 of assets uploaded to a site + + Required scope | `assets:read` Parameters ---------- @@ -495,31 +921,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 +1017,18 @@ 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` + 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 ---------- @@ -543,13 +1036,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 +1054,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 +1153,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 details about an asset + + Required scope | `assets:read` Parameters ---------- @@ -616,31 +1172,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 +1262,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 +1278,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 details of 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 +1392,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 +1490,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 +1509,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 +1604,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 +1629,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 +1728,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 +1747,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..5fb47b3 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 ---------- @@ -61,10 +74,10 @@ def list_items( 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 sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -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 + 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 - 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,223 @@ 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 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 + + 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 +601,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 all published items in a collection. + + Required scope | `CMS:read` Parameters ---------- @@ -263,10 +620,10 @@ def list_items_live( 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 sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] Sort results by the provided value @@ -284,13 +641,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 +666,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 +732,150 @@ 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 item(s) in a collection that will be immediately 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( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + 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. + + Using this endpoint to delete published item(s) will unpublish the item(s) from the live site and set the item(s) `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 - 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 +886,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,30 +913,386 @@ 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 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 + + 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 == 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 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. + + + - 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 + + 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 ---------- @@ -564,35 +1315,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 +1406,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. + + Required scope | `CMS:write` Parameters ---------- @@ -629,35 +1430,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 +1511,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 +1534,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 +1555,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 +1567,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 +1594,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 +1674,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 +1699,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 +1790,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 +1816,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 +1897,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 +1920,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 +1941,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 +1953,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 +1980,82 @@ 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 == 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) @@ -1030,9 +2067,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 +2085,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 +2205,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 ---------- @@ -1121,10 +2224,10 @@ async def list_items( 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 sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -1142,14 +2245,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 +2278,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 +2344,1160 @@ 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. + + 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 - 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 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 + + 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 all published items in 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 + + limit : typing.Optional[float] + 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 + + 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 item(s) in a collection that will be immediately published to the live site. - last_updated : typing.Optional[str] - The date the item was last updated - created_on : typing.Optional[str] - The date the item was created + To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) - 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 + Required scope | `CMS:write` - field_data : typing.Optional[CollectionItemFieldData] + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + 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( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + 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. + + Using this endpoint to delete published item(s) will unpublish the item(s) from the live site and set the item(s) `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 - 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 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 - 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 == 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) 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. + + + - 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 - 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 +3512,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 +3537,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 +3636,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. + + Required scope | `CMS:write` Parameters ---------- @@ -1689,35 +3660,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 +3749,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 +3772,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 +3793,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 +3805,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 +3840,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 +3920,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 +3945,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 +4044,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 +4070,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 +4159,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 +4182,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 +4203,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 +4215,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 +4250,82 @@ 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 == 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) @@ -2090,9 +4337,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 +4355,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..15687aa --- /dev/null +++ b/src/webflow/resources/components/client.py @@ -0,0 +1,1474 @@ +# 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 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. 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 default property values of a component definition in a specificed locale. + + Before making updates, 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. + + 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. 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 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. 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 default property values of a component definition in a specificed locale. + + Before making updates, 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. + + 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. 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..59e4477 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,204 @@ 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, + ) + 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) + + 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)}", method="GET", request_options=request_options + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _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(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( + 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) @@ -258,18 +630,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 +656,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 +775,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 +800,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 +912,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 +931,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 +1061,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 +1165,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 +1184,220 @@ 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, ) + 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) + + 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)}", method="GET", request_options=request_options + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _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(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( + 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) @@ -555,18 +1407,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 +1433,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..4707b46 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,26 @@ 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 content from a static page. This includes text nodes, image nodes, and component instances with [property overrides](https://help.webflow.com/hc/en-us/articles/33961219350547-Component-properties#how-to-modify-property-values-on-component-instances). + + To retrieve the static content of a component instance, use the [Get Component Content](/data/reference/pages-and-components/components/get-content) endpoint. + + If you do not include a `localeId` 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 +542,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 +640,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 +678,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 +719,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 +817,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 +851,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 +947,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 +968,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 +1067,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 +1079,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 +1133,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 +1145,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 +1224,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 +1304,26 @@ 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 content from a static page. This includes text nodes, image nodes, and component instances with [property overrides](https://help.webflow.com/hc/en-us/articles/33961219350547-Component-properties#how-to-modify-property-values-on-component-instances). + + To retrieve the static content of a component instance, use the [Get Component Content](/data/reference/pages-and-components/components/get-content) endpoint. + + If you do not include a `localeId` 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 +1342,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 +1448,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 +1486,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..09dc686 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,9 @@ 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 scripts applied to a page. + + Required scope | `custom_code:read` Parameters ---------- @@ -45,31 +50,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 +138,13 @@ 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` + Apply scripts to a page. + + + 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 ---------- @@ -111,24 +170,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 +195,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 +281,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

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 a custom code block that the App created on a page. + + 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 +301,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 +382,9 @@ 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 scripts applied to a page. + + Required scope | `custom_code:read` Parameters ---------- @@ -233,31 +401,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 +497,13 @@ 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` + Apply scripts to a page. + + + 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 ---------- @@ -299,49 +529,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 +650,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

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 a custom code block that the App created on a page. + + 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 +670,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..31cccd6 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,21 @@ # 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): + required: typing.Optional[typing.Optional[typing.Any]] = None 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..2a1c69d 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,13 @@ 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` + 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 ---------- @@ -44,31 +51,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 +141,13 @@ 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` + 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 ---------- @@ -118,13 +179,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 +202,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 +284,13 @@ 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` + 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 ---------- @@ -206,13 +322,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 +344,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 +423,13 @@ 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` + 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 ---------- @@ -275,31 +446,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 +544,13 @@ 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` + 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 ---------- @@ -349,18 +582,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 +613,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 +695,13 @@ 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` + 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 ---------- @@ -437,17 +733,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 +763,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..1bf398c 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,154 @@ 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 +196,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 +254,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 +273,315 @@ 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 + f"sites/{jsonable_encoder(site_id)}", + method="GET", + request_options=request_options, ) 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 == 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(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="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) + + 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 +589,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 +608,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 +693,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 +707,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 +717,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 +812,234 @@ 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 +1047,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 +1066,339 @@ 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", ) - await client.sites.get( - site_id="site_id", + + + 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", + ) + + + 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 +1408,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 +1427,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 +1520,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 +1534,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 +1544,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..45286b9 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,11 @@ 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. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` Parameters ---------- @@ -51,32 +56,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 +142,11 @@ 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. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` Parameters ---------- @@ -119,32 +169,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..85cd891 --- /dev/null +++ b/src/webflow/resources/sites/resources/plans/client.py @@ -0,0 +1,237 @@ +# 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. + + 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 + ------- + 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. + + 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 + ------- + 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..8a825c9 --- /dev/null +++ b/src/webflow/resources/sites/resources/redirects/client.py @@ -0,0 +1,1009 @@ +# 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. + + 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 + ------- + 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. + + 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 + ------- + 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. + + 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 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. + + 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 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. + + 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 + ------- + 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. + + 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 + ------- + 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. + + 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 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. + + 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 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..8577f02 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,13 @@ 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 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 ---------- @@ -46,31 +54,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 +142,13 @@ 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` + Apply registered scripts 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 ---------- @@ -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,9 @@ 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` + Remove scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + Required scope | `custom_code:write` Parameters ---------- @@ -178,31 +293,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 +374,15 @@ 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 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 ---------- @@ -240,34 +405,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 +496,13 @@ 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 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 ---------- @@ -299,31 +519,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 +615,13 @@ 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` + Apply registered scripts 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 ---------- @@ -365,49 +647,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 +758,9 @@ 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` + Remove scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + 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,15 @@ 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 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 ---------- @@ -495,34 +896,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..c799f7c 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -15,13 +15,34 @@ 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 import Conflict from .conflict_error_body import ConflictErrorBody from .custom_code_block import CustomCodeBlock from .custom_code_block_type import CustomCodeBlockType @@ -33,7 +54,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 +67,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 +98,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 +110,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 +119,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 +144,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 +159,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 +178,32 @@ "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", + "Conflict", "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", @@ -167,7 +215,7 @@ "DuplicateUserEmail", "EcommerceSettings", "Error", - "ErrorDetailsItem", + "ErrorCode", "Field", "FieldType", "ForbiddenErrorBody", @@ -180,18 +228,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 +262,6 @@ "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", "Page", - "PageDetails", - "PageDetailsOpenGraph", - "PageDetailsSeo", "PageList", "PageOpenGraph", "PageSeo", @@ -226,6 +274,8 @@ "ProductFieldDataEcProductType", "ProductFieldDataTaxCategory", "PublishStatus", + "Redirect", + "Redirects", "RegisteredScriptList", "ScriptApply", "ScriptApplyList", @@ -233,9 +283,14 @@ "Scripts", "Site", "SiteActivityLogItem", + "SiteActivityLogItemEvent", "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "SiteDataCollectionType", + "SitePlan", + "SitePlanId", + "SitePlanName", "Sites", "Sku", "SkuFieldData", @@ -253,7 +308,10 @@ "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "Text", "TextNode", + "TextNodeText", + "TextNodeWrite", "TriggerType", "User", "UserAccessGroupsItem", @@ -265,5 +323,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..d2212b0 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -1,77 +1,82 @@ # 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 datetime as dt 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 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + +class Asset(UniversalBaseModel): + """ + Asset details + """ -class Asset(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: str = pydantic.Field() """ Unique identifier for this asset """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + content_type: typing_extensions.Annotated[str, FieldMetadata(alias="contentType")] = pydantic.Field() """ - Original file name at the time of upload + File format type """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + size: int = pydantic.Field() """ - 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[str, FieldMetadata(alias="siteId")] = pydantic.Field() """ - 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[str, FieldMetadata(alias="hostedUrl")] = pydantic.Field() """ - 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[str, FieldMetadata(alias="originalFileName")] = pydantic.Field() """ - 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[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ - 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[dt.datetime, FieldMetadata(alias="lastUpdated")] = pydantic.Field() """ Date the asset metadata was last updated """ - hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + created_on: typing_extensions.Annotated[dt.datetime, FieldMetadata(alias="createdOn")] = pydantic.Field() """ - Link to the asset + Date the asset metadata was created """ - variants: typing.Optional[typing.List[AssetVariant]] = 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) + 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. + """ - 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} + alt_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="altText")] = pydantic.Field( + default=None + ) + """ + The visual description of the asset + """ - 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..bc023dc 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.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 typing_extensions +from ..core.serialization import FieldMetadata +import pydantic import typing +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(UniversalBaseModel): + """ + Asset variant details + """ -class AssetVariant(pydantic_v1.BaseModel): - hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + hosted_url: typing_extensions.Annotated[str, FieldMetadata(alias="hostedUrl")] = pydantic.Field() """ 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[str, FieldMetadata(alias="originalFileName")] = pydantic.Field() """ Original file name of the variant """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Display name of the variant """ - format: typing.Optional[str] = pydantic_v1.Field(default=None) + format: str = pydantic.Field() """ format of the variant """ - width: typing.Optional[int] = pydantic_v1.Field(default=None) + width: int = pydantic.Field() """ Width in pixels """ - height: typing.Optional[int] = pydantic_v1.Field(default=None) + height: int = pydantic.Field() """ Height in pixels """ - quality: typing.Optional[int] = pydantic_v1.Field(default=None) + quality: int = pydantic.Field() """ 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..bd5f8ea 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -1,34 +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 .asset import Asset +from .pagination import Pagination +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 + 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/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..561a535 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -1,69 +1,64 @@ # 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 +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[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Name given to the Collection """ - singular_name: typing.Optional[str] = pydantic_v1.Field(alias="singularName", 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”) """ - 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..ab8396d 100644 --- a/src/webflow/types/collection_item.py +++ b/src/webflow/types/collection_item.py @@ -1,71 +1,71 @@ # 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[str, FieldMetadata(alias="lastPublished")] = pydantic.Field() """ The date the item was last published """ - last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[str, FieldMetadata(alias="lastUpdated")] = pydantic.Field() """ The date the item was last updated """ - created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[str, FieldMetadata(alias="createdOn")] = pydantic.Field() """ 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..6735289 --- /dev/null +++ b/src/webflow/types/component_node.py @@ -0,0 +1,41 @@ +# 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 .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: str = pydantic.Field() + """ + 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 + """ + + property_overrides: typing_extensions.Annotated[ + typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + ] = pydantic.Field() + """ + 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/error_details_item.py b/src/webflow/types/conflict.py similarity index 54% rename from src/webflow/types/error_details_item.py rename to src/webflow/types/conflict.py index 693e235..30b9809 100644 --- a/src/webflow/types/error_details_item.py +++ b/src/webflow/types/conflict.py @@ -2,4 +2,4 @@ import typing -ErrorDetailsItem = typing.Union[str, typing.Dict[str, 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 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..c4e7eac 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node.py @@ -1,36 +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 +from .image_node_image import ImageNodeImage import typing +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) + id: str = pydantic.Field() + """ + Node UUID + """ - 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) + image: ImageNodeImage = pydantic.Field() + """ + The image details of the node + """ - 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} + 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..f8d9379 --- /dev/null +++ b/src/webflow/types/image_node_image.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 typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +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 + + 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/invalid_scopes.py b/src/webflow/types/invalid_scopes.py new file mode 100644 index 0000000..90edaa0 --- /dev/null +++ b/src/webflow/types/invalid_scopes.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +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..462a30b 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: str + text: TextNodeText + 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: str + image: ImageNodeImage + 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: str + component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] + property_overrides: typing_extensions.Annotated[ + 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 + 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..6b8d4ee 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 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 Pagination(pydantic_v1.BaseModel): +class Pagination(UniversalBaseModel): """ Pagination object """ - limit: typing.Optional[float] = pydantic_v1.Field(default=None) + limit: float = pydantic.Field() """ The limit used for pagination """ - offset: typing.Optional[float] = pydantic_v1.Field(default=None) + offset: float = pydantic.Field() """ The offset used for pagination """ - total: typing.Optional[float] = pydantic_v1.Field(default=None) + total: float = pydantic.Field() """ 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..dc3b9fa 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -1,77 +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_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") + ] = 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") + ] = 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 + """ + + 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..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 @@ -1,46 +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 - -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(UniversalBaseModel): + """ + [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU + """ -class SkuFieldDataEcSkuSubscriptionPlan(pydantic_v1.BaseModel): - interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic_v1.Field(default=None) + 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..913d5d1 --- /dev/null +++ b/src/webflow/types/text.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 Text(UniversalBaseModel): + """ + The text content of the node + """ + + 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..aa15d4b 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -1,34 +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 +from .text_node_text import TextNodeText import typing +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 + id: str = pydantic.Field() + """ + Node UUID + """ - 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) + text: TextNodeText = pydantic.Field() + """ + The text content of the node + """ - 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} + 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..5add2f0 --- /dev/null +++ b/src/webflow/types/text_node_text.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 TextNodeText(UniversalBaseModel): + """ + The text content of the node + """ + + 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..1740272 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 .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class WebhookList(pydantic_v1.BaseModel): - pagination: typing.Optional[Pagination] = None +class WebhookList(UniversalBaseModel): webhooks: typing.Optional[typing.List[Webhook]] = 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/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..de4eb75 --- /dev/null +++ b/tests/collections/test_items.py @@ -0,0 +1,816 @@ +# 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( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + 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( + last_published="2023-03-17T18:47:35.560Z", + last_updated="2023-03-17T18:47:35.560Z", + created_on="2023-03-17T18:47:35.560Z", + 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..5f9da41 --- /dev/null +++ b/tests/test_assets.py @@ -0,0 +1,409 @@ +# 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": None, "offset": None, "total": 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": "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": 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..7dc07bb --- /dev/null +++ b/tests/test_forms.py @@ -0,0 +1,279 @@ +# 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_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 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..4583a52 --- /dev/null +++ b/tests/test_products.py @@ -0,0 +1,467 @@ +# 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 = { + "required": {"key": "value"}, + "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 = { + "required": 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_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..cbd626b --- /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 = { + "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": None, "offset": None, "total": None}, + } + 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