From d22304860170e146e5c85688e95d1022fd29e760 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 13:53:38 +0000 Subject: [PATCH] SDK regeneration --- .github/workflows/ci.yml | 8 +- .mock/definition/__package__.yml | 2105 ++++++++++++-- .mock/definition/accessGroups.yml | 1 + .mock/definition/api.yml | 11 +- .mock/definition/assets.yml | 135 +- .mock/definition/collections.yml | 187 +- .mock/definition/collections/fields.yml | 119 +- .mock/definition/collections/items.yml | 557 ++-- .mock/definition/comments.yml | 40 + .mock/definition/components.yml | 164 +- .mock/definition/ecommerce.yml | 1 + .mock/definition/forms.yml | 152 +- .mock/definition/inventory.yml | 54 +- .mock/definition/items.yml | 111 + .mock/definition/orders.yml | 470 ++- .mock/definition/pages.yml | 245 +- .mock/definition/pages/scripts.yml | 61 +- .mock/definition/products.yml | 247 +- .mock/definition/scripts.yml | 71 +- .mock/definition/sites.yml | 104 +- .mock/definition/sites/activityLogs.yml | 17 +- .mock/definition/sites/comments.yml | 323 +++ .mock/definition/sites/plans.yml | 8 +- .mock/definition/sites/redirects.yml | 41 +- .mock/definition/sites/robotsTxt.yml | 221 ++ .mock/definition/sites/scripts.yml | 58 +- .mock/definition/sites/wellKnown.yml | 114 + .mock/definition/token.yml | 2 + .mock/definition/users.yml | 244 +- .mock/definition/webhooks.yml | 15 +- .mock/definition/workspaces/auditLogs.yml | 119 + .mock/fern.config.json | 2 +- poetry.lock | 67 +- pyproject.toml | 2 +- reference.md | 2569 +++++++++++++---- src/webflow/__init__.py | 274 +- src/webflow/client.py | 35 +- src/webflow/core/client_wrapper.py | 29 +- src/webflow/environment.py | 22 +- src/webflow/resources/__init__.py | 36 +- src/webflow/resources/access_groups/client.py | 2 + src/webflow/resources/assets/client.py | 50 +- src/webflow/resources/collections/__init__.py | 20 +- src/webflow/resources/collections/client.py | 108 +- .../collections/resources/__init__.py | 20 +- .../collections/resources/fields/__init__.py | 3 - .../collections/resources/fields/client.py | 152 +- .../resources/fields/types/__init__.py | 5 - .../collections/resources/items/__init__.py | 18 +- .../collections/resources/items/client.py | 446 ++- .../resources/items/types/__init__.py | 18 +- .../resources/items/types/item_i_ds.py | 25 + .../items/types/item_i_ds_with_locales.py | 24 + ...=> items_create_item_live_request_body.py} | 2 +- ...t.py => items_create_item_request_body.py} | 2 +- ...ms_delete_items_live_request_items_item.py | 6 +- .../items/types/items_publish_item_request.py | 7 + ...s_publish_item_request_items_items_item.py | 31 + .../types/items_update_items_response.py | 7 + src/webflow/resources/components/client.py | 168 +- .../types/component_dom_write_nodes_item.py | 10 +- src/webflow/resources/ecommerce/client.py | 2 + src/webflow/resources/forms/client.py | 540 ++++ src/webflow/resources/inventory/__init__.py | 4 +- src/webflow/resources/inventory/client.py | 72 +- .../resources/inventory/types/__init__.py | 3 +- .../types/ecomm_inventory_changed_payload.py | 25 + src/webflow/resources/orders/client.py | 12 + src/webflow/resources/pages/__init__.py | 10 +- src/webflow/resources/pages/client.py | 332 +-- .../pages/resources/scripts/client.py | 62 +- src/webflow/resources/pages/types/__init__.py | 4 +- .../pages/types/page_dom_write_nodes_item.py | 10 +- .../types/page_metadata_write_open_graph.py | 47 + .../pages/types/page_metadata_write_seo.py | 31 + src/webflow/resources/products/__init__.py | 4 +- src/webflow/resources/products/client.py | 342 ++- .../resources/products/types/__init__.py | 4 +- .../types/product_sku_create_product.py | 22 + .../products/types/product_sku_create_sku.py | 22 + .../types/products_create_sku_response.py | 2 +- src/webflow/resources/scripts/client.py | 70 +- src/webflow/resources/sites/__init__.py | 35 +- src/webflow/resources/sites/client.py | 62 +- .../resources/sites/resources/__init__.py | 28 +- .../sites/resources/activity_logs/client.py | 14 +- .../sites/resources/comments/__init__.py | 19 + .../sites/resources/comments/client.py | 901 ++++++ .../resources/comments/types/__init__.py | 17 + ...ents_get_comment_thread_request_sort_by.py | 5 + ...s_get_comment_thread_request_sort_order.py | 5 + ...ts_list_comment_replies_request_sort_by.py | 5 + ...list_comment_replies_request_sort_order.py | 5 + ...ts_list_comment_threads_request_sort_by.py | 5 + ...list_comment_threads_request_sort_order.py | 5 + .../resources/sites/resources/plans/client.py | 6 + .../sites/resources/redirects/client.py | 44 +- .../sites/resources/robots_txt/__init__.py | 2 + .../sites/resources/robots_txt/client.py | 1050 +++++++ .../sites/resources/scripts/client.py | 68 +- .../sites/resources/well_known/__init__.py | 5 + .../sites/resources/well_known/client.py | 532 ++++ .../resources/well_known/types/__init__.py | 5 + .../types/well_known_file_content_type.py | 5 + src/webflow/resources/token/client.py | 4 + src/webflow/resources/users/__init__.py | 26 +- src/webflow/resources/users/client.py | 184 +- src/webflow/resources/users/types/__init__.py | 23 +- .../users/types/user_account_added_payload.py | 25 + .../user_account_added_payload_payload.py | 76 + ...ser_account_added_payload_payload_data.py} | 26 +- .../types/user_account_deleted_payload.py | 25 + .../user_account_deleted_payload_payload.py | 76 + ...er_account_deleted_payload_payload_data.py | 32 + .../types/user_account_updated_payload.py | 25 + .../user_account_updated_payload_payload.py | 76 + ...er_account_updated_payload_payload_data.py | 32 + src/webflow/resources/webhooks/client.py | 8 + src/webflow/resources/workspaces/__init__.py | 13 + src/webflow/resources/workspaces/client.py | 18 + .../workspaces/resources/__init__.py | 10 + .../resources/audit_logs/__init__.py | 5 + .../workspaces/resources/audit_logs/client.py | 332 +++ .../resources/audit_logs/types/__init__.py | 6 + ...workspace_audit_logs_request_event_type.py | 8 + ...workspace_audit_logs_request_sort_order.py | 5 + src/webflow/types/__init__.py | 269 +- src/webflow/types/application.py | 38 +- src/webflow/types/asset.py | 14 +- src/webflow/types/asset_variant.py | 24 +- src/webflow/types/assets.py | 2 + src/webflow/types/bulk_collection_item.py | 4 +- src/webflow/types/collection.py | 10 +- src/webflow/types/collection_item_changed.py | 33 + src/webflow/types/collection_item_created.py | 33 + .../types/collection_item_published.py | 29 + src/webflow/types/collection_item_removed.py | 32 + .../types/collection_item_removed_payload.py | 69 + ...lection_item_removed_payload_field_data.py | 20 + .../types/collection_item_unpublished.py | 32 + .../collection_item_unpublished_payload.py | 69 + ...ion_item_unpublished_payload_field_data.py | 20 + src/webflow/types/comment.py | 33 + src/webflow/types/comment_payload.py | 114 + src/webflow/types/comment_payload_author.py | 34 + .../comment_payload_mentioned_users_item.py | 34 + src/webflow/types/comment_reply.py | 89 + src/webflow/types/comment_reply_author.py | 32 + src/webflow/types/comment_reply_list.py | 26 + .../types/comment_reply_list_pagination.py | 32 + .../comment_reply_mentioned_users_item.py | 32 + src/webflow/types/comment_thread.py | 92 + src/webflow/types/comment_thread_author.py | 34 + src/webflow/types/comment_thread_list.py | 26 + .../types/comment_thread_list_pagination.py | 32 + .../comment_thread_mentioned_users_item.py | 34 + src/webflow/types/component_dom.py | 2 +- ...errides_write.py => component_instance.py} | 2 +- ...omponent_node.py => component_node_dom.py} | 18 +- src/webflow/types/conflict.py | 5 + src/webflow/types/custom_role.py | 33 + .../types/custom_role_audit_log_item.py | 26 + ...stom_role_audit_log_item_event_sub_type.py | 7 + src/webflow/types/dom.py | 14 + src/webflow/types/field.py | 6 + src/webflow/types/field_create.py | 8 + src/webflow/types/field_type.py | 6 +- src/webflow/types/field_validations.py | 28 + ...field_validations_additional_properties.py | 10 + ...tional_properties_additional_properties.py | 23 + src/webflow/types/form_submission_trigger.py | 36 + .../types/form_submission_trigger_payload.py | 74 + ..._submission_trigger_payload_schema_item.py | 41 + ..._trigger_payload_schema_item_field_type.py | 8 + .../{image_node.py => image_node_dom.py} | 12 +- src/webflow/types/image_node_image.py | 4 + ..._list_items_live_request_last_published.py | 28 + ...items_list_items_request_last_published.py | 28 + src/webflow/types/metadata.py | 27 + src/webflow/types/metadata_options_item.py | 31 + src/webflow/types/new_order.py | 33 + src/webflow/types/node.py | 102 +- src/webflow/types/option_field.py | 58 + src/webflow/types/order.py | 6 +- src/webflow/types/order_billing_address.py | 78 + .../types/order_billing_address_japan_type.py | 5 + .../types/order_billing_address_type.py | 5 + src/webflow/types/order_shipping_address.py | 78 + .../order_shipping_address_japan_type.py | 5 + .../types/order_shipping_address_type.py | 5 + src/webflow/types/page.py | 8 +- src/webflow/types/page_created_webhook.py | 36 + .../types/page_created_webhook_payload.py | 30 + src/webflow/types/page_deleted_webhook.py | 36 + .../types/page_deleted_webhook_payload.py | 30 + .../types/page_metadata_updated_webhook.py | 36 + .../page_metadata_updated_webhook_payload.py | 30 + src/webflow/types/payload.py | 67 + src/webflow/types/payload_field_data.py | 20 + src/webflow/types/product_field_data.py | 4 +- src/webflow/types/reference_field.py | 62 + src/webflow/types/reference_field_metadata.py | 28 + src/webflow/types/reference_field_type.py | 5 + src/webflow/types/registered_script_list.py | 2 + src/webflow/types/robots.py | 32 + src/webflow/types/robots_rules_item.py | 34 + .../{text_node_write.py => search_button.py} | 8 +- src/webflow/types/search_button_node_dom.py | 36 + src/webflow/types/select.py | 34 + src/webflow/types/select_node_choices_item.py | 27 + src/webflow/types/select_node_dom.py | 37 + .../types/select_node_write_choices_item.py | 27 + .../types/single_locale_created_payload.py | 57 + ...ingle_locale_created_payload_field_data.py | 20 + src/webflow/types/site_membership.py | 49 + .../types/site_membership_audit_log_item.py | 26 + ...embership_audit_log_item_event_sub_type.py | 7 + src/webflow/types/site_publish.py | 36 + src/webflow/types/site_publish_payload.py | 50 + src/webflow/types/sku_field_data.py | 30 +- ...sku_field_data_ec_sku_subscription_plan.py | 4 + src/webflow/types/sku_field_data_price.py | 5 + src/webflow/types/static_field.py | 56 + .../static_field_type.py} | 5 +- src/webflow/types/submit_button.py | 40 + src/webflow/types/submit_button_node_dom.py | 43 + src/webflow/types/text.py | 4 + src/webflow/types/text_input.py | 33 + src/webflow/types/text_input_node_dom.py | 36 + src/webflow/types/text_node.py | 14 +- src/webflow/types/text_node_dom.py | 37 + src/webflow/types/text_node_text.py | 4 + src/webflow/types/trigger_type.py | 2 + src/webflow/types/updated_order.py | 33 + src/webflow/types/user.py | 6 +- src/webflow/types/user_access.py | 33 + .../types/user_access_audit_log_item.py | 26 + ...er_access_audit_log_item_event_sub_type.py | 5 + src/webflow/types/webhook_list.py | 4 +- src/webflow/types/workspace_audit_log_item.py | 141 + .../types/workspace_audit_log_item_actor.py | 20 + ...log_item_payload_site_membership_method.py | 7 + ...t_log_item_payload_site_membership_site.py | 20 + ...tem_payload_site_membership_target_user.py | 20 + ..._item_payload_site_membership_user_type.py | 7 + ...dit_log_item_payload_user_access_method.py | 7 + ...tem_payload_workspace_invitation_method.py | 7 + ...ayload_workspace_invitation_target_user.py | 20 + ..._payload_workspace_invitation_user_type.py | 7 + ...tem_payload_workspace_membership_method.py | 7 + ...ayload_workspace_membership_target_user.py | 20 + ..._payload_workspace_membership_user_type.py | 7 + .../workspace_audit_log_item_workspace.py | 20 + .../types/workspace_audit_log_response.py | 22 + src/webflow/types/workspace_invitation.py | 49 + .../workspace_invitation_audit_log_item.py | 26 + ...nvitation_audit_log_item_event_sub_type.py | 7 + src/webflow/types/workspace_membership.py | 49 + .../workspace_membership_audit_log_item.py | 26 + ...embership_audit_log_item_event_sub_type.py | 7 + tests/collections/test_fields.py | 35 +- tests/collections/test_items.py | 174 +- tests/conftest.py | 19 +- tests/sites/test_activity_logs.py | 6 - tests/sites/test_comments.py | 212 ++ tests/sites/test_robots_txt.py | 145 + tests/sites/test_scripts.py | 2 - tests/sites/test_well_known.py | 32 + tests/test_assets.py | 129 +- tests/test_collections.py | 399 ++- tests/test_components.py | 129 +- tests/test_forms.py | 87 +- tests/test_inventory.py | 8 +- tests/test_orders.py | 178 +- tests/test_pages.py | 172 +- tests/test_products.py | 361 ++- tests/test_scripts.py | 12 +- tests/test_sites.py | 81 +- tests/test_token.py | 2 +- tests/test_users.py | 27 +- tests/test_webhooks.py | 8 +- tests/workspaces/__init__.py | 2 + tests/workspaces/test_audit_logs.py | 53 + 283 files changed, 18752 insertions(+), 3148 deletions(-) create mode 100644 .mock/definition/comments.yml create mode 100644 .mock/definition/items.yml create mode 100644 .mock/definition/sites/comments.yml create mode 100644 .mock/definition/sites/robotsTxt.yml create mode 100644 .mock/definition/sites/wellKnown.yml create mode 100644 .mock/definition/workspaces/auditLogs.yml delete mode 100644 src/webflow/resources/collections/resources/fields/types/__init__.py create mode 100644 src/webflow/resources/collections/resources/items/types/item_i_ds.py create mode 100644 src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py rename src/webflow/resources/collections/resources/items/types/{items_create_item_live_request.py => items_create_item_live_request_body.py} (69%) rename src/webflow/resources/collections/resources/items/types/{items_create_item_request.py => items_create_item_request_body.py} (70%) create mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_request.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_update_items_response.py create mode 100644 src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py create mode 100644 src/webflow/resources/pages/types/page_metadata_write_open_graph.py create mode 100644 src/webflow/resources/pages/types/page_metadata_write_seo.py create mode 100644 src/webflow/resources/products/types/product_sku_create_product.py create mode 100644 src/webflow/resources/products/types/product_sku_create_sku.py create mode 100644 src/webflow/resources/sites/resources/comments/__init__.py create mode 100644 src/webflow/resources/sites/resources/comments/client.py create mode 100644 src/webflow/resources/sites/resources/comments/types/__init__.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py create mode 100644 src/webflow/resources/sites/resources/robots_txt/__init__.py create mode 100644 src/webflow/resources/sites/resources/robots_txt/client.py create mode 100644 src/webflow/resources/sites/resources/well_known/__init__.py create mode 100644 src/webflow/resources/sites/resources/well_known/client.py create mode 100644 src/webflow/resources/sites/resources/well_known/types/__init__.py create mode 100644 src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py create mode 100644 src/webflow/resources/users/types/user_account_added_payload.py create mode 100644 src/webflow/resources/users/types/user_account_added_payload_payload.py rename src/webflow/resources/users/types/{users_update_request_data.py => user_account_added_payload_payload_data.py} (59%) create mode 100644 src/webflow/resources/users/types/user_account_deleted_payload.py create mode 100644 src/webflow/resources/users/types/user_account_deleted_payload_payload.py create mode 100644 src/webflow/resources/users/types/user_account_deleted_payload_payload_data.py create mode 100644 src/webflow/resources/users/types/user_account_updated_payload.py create mode 100644 src/webflow/resources/users/types/user_account_updated_payload_payload.py create mode 100644 src/webflow/resources/users/types/user_account_updated_payload_payload_data.py create mode 100644 src/webflow/resources/workspaces/__init__.py create mode 100644 src/webflow/resources/workspaces/client.py create mode 100644 src/webflow/resources/workspaces/resources/__init__.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/__init__.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/client.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py create mode 100644 src/webflow/types/collection_item_changed.py create mode 100644 src/webflow/types/collection_item_created.py create mode 100644 src/webflow/types/collection_item_published.py create mode 100644 src/webflow/types/collection_item_removed.py create mode 100644 src/webflow/types/collection_item_removed_payload.py create mode 100644 src/webflow/types/collection_item_removed_payload_field_data.py create mode 100644 src/webflow/types/collection_item_unpublished.py create mode 100644 src/webflow/types/collection_item_unpublished_payload.py create mode 100644 src/webflow/types/collection_item_unpublished_payload_field_data.py create mode 100644 src/webflow/types/comment.py create mode 100644 src/webflow/types/comment_payload.py create mode 100644 src/webflow/types/comment_payload_author.py create mode 100644 src/webflow/types/comment_payload_mentioned_users_item.py create mode 100644 src/webflow/types/comment_reply.py create mode 100644 src/webflow/types/comment_reply_author.py create mode 100644 src/webflow/types/comment_reply_list.py create mode 100644 src/webflow/types/comment_reply_list_pagination.py create mode 100644 src/webflow/types/comment_reply_mentioned_users_item.py create mode 100644 src/webflow/types/comment_thread.py create mode 100644 src/webflow/types/comment_thread_author.py create mode 100644 src/webflow/types/comment_thread_list.py create mode 100644 src/webflow/types/comment_thread_list_pagination.py create mode 100644 src/webflow/types/comment_thread_mentioned_users_item.py rename src/webflow/types/{component_instance_node_property_overrides_write.py => component_instance.py} (94%) rename src/webflow/types/{component_node.py => component_node_dom.py} (69%) create mode 100644 src/webflow/types/conflict.py create mode 100644 src/webflow/types/custom_role.py create mode 100644 src/webflow/types/custom_role_audit_log_item.py create mode 100644 src/webflow/types/custom_role_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/field_create.py create mode 100644 src/webflow/types/field_validations.py create mode 100644 src/webflow/types/field_validations_additional_properties.py create mode 100644 src/webflow/types/field_validations_additional_properties_additional_properties.py create mode 100644 src/webflow/types/form_submission_trigger.py create mode 100644 src/webflow/types/form_submission_trigger_payload.py create mode 100644 src/webflow/types/form_submission_trigger_payload_schema_item.py create mode 100644 src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py rename src/webflow/types/{image_node.py => image_node_dom.py} (85%) create mode 100644 src/webflow/types/items_list_items_live_request_last_published.py create mode 100644 src/webflow/types/items_list_items_request_last_published.py create mode 100644 src/webflow/types/metadata.py create mode 100644 src/webflow/types/metadata_options_item.py create mode 100644 src/webflow/types/new_order.py create mode 100644 src/webflow/types/option_field.py create mode 100644 src/webflow/types/order_billing_address.py create mode 100644 src/webflow/types/order_billing_address_japan_type.py create mode 100644 src/webflow/types/order_billing_address_type.py create mode 100644 src/webflow/types/order_shipping_address.py create mode 100644 src/webflow/types/order_shipping_address_japan_type.py create mode 100644 src/webflow/types/order_shipping_address_type.py create mode 100644 src/webflow/types/page_created_webhook.py create mode 100644 src/webflow/types/page_created_webhook_payload.py create mode 100644 src/webflow/types/page_deleted_webhook.py create mode 100644 src/webflow/types/page_deleted_webhook_payload.py create mode 100644 src/webflow/types/page_metadata_updated_webhook.py create mode 100644 src/webflow/types/page_metadata_updated_webhook_payload.py create mode 100644 src/webflow/types/payload.py create mode 100644 src/webflow/types/payload_field_data.py create mode 100644 src/webflow/types/reference_field.py create mode 100644 src/webflow/types/reference_field_metadata.py create mode 100644 src/webflow/types/reference_field_type.py create mode 100644 src/webflow/types/robots.py create mode 100644 src/webflow/types/robots_rules_item.py rename src/webflow/types/{text_node_write.py => search_button.py} (75%) create mode 100644 src/webflow/types/search_button_node_dom.py create mode 100644 src/webflow/types/select.py create mode 100644 src/webflow/types/select_node_choices_item.py create mode 100644 src/webflow/types/select_node_dom.py create mode 100644 src/webflow/types/select_node_write_choices_item.py create mode 100644 src/webflow/types/single_locale_created_payload.py create mode 100644 src/webflow/types/single_locale_created_payload_field_data.py create mode 100644 src/webflow/types/site_membership.py create mode 100644 src/webflow/types/site_membership_audit_log_item.py create mode 100644 src/webflow/types/site_membership_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/site_publish.py create mode 100644 src/webflow/types/site_publish_payload.py create mode 100644 src/webflow/types/static_field.py rename src/webflow/{resources/collections/resources/fields/types/field_create_type.py => types/static_field_type.py} (82%) create mode 100644 src/webflow/types/submit_button.py create mode 100644 src/webflow/types/submit_button_node_dom.py create mode 100644 src/webflow/types/text_input.py create mode 100644 src/webflow/types/text_input_node_dom.py create mode 100644 src/webflow/types/text_node_dom.py create mode 100644 src/webflow/types/updated_order.py create mode 100644 src/webflow/types/user_access.py create mode 100644 src/webflow/types/user_access_audit_log_item.py create mode 100644 src/webflow/types/user_access_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/workspace_audit_log_item.py create mode 100644 src/webflow/types/workspace_audit_log_item_actor.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_user_access_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_workspace.py create mode 100644 src/webflow/types/workspace_audit_log_response.py create mode 100644 src/webflow/types/workspace_invitation.py create mode 100644 src/webflow/types/workspace_invitation_audit_log_item.py create mode 100644 src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/workspace_membership.py create mode 100644 src/webflow/types/workspace_membership_audit_log_item.py create mode 100644 src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py create mode 100644 tests/sites/test_comments.py create mode 100644 tests/sites/test_robots_txt.py create mode 100644 tests/sites/test_well_known.py create mode 100644 tests/workspaces/__init__.py create mode 100644 tests/workspaces/test_audit_logs.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d396980..14569f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -19,7 +19,7 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -36,12 +36,12 @@ jobs: - name: Install Fern run: npm install -g fern-api - name: Test - run: fern test --command "poetry run pytest -rP ./tests/custom/" + run: fern test --command "poetry run pytest -rP ." publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml index db84636..c541456 100644 --- a/.mock/definition/__package__.yml +++ b/.mock/definition/__package__.yml @@ -67,10 +67,18 @@ errors: ConflictError: status-code: 409 type: unknown - docs: Site is published to multiple domains at different times + docs: Collection already exists examples: + - value: + code: duplicate_collection + message: Collection already exists - value: message: '''Site is published to multiple domains at different times' + - value: + code: conflict + message: >- + Conflict: Conflict with server data: Live PATCH updates can't be + applied to items that have never been published - value: code: custom_code_max_registered_scripts message: The maximum number of registered scripts has been reached. @@ -97,6 +105,26 @@ types: - NoDomains source: openapi: ../../../openapi/referenced-specs/v2.yml + ItemsListItemsRequestLastPublished: + properties: + lte: + type: optional + docs: Filter items last published before this date + gte: + type: optional + docs: Filter items last published after this date + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsListItemsLiveRequestLastPublished: + properties: + lte: + type: optional + docs: Filter items last published before this date + gte: + type: optional + docs: Filter items last published after this date + source: + openapi: ../../../openapi/referenced-specs/v2.yml ConflictErrorBody: discriminated: false union: @@ -173,7 +201,24 @@ types: docs: Array of errors source: openapi: ../../../openapi/referenced-specs/v2.yml - Application: unknown + Application: + properties: + id: + type: optional + docs: Unique identifier for the Application + description: + type: optional + docs: Application description provided by the developer + homepage: + type: optional + docs: Application homepage URL provided by the developer + validation: + format: uri + displayName: + type: optional + docs: Application name provided by the developer + source: + openapi: ../../../openapi/referenced-specs/v2.yml AuthorizationAuthorizationAuthorizedTo: properties: siteIds: @@ -232,6 +277,7 @@ types: lastPublished: type: optional docs: The date the custom domain was last published to + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml Locale: @@ -329,6 +375,305 @@ types: openapi: ../../../openapi/referenced-specs/v2.yml InvalidScopes: unknown NotEnterprisePlanWorkspace: unknown + WorkspaceAuditLogItemPayloadUserAccessMethod: + enum: + - dashboard + - sso + - api + - google + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + User access: + properties: + method: + type: optional + location: + type: optional + docs: The geolocation based on the logged IP address + ipAddress: + type: optional + docs: The captured IP address of the user + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessAuditLogItemEventSubType: + enum: + - login + - logout + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessAuditLogItem: + properties: + eventSubType: + type: optional + payload: + type: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Custom role: + properties: + roleName: + type: optional + docs: The name of the custom role + previousRoleName: + type: optional + docs: The previous name of the custom role + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomRoleAuditLogItemEventSubType: + enum: + - role_created + - role_updated + - role_deleted + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomRoleAuditLogItem: + properties: + eventSubType: + type: optional + payload: + type: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod: + enum: + - sso + - dashboard + - admin + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Workspace membership: + properties: + targetUser: + type: optional + method: + type: optional + userType: + type: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceMembershipAuditLogItemEventSubType: + enum: + - user_added + - user_removed + - user_role_updated + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceMembershipAuditLogItem: + properties: + eventSubType: + type: optional + payload: + type: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSiteMembershipSite: + properties: + id: optional + slug: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadSiteMembershipMethod: + enum: + - sso + - invite + - scim + - dashboard + - admin + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSiteMembershipUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Site membership: + properties: + site: + type: optional + targetUser: + type: optional + method: + type: optional + userType: + type: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteMembershipAuditLogItemEventSubType: + enum: + - user_added + - user_removed + - user_role_updated + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteMembershipAuditLogItem: + properties: + eventSubType: + type: optional + payload: + type: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod: + enum: + - sso + - dashboard + - admin + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Workspace invitation: + properties: + targetUser: + type: optional + method: + type: optional + userType: + type: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceInvitationAuditLogItemEventSubType: + enum: + - invite_sent + - invite_accepted + - invite_updated + - invite_canceled + - invite_declined + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceInvitationAuditLogItem: + properties: + eventSubType: + type: optional + payload: + type: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemActor: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemWorkspace: + properties: + id: optional + slug: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItem: + discriminant: eventType + base-properties: + timestamp: optional + actor: optional + workspace: optional + union: + user_access: + type: UserAccessAuditLogItem + custom_role: + type: CustomRoleAuditLogItem + workspace_membership: + type: WorkspaceMembershipAuditLogItem + site_membership: + type: SiteMembershipAuditLogItem + workspace_invitation: + type: WorkspaceInvitationAuditLogItem + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Pagination: + docs: Pagination object + properties: + limit: + type: optional + docs: The limit used for pagination + access: read-only + offset: + type: optional + docs: The offset used for pagination + access: read-only + total: + type: optional + docs: The total number of records + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogResponse: + properties: + items: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml Sites: properties: sites: optional> @@ -348,6 +693,7 @@ types: id: type: optional docs: The ID of the specific redirect rule + access: read-only fromUrl: type: optional docs: The source URL path that will be redirected. @@ -356,20 +702,6 @@ types: docs: The target URL path where the user or client will be redirected. source: openapi: ../../../openapi/referenced-specs/v2.yml - Pagination: - docs: Pagination object - properties: - limit: - type: optional - docs: The limit used for pagination - offset: - type: optional - docs: The offset used for pagination - total: - type: optional - docs: The total number of records - source: - openapi: ../../../openapi/referenced-specs/v2.yml Redirects: docs: Site redirects response properties: @@ -440,6 +772,31 @@ types: docs: URL for more information about Webflow hosting plan pricing. source: openapi: ../../../openapi/referenced-specs/v2.yml + RobotsRulesItem: + properties: + userAgent: + type: string + docs: The user agent the rules apply to. + allows: + type: optional> + docs: List of paths allowed for this user agent. + disallows: + type: optional> + docs: List of paths disallowed for this user agent. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Robots: + docs: The robots.txt file for a given site + properties: + rules: + type: optional> + docs: List of rules for user agents. + sitemap: + type: optional + docs: URL to the sitemap. + source: + openapi: ../../../openapi/referenced-specs/v2.yml SiteActivityLogItemEvent: enum: - styles_modified @@ -549,9 +906,11 @@ types: createdOn: type: optional docs: The date the collection was created + access: read-only lastUpdated: type: optional docs: The date the collection was last updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml CollectionList: @@ -561,12 +920,12 @@ types: docs: An array of Collections source: openapi: ../../../openapi/referenced-specs/v2.yml - FieldType: + StaticFieldType: enum: - Color - DateTime - Email - - ExtFileRef + - File - Image - Link - MultiImage @@ -575,31 +934,27 @@ types: - PlainText - RichText - Switch - - Video + - VideoLink docs: Choose these appropriate field type for your collection data inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml - Field: - docs: The details of a field in a collection + Static Field: properties: id: - type: string + type: optional docs: Unique identifier for a Field - isRequired: - type: boolean - docs: define whether a field is required in a collection + access: read-only isEditable: type: optional docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection type: - type: FieldType + type: StaticFieldType docs: Choose these appropriate field type for your collection data - slug: - type: optional - docs: >- - Slug of Field in Site URL structure. Slugs should be all lowercase - with no spaces. Any spaces will be converted to "-." displayName: type: string docs: The name of a field @@ -608,56 +963,243 @@ types: docs: Additional text to help anyone filling out this field source: openapi: ../../../openapi/referenced-specs/v2.yml - Collection: - docs: A collection object + MetadataOptionsItem: + docs: A single option value for the Option field. properties: - id: + name: type: string - docs: Unique identifier for a Collection - displayName: - 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: + docs: The name of the option + id: 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 + docs: The unique identifier of the option + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemFieldData: + inline: true + Metadata: + docs: The metadata for the Option field. 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 + options: + docs: The option values for the Option field. + type: list 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
+ Option Field: + properties: + id: + type: optional + docs: Unique identifier for a Field + access: read-only + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection + type: + type: literal<"Option"> + docs: >- + The [Option field + type](/data/reference/field-types-item-values#option) + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + metadata: Metadata + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ReferenceFieldType: + enum: + - MultiReference + - Reference + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ReferenceFieldMetadata: + docs: >- + The collectionId for the referenced collection. Only applicable for + Reference and MultiReference fields. + properties: + collectionId: + type: string + docs: The unique identifier of the collection + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Reference Field: + properties: + id: + type: optional + docs: Unique identifier for a Field + access: read-only + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection + type: + type: ReferenceFieldType + docs: Choose these appropriate field type for your collection data + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + metadata: + type: ReferenceFieldMetadata + docs: >- + The collectionId for the referenced collection. Only applicable for + Reference and MultiReference fields. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldCreate: + discriminated: false + docs: Details about the field of a collection + union: + - type: Static Field + - type: Option Field + - type: Reference Field + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldType: + enum: + - Color + - DateTime + - Email + - ExtFileRef + - File + - Image + - Link + - MultiImage + - MultiReference + - Number + - Option + - Phone + - PlainText + - Reference + - RichText + - Switch + - VideoLink + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldValidationsAdditionalPropertiesAdditionalProperties: + properties: + additionalProperties: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FieldValidationsAdditionalProperties: + discriminated: false + union: + - string + - double + - boolean + - integer + - FieldValidationsAdditionalPropertiesAdditionalProperties + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FieldValidations: + docs: The validations for the field + properties: + additionalProperties: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Field: + docs: The details of a field in a collection + properties: + id: + type: string + docs: Unique identifier for a Field + isRequired: + type: boolean + docs: define whether a field is required in a collection + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + type: + type: FieldType + docs: Choose these appropriate field type for your collection data + slug: + type: optional + docs: >- + Slug of Field in Site URL structure. Slugs should be all lowercase + with no spaces. Any spaces will be converted to "-." + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + validations: + type: optional + docs: The validations for the field + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Collection: + docs: A collection object + properties: + id: + type: string + docs: Unique identifier for a Collection + displayName: + type: string + docs: Name given to the Collection + singularName: + type: string + docs: >- + The name of one Item in Collection (e.g. ”Blog Post” if the Collection + is called “Blog Posts”) + slug: + type: optional + docs: Slug of Collection in Site URL structure + createdOn: + type: optional + docs: The date the collection was created + access: read-only + lastUpdated: + type: optional + docs: The date the collection was last updated + access: read-only + fields: + docs: The list of fields in the Collection + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemFieldData: + properties: + name: + type: string + docs: Name of the Item + slug: + type: string + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItem: + docs: > + A Collection Item represents a single entry in your collection. Each item + includes: + + + - **System metadata** - Automatically managed fields like IDs and + timestamp
- **Status flags** - Controls for managing content state: `isDraft`, `isArchived `
@@ -669,18 +1211,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -714,7 +1260,8 @@ types: items: type: optional> docs: List of Items within the collection - pagination: optional + pagination: + type: optional source: openapi: ../../../openapi/referenced-specs/v2.yml CollectionItemPostSingleFieldData: @@ -750,18 +1297,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is in an archived state. @@ -769,7 +1320,7 @@ types: isDraft: type: optional docs: Boolean determining if the Item is in a draft state. - default: false + default: true fieldData: CollectionItemPostSingleFieldData source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -803,12 +1354,15 @@ types: lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -826,6 +1380,7 @@ types: docs: List of Items within the collection source: openapi: ../../../openapi/referenced-specs/v2.yml + Conflict: unknown BulkCollectionItemFieldData: properties: name: @@ -848,7 +1403,7 @@ types: items properties: id: - type: string + type: optional docs: Unique identifier for the Item cmsLocaleIds: type: optional> @@ -856,12 +1411,15 @@ types: lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -897,18 +1455,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -918,95 +1480,308 @@ types: fieldData: optional source: openapi: ../../../openapi/referenced-specs/v2.yml - PageSeo: - docs: SEO-related fields for the Page + CommentThreadAuthor: 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 + userId: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - PageOpenGraph: - docs: Open Graph fields for the Page + CommentThreadMentionedUsersItem: 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 + userId: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - Page: - docs: The Page object + CommentThread: + docs: > + A comment thread represents a conversation between users on a specific + page. Each comment thread has a unique identifier and can contain multiple + comments. Retrieve comment replies using the replies API endpoint. properties: id: type: string - docs: Unique identifier for the Page + docs: Unique identifier for the comment thread siteId: + type: string + docs: The site unique identifier + pageId: + type: string + docs: The page unique identifier + localeId: type: optional - docs: 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: + docs: The locale unique identifier + access: read-only + itemId: type: optional + docs: The item unique identifier + access: read-only + breakpoint: + type: string + docs: The breakpoint the comment was left on + url: + type: string + docs: The URL of the page the comment was left on + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentThreadAuthor + mentionedUsers: docs: >- - Unique identifier for a linked Collection, value will be null if the - Page is not part of a Collection. + List of mentioned users. This is an empty array until email + notifications are sent, which can take up to 5 minutes after the + comment is created. + type: list createdOn: - type: optional - docs: The date the Page was created + type: string + docs: The date the item 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) + type: string + docs: The date the item was last updated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentThreadListPagination: + properties: + limit: + type: double + docs: The limit specified in the request (default 100) + default: 100 + offset: + type: double + docs: The offset specified for pagination + default: 0 + total: + type: double + docs: Total number of comment threads + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentThreadList: + docs: > + A list of comment threads on the site. Contains the content of the first + reply. + properties: + comments: list + pagination: CommentThreadListPagination + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentReplyAuthor: + properties: + id: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReplyMentionedUsersItem: + properties: + id: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReply: + docs: > + A comment thread represents a conversation between users on a specific + page. Each comment thread has a unique identifier and can contain multiple + comments. + properties: + id: + type: string + docs: Unique identifier for the comment thread + commentId: + type: string + docs: The comment reply unique identifier + siteId: + type: string + docs: The site unique identifier + pageId: + type: string + docs: The page unique identifier + localeId: + type: optional + docs: The locale unique identifier + access: read-only + breakpoint: + type: string + docs: The breakpoint the comment was left on + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentReplyAuthor + mentionedUsers: + type: optional> + docs: >- + List of mentioned users is an empty array until email notifications + are sent. + lastUpdated: + type: optional + docs: The date the item was last updated + access: read-only + createdOn: + type: optional + docs: The date the item was created + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentReplyListPagination: + properties: + limit: + type: double + docs: The limit specified in the request (default 100) + default: 100 + offset: + type: double + docs: The offset specified for pagination + default: 0 + total: + type: double + docs: Total number of comment replies + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReplyList: + docs: | + A list of comment replies. + properties: + comments: list + pagination: CommentReplyListPagination + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageSeo: + docs: SEO-related fields for the Page + properties: + title: + type: optional + docs: The Page title shown in search engine results + description: + type: optional + docs: The Page description shown in search engine results + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageOpenGraph: + docs: Open Graph fields for the Page + properties: + title: + type: optional + docs: The title supplied to Open Graph annotations + titleCopied: + type: optional + docs: Indicates the Open Graph title was copied from the SEO title + default: true + access: read-only + description: + type: optional + docs: The description supplied to Open Graph annotations + descriptionCopied: + type: optional + docs: >- + Indicates the Open Graph description was copied from the SEO + description + default: true + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Page: + docs: The Page object + properties: + id: + type: string + docs: Unique identifier for the Page + siteId: + type: optional + docs: Unique identifier for the Site + access: read-only + title: + type: optional + docs: Title of the Page + slug: + type: optional + docs: slug of the Page (derived from title) + parentId: + type: optional + docs: Identifier of the parent folder + access: read-only + collectionId: + type: optional + docs: >- + Unique identifier for a linked Collection, value will be null if the + Page is not part of a Collection. + access: read-only + createdOn: + type: optional + docs: The date the Page was created + access: read-only + lastUpdated: + type: optional + docs: The date the Page was most recently updated + access: read-only + archived: + type: optional + docs: Whether the Page has been archived + default: false + access: read-only + draft: + type: optional + docs: Whether the Page is a draft + default: false + access: read-only + canBranch: + type: optional + docs: >- + Indicates whether the Page supports [Page + Branching](https://university.webflow.com/lesson/page-branching). + Pages that are already branches cannot be branched again. default: false - isMembersOnly: + access: read-only + isBranch: 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) + Indicates whether the Page is a Branch of another Page [Page + Branching](https://university.webflow.com/lesson/page-branching) default: false + access: read-only + branchId: + type: optional + docs: If the Page is a Branch of another Page, this is the ID of the Branch seo: type: optional docs: SEO-related fields for the Page @@ -1016,9 +1791,11 @@ types: localeId: type: optional docs: Unique ID of the page locale + access: read-only publishedPath: type: optional docs: Relative path of the published page URL + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml PageList: @@ -1029,6 +1806,7 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml TextNodeText: + docs: The text content of the node properties: html: type: optional @@ -1039,29 +1817,32 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - TextNode: + Text Node DOM: docs: > Represents text content within the DOM. It contains both the raw text and its HTML representation. Additional attributes can be associated with the text for styling or other purposes. properties: id: - type: optional + type: string docs: Node UUID - text: optional + text: + type: TextNodeText + docs: The text content of the node attributes: type: optional> docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml ImageNodeImage: + docs: The image details of the node properties: alt: optional assetId: optional source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ImageNode: + Image Node DOM: docs: > Represents an image within the DOM. It contains details about the image, such as its alternative text (alt) for accessibility and an asset @@ -1069,15 +1850,18 @@ types: can be associated with the image for styling or other purposes. properties: id: - type: optional + type: string docs: Node UUID - image: optional + image: + type: ImageNodeImage + docs: The image details of the node attributes: type: optional> docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml Text: + docs: The text content of the node properties: html: type: optional @@ -1122,20 +1906,102 @@ types: and its HTML representation. source: openapi: ../../../openapi/referenced-specs/v2.yml - ComponentNode: + Component Node DOM: docs: > Represents a component instance within the DOM. It contains details about the component instance, such as its type and properties. properties: id: - type: optional - docs: Node UUID + type: string + docs: The unique identifier of the component instance node componentId: - type: optional - docs: Component ID + type: string + docs: The unique identifier of the component propertyOverrides: - type: optional> docs: List of component properties with overrides for a component instance. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Text Input Node DOM: + docs: > + Represents text input and textarea elements within the DOM. It contains + the placeholder text in the input. Additional attributes can be associated + with the text for styling or other purposes. + properties: + id: + type: string + docs: Node UUID + placeholder: + type: string + docs: The placeholder text of the input node + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SelectNodeChoicesItem: + properties: + value: + type: string + docs: The value of the choice when selected. + text: + type: string + docs: The text to display for the choice. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Select Node DOM: + docs: > + Represents select elements within the DOM. It contains the list of choices + in the select. Additional attributes can be associated with the text for + styling or other purposes. + properties: + id: + type: string + docs: Node UUID + choices: + docs: The list of choices in this select node. + type: list + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Submit Button Node DOM: + docs: > + Represents submit button elements within the DOM. It contains the text and + waiting text of the button. Additional attributes can be associated with + the text for styling or other purposes. + properties: + id: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the submit button. + waitingText: + type: string + docs: The text to show while the form is submitting. + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Search Button Node DOM: + docs: > + Represents search button elements within the DOM. It contains the text of + the button. Additional attributes can be associated with the text for + styling or other purposes. + properties: + id: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the search button. + attributes: + type: optional> + docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml Node: @@ -1146,9 +2012,20 @@ types: Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. union: - text: TextNode - image: ImageNode - component-instance: ComponentNode + text: + type: Text Node DOM + image: + type: Image Node DOM + component-instance: + type: Component Node DOM + text-input: + type: Text Input Node DOM + select: + type: Select Node DOM + submit-button: + type: Submit Button Node DOM + search-button: + type: Search Button Node DOM source: openapi: ../../../openapi/referenced-specs/v2.yml Dom: @@ -1163,11 +2040,18 @@ types: pageId: type: optional docs: Page ID + branchId: + type: optional + docs: If the page is a branch, this is the ID of the branch nodes: optional> pagination: optional + lastUpdated: + type: optional + docs: The date the page dom was most recently updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml - TextNodeWrite: + Text Node: docs: Update a text node properties: nodeId: @@ -1201,7 +2085,7 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ComponentInstanceNodePropertyOverridesWrite: + Component Instance: docs: Update text property overrides of a component instance properties: nodeId: @@ -1214,6 +2098,64 @@ types: type: list source: openapi: ../../../openapi/referenced-specs/v2.yml + SelectNodeWriteChoicesItem: + properties: + value: + type: string + docs: The value of the choice when selected. + text: + type: string + docs: The text to display for the choice. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Select: + docs: Update choices on a select node + properties: + nodeId: + type: string + docs: Node UUID + choices: + docs: The list of choices to set on the select node. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Text Input: + docs: Update placeholder text on a text input node + properties: + nodeId: + type: string + docs: Node UUID + placeholder: + type: string + docs: The placeholder text of the input node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Submit Button: + docs: Update a submit button node + properties: + nodeId: + type: string + docs: Node UUID + value: + type: optional + docs: The text content of the submit button. + waitingText: + type: optional + docs: The text to show while the form is submitting. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Search Button: + docs: Update a search button node + properties: + nodeId: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the search button. + source: + openapi: ../../../openapi/referenced-specs/v2.yml Component: docs: The Component object properties: @@ -1223,18 +2165,22 @@ types: name: type: optional docs: Component Name + access: read-only group: type: optional docs: The group that the component belongs to + access: read-only description: type: optional docs: Component Description + access: read-only readonly: type: optional docs: >- Indicates whether the component is read-only. Components that cannot be updated within this Site are set to readonly. Workspace Libraries are a good example. + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml ComponentList: @@ -1249,8 +2195,8 @@ types: The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each - node has a unique identifier and can contain text, images, or nested - component instances. + node has a unique identifier and can contain text, images, select or text + inputs, submit buttons, or nested component instances. properties: componentId: type: optional @@ -1270,6 +2216,7 @@ types: componentId: type: optional docs: Component ID + access: read-only properties: optional> pagination: optional source: @@ -1314,9 +2261,11 @@ types: lastUpdated: type: optional docs: Date when the Site's scripts were last updated + access: read-only createdOn: type: optional docs: Date when the Site's scripts were created + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml CustomCodeHostedResponse: @@ -1325,6 +2274,7 @@ types: id: type: optional docs: Human readable id, derived from the user-specified display name + access: read-only canCopy: type: optional docs: >- @@ -1347,9 +2297,11 @@ types: createdOn: type: optional docs: Timestamp when the script version was created + access: read-only lastUpdated: type: optional docs: Timestamp when the script version was last updated + access: read-only version: type: optional docs: A Semantic Version (SemVer) string, denoting the version of the script @@ -1359,6 +2311,7 @@ types: docs: A list of scripts registered to the site properties: registeredScripts: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml CustomCodeInlineResponse: @@ -1367,6 +2320,7 @@ types: id: type: optional docs: Human readable id, derived from the user-specified display name + access: read-only canCopy: type: optional docs: >- @@ -1389,9 +2343,11 @@ types: createdOn: type: optional docs: Timestamp when the script version was created + access: read-only lastUpdated: type: optional docs: Timestamp when the script version was last updated + access: read-only version: type: optional docs: A Semantic Version (SemVer) string, denoting the version of the script @@ -1426,9 +2382,11 @@ types: createdOn: type: optional docs: The date the Block was created + access: read-only lastUpdated: type: optional docs: The date the Block was most recently updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml ListCustomCodeBlocks: @@ -1439,29 +2397,30 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml AssetVariant: + docs: Asset variant details properties: hostedUrl: - type: optional + type: string docs: URL of where the asset variant is hosted validation: format: uri originalFileName: - type: optional + type: string docs: Original file name of the variant displayName: - type: optional + type: string docs: Display name of the variant format: - type: optional + type: string docs: format of the variant width: - type: optional + type: integer docs: Width in pixels height: type: optional docs: Height in pixels quality: - type: optional + type: integer docs: Value between 0 and 100 representing the image quality error: type: optional @@ -1469,37 +2428,51 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml Asset: + docs: Asset details properties: id: type: optional docs: Unique identifier for this asset + access: read-only contentType: type: optional docs: File format type + access: read-only size: type: optional docs: size in bytes + access: read-only siteId: type: optional docs: Unique identifier for the site that hosts this asset + access: read-only hostedUrl: type: optional docs: Link to the asset validation: format: uri + access: read-only originalFileName: type: optional docs: Original file name at the time of upload + access: read-only displayName: - type: optional + type: string docs: Display name of the asset lastUpdated: type: optional docs: Date the asset metadata was last updated + access: read-only createdOn: type: optional docs: Date the asset metadata was created - variants: optional> + access: read-only + variants: + docs: >- + A list of [asset + variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) + created by Webflow to serve your site responsively. + type: list altText: type: optional docs: The visual description of the asset @@ -1509,6 +2482,7 @@ types: docs: A list of assets properties: assets: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml AssetUploadUploadDetails: @@ -1616,48 +2590,12 @@ types: - collection_item_created - collection_item_changed - collection_item_deleted + - collection_item_published - collection_item_unpublished + - comment_created docs: > - * `form_submission` - Sends the [form_submission](#form_submission) event - - * `site_publish` - Sends a [site_publish](#site_publish) event - - * `page_created` - Send the [page_created](#page_created) event - - * `page_metadata_updated` - Sends the - [page_metadata_updated](#page_metadata_updated) event - - * `page_deleted` - Sends the [page_deleted](#page_deleted) event - - * `ecomm_new_order` - Sends the new [ecomm_new_order](#ecomm_new_order) - event - - * `ecomm_order_changed` - Sends the - [ecomm_order_changed](#ecomm_order_changed) event - - * `ecomm_inventory_changed` - Sends the - [ecomm_inventory_changed](#ecomm_inventory_changed) event - - * `user_account_added` - Sends the - [user_account_added](#user_account_added) event - - * `user_account_updated` - Sends the - [user_account_updated](#user_account_updated) event - - * `user_account_deleted` - Sends the - [user_account_deleted](#user_account_deleted) event - - * `collection_item_created` - Sends the - [collection_item_created](#collection_item_created) event - - * `collection_item_changed` - Sends the - [collection_item_changed](#collection_item_changed) event - - * `collection_item_deleted` - Sends the - [collection_item_deleted](#collection_item_deleted) event - - * `collection_item_unpublished` - Sends the - [collection_item_unpublished](#collection_item_unpublished) event + The type of event that triggered the request. See the the documentation + for details on [supported events](/data/reference/all-events). source: openapi: ../../../openapi/referenced-specs/v2.yml WebhookFilter: @@ -1676,6 +2614,7 @@ types: id: type: optional docs: Unique identifier for the Webhook registration + access: read-only triggerType: optional url: type: optional @@ -1683,9 +2622,11 @@ types: workspaceId: type: optional docs: Unique identifier for the Workspace the Webhook is registered in + access: read-only siteId: type: optional docs: Unique identifier for the Site the Webhook is registered in + access: read-only filter: type: optional docs: >- @@ -1694,15 +2635,17 @@ types: lastTriggered: type: optional docs: Date the Webhook instance was last triggered + access: read-only createdOn: type: optional docs: Date the Webhook registration was created + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml WebhookList: properties: - pagination: optional webhooks: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml FormFieldValueType: @@ -1830,43 +2773,12 @@ types: pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml - UserDataData: - properties: - name: - type: optional - docs: | - The name of the user - email: - type: optional - docs: | - The email address of the user - accept-privacy: - type: optional - docs: | - Boolean indicating if the user has accepted the privacy policy - accept-communications: - type: optional - docs: | - Boolean indicating if the user has accepted to receive communications - additionalProperties: - type: optional - docs: Custom user attributes - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - UserData: - docs: An object containing the User's basic info and custom fields - properties: - data: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml UserStatus: enum: - invited - verified - unverified docs: The status of the user - inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml UserAccessGroupsItemType: @@ -1894,7 +2806,36 @@ types: * `ecommerce` - Assigned to the user via an ecommerce purchase 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 User: docs: > The fields that define the schema for a given Item are based on the @@ -1905,24 +2846,28 @@ types: id: type: optional docs: Unique identifier for the User + access: read-only isEmailVerified: type: optional docs: Shows whether the user has verified their email address + access: read-only lastUpdated: type: optional docs: The timestamp the user was updated + access: read-only invitedOn: type: optional docs: The timestamp the user was invited + access: read-only createdOn: type: optional docs: The timestamp the user was created + access: read-only lastLogin: type: optional docs: The timestamp the user was logged in - status: - type: optional - docs: The status of the user + access: read-only + status: optional accessGroups: type: optional> docs: Access groups the user belongs to @@ -2128,9 +3073,9 @@ types: sku-properties: type: optional> docs: Variant types to include in SKUs - categories: + category: type: optional> - docs: The categories your product belongs to. + docs: The category your product belongs to. tax-category: type: optional docs: Product tax class @@ -2152,18 +3097,23 @@ types: id: type: optional docs: Unique identifier for the Product + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item + access: read-only lastPublished: type: optional docs: The date the Product was last published + access: read-only lastUpdated: type: optional docs: The date the Product was last updated + access: read-only createdOn: type: optional docs: The date the Product was created + access: read-only isArchived: type: optional docs: Boolean determining if the Product is set to archived @@ -2178,8 +3128,10 @@ types: SkuValueList: type: map docs: > - A dictionary that maps a SKU property to a SKU value. The key of the - dictionary is the SKU property ID, and the value is the SKU value ID. + A mapping between SKU properties and their values, represented as + key-value pairs. Each key represents a SKU Property ID (e.g. "color") and + maps to its corresponding SKU Value ID (e.g. "blue"). This structure + defines the specific variant combination for a SKU. SkuFieldDataPrice: docs: price of SKU properties: @@ -2189,6 +3141,9 @@ types: unit: type: optional docs: Currency of Item + currency: + type: optional + docs: Currency of Item (alternative representation) source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -2209,6 +3164,10 @@ types: - value: one-time name: OneTime - subscription + docs: >- + [Billing + method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for + the SKU inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -2246,6 +3205,10 @@ types: openapi: ../../../openapi/referenced-specs/v2.yml inline: true SkuFieldDataEcSkuSubscriptionPlan: + docs: >- + [Subscription + plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) + for the SKU properties: interval: type: optional @@ -2256,7 +3219,9 @@ types: trial: type: optional docs: Number of days of a trial - plans: optional> + plans: + type: optional> + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -2276,17 +3241,27 @@ types: compare-at-price: type: optional docs: comparison price of SKU - ec-sku-billing-method: optional - ec-sku-subscription-plan: optional - track-inventory: - type: optional + ec-sku-billing-method: + type: optional docs: >- - A boolean indicating whether inventory for this product should be - tracked. - default: false - quantity: - type: optional - docs: Quantity of SKU that will be tracked as items are ordered. + [Billing + method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for + the SKU + ec-sku-subscription-plan: + type: optional + docs: >- + [Subscription + plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) + for the SKU + main-image: + type: optional + docs: The URL for the main image of the SKU + sku: + type: optional + docs: A unique identifier for the SKU + sku-properties: + type: optional> + docs: The properties of the SKU source: openapi: ../../../openapi/referenced-specs/v2.yml Sku: @@ -2295,18 +3270,23 @@ types: id: type: optional docs: Unique identifier for the Product + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item + access: read-only lastPublished: type: optional docs: The date the Product was last published + access: read-only lastUpdated: type: optional docs: The date the Product was last updated + access: read-only createdOn: type: optional docs: The date the Product was created + access: read-only fieldData: optional source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -2472,6 +3452,7 @@ types: productId: type: optional docs: The unique identifier for the Product + access: read-only productName: type: optional docs: User-facing name of the Product @@ -2637,6 +3618,112 @@ types: inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml + OrderShippingAddressType: + enum: + - shipping + - billing + docs: The type of the order address (billing or shipping) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderShippingAddressJapanType: + enum: + - kana + - kanji + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderShippingAddress: + docs: The shipping address + properties: + type: + type: optional + docs: The type of the order address (billing or shipping) + japanType: + type: optional + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + addressee: + type: optional + docs: Display name on the address + line1: + type: optional + docs: The first line of the address + line2: + type: optional + docs: The second line of the address + city: + type: optional + docs: The city of the address. + state: + type: optional + docs: The state or province of the address + country: + type: optional + docs: The country of the address + postalCode: + type: optional + docs: The postal code of the address + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderBillingAddressType: + enum: + - shipping + - billing + docs: The type of the order address (billing or shipping) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderBillingAddressJapanType: + enum: + - kana + - kanji + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderBillingAddress: + docs: The billing address + properties: + type: + type: optional + docs: The type of the order address (billing or shipping) + japanType: + type: optional + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + addressee: + type: optional + docs: Display name on the address + line1: + type: optional + docs: The first line of the address + line2: + type: optional + docs: The second line of the address + city: + type: optional + docs: The city of the address. + state: + type: optional + docs: The state or province of the address + country: + type: optional + docs: The country of the address + postalCode: + type: optional + docs: The postal code of the address + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true OrderCustomerInfo: docs: An object with the keys `fullName` and `email`. properties: @@ -2725,6 +3812,7 @@ types: The order ID. Will usually be 6 hex characters, but can also be 9 hex characters if the site has a very large number of Orders. Randomly assigned. + access: read-only status: type: optional docs: | @@ -2780,10 +3868,10 @@ types: type: optional> docs: All addresses provided by the customer during the ordering flow. shippingAddress: - type: optional + type: optional docs: The shipping address billingAddress: - type: optional + type: optional docs: The billing address shippingProvider: type: optional @@ -2868,6 +3956,7 @@ types: id: type: optional docs: Unique identifier for a SKU item + access: read-only quantity: type: optional docs: >- @@ -2884,11 +3973,501 @@ types: siteId: type: optional docs: The identifier of the Site + access: read-only createdOn: type: optional docs: Date that the Site was created on + access: read-only defaultCurrency: type: optional docs: The three-letter ISO currency code for the Site source: openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmissionTriggerPayloadSchemaItemFieldType: + enum: + - FormTextInput + - FormTextarea + - FormCheckboxInput + - FormRadioInput + - FormFileUploadInput + docs: Form field type + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmissionTriggerPayloadSchemaItem: + properties: + fieldName: + type: optional + docs: Form field name + fieldType: + type: optional + docs: Form field type + fieldElementId: + type: optional + docs: Element ID of the Form Field + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FormSubmissionTriggerPayload: + docs: The payload of data sent from Webflow + properties: + name: + type: optional + docs: The name of the form + siteId: + type: optional + docs: The ID of the site that the form was submitted from + data: + type: optional> + docs: The data submitted in the form + schema: + type: optional> + docs: A list of fields from the submitted form + submittedAt: + type: optional + docs: The timestamp the form was submitted + id: + type: optional + docs: the ID of the event + formId: + type: optional + docs: The ID of the form submission + formElementId: + type: optional + docs: The uniqueID of the Form element + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FormSubmissionTrigger: + docs: The Webhook payload for when a form is submitted + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SitePublishPayload: + docs: The payload of data sent from Webflow + properties: + siteId: + type: optional + docs: The ID of the site that was published + publishedOn: + type: optional + docs: The timestamp of the publish event + domains: + type: optional> + docs: The domains that were published + publishedBy: + type: optional> + docs: The name andID of the user who published the site + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SitePublish: + docs: The Webhook payload for when a Site is published + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + NewOrder: + docs: The Webhook payload for when a new order is created + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UpdatedOrder: + docs: The Webhook payload for when an order is updated + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SingleLocaleCreatedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SingleLocaleCreatedPayload: + properties: + id: + type: string + docs: Unique identifier for the Item + validation: + format: uuid + workspaceId: + type: string + docs: Unique identifier of the workspace + validation: + format: uuid + siteId: + type: string + docs: Unique identifier of the site + validation: + format: uuid + collectionId: + type: string + docs: Unique identifier of the collection + validation: + format: uuid + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: + type: optional + lastUpdated: + type: optional + createdOn: + type: optional + isArchived: + type: optional + isDraft: + type: optional + fieldData: SingleLocaleCreatedPayloadFieldData + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemCreated: + docs: The Webhook payload for when a Collection Item is created + properties: + triggerType: + type: literal<"collection_item_created"> + docs: The type of event that triggered the request + payload: + type: SingleLocaleCreatedPayload + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemChanged: + docs: The Webhook payload for when a Collection Item is changed + properties: + triggerType: + type: literal<"collection_item_changed"> + docs: The type of event that triggered the request + payload: + type: SingleLocaleCreatedPayload + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemRemovedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemRemovedPayload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was deleted + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemRemoved: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Payload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was unpublished + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemPublished: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemUnpublishedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemUnpublishedPayload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was unpublished + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemUnpublished: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageCreatedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + createdOn: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageCreatedWebhook: + docs: The Webhook payload for when a Page is created + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageMetadataUpdatedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + lastUpdated: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageMetadataUpdatedWebhook: + docs: The Webhook payload for when a Page's metadata is updated + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageDeletedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + deletedOn: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageDeletedWebhook: + docs: The Webhook payload for when a Page is deleted + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentPayloadAuthor: + properties: + userId: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentPayloadMentionedUsersItem: + properties: + userId: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentPayload: + docs: > + The comment webhook payload contains data for the thread and for replies. + Check the type to determine if the payload is for a thread or a reply. + The webhook payload may be delayed by up to 5 minutes. + properties: + threadId: + type: optional + docs: Unique identifier for the comment thread + access: read-only + commentId: + type: optional + docs: Unique identifier for the comment reply + access: read-only + type: + type: optional + docs: The type of comment payload + access: read-only + siteId: + type: optional + docs: The site unique identifier + access: read-only + pageId: + type: optional + docs: The page unique identifier + access: read-only + localeId: + type: optional + docs: The locale unique identifier + access: read-only + itemId: + type: optional + docs: The item unique identifier + access: read-only + breakpoint: + type: optional + docs: The breakpoint the comment was left on + access: read-only + url: + type: optional + docs: The URL of the page the comment was left on + access: read-only + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentPayloadAuthor + mentionedUsers: + docs: >- + List of mentioned users. This is an empty array until email + notifications are sent, which can take up to 5 minutes after the + comment is created. + type: list + createdOn: + type: optional + docs: The date the item was created + access: read-only + lastUpdated: + type: optional + docs: The date the item was last updated + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Comment: + docs: The Webhook payload for when a comment thread or reply is made on a Site + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/accessGroups.yml b/.mock/definition/accessGroups.yml index d8828f8..7689533 100644 --- a/.mock/definition/accessGroups.yml +++ b/.mock/definition/accessGroups.yml @@ -49,6 +49,7 @@ service: response: docs: Request was successful type: root.AccessGroupList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/api.yml b/.mock/definition/api.yml index aee9acd..b881d16 100644 --- a/.mock/definition/api.yml +++ b/.mock/definition/api.yml @@ -3,8 +3,15 @@ error-discrimination: strategy: status-code display-name: Data API environments: - Default: https://api.webflow.com/v2 -default-environment: Default + Data API: + urls: + Base: https://api.webflow.com/v2 + Data API: https://api.webflow.com/v2 + Content Delivery API: https://api-cdn.webflow.com/v2 + Production: https://api.webflow.com/v2 + CDN: https://api-cdn.webflow.com/v2 +default-environment: Data API +default-url: Base auth-schemes: BearerToken: scheme: bearer diff --git a/.mock/definition/assets.yml b/.mock/definition/assets.yml index 35392ec..3d36d0b 100644 --- a/.mock/definition/assets.yml +++ b/.mock/definition/assets.yml @@ -9,7 +9,7 @@ service: method: GET auth: true docs: | - List assets for a given site + List of assets uploaded to a site Required scope | `assets:read` source: @@ -22,6 +22,7 @@ service: response: docs: Request was successful type: root.Assets + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -55,35 +56,64 @@ service: width: 500 height: 900 quality: 100 - altText: A red chair + altText: A single candy wrapper + - id: 63e5889e7fe4eafa7384cea5 + contentType: image/png + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Gum-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea5_Gum-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' + variants: + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: >- + Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 + height: 900 + quality: 100 + altText: A single gum wrapper + pagination: + limit: 2 + offset: 0 + total: 2 create: path: /sites/{site_id}/assets method: POST auth: true docs: > - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: - `uploadUrl` and `uploadDetails`. + `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by - making a - POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your - header information in the request. - - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson + s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) + to complete the upload. + + + + To learn more about how to upload assets to Webflow, see our [assets + guide](/data/docs/working-with-assets). + + Required scope | `assets:write` source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: site_id: type: string docs: Unique identifier for a Site - display-name: Create Asset Metadata + display-name: Upload Asset request: name: AssetsCreateRequest body: @@ -103,6 +133,7 @@ service: response: docs: Request was successful type: root.AssetUpload + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -137,7 +168,7 @@ service: assetUrl: >- https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png hostedUrl: >- - https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png + https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png originalFileName: file.png createdOn: '2023-04-11T16:32:21Z' lastUpdated: '2023-04-12T20:31:03Z' @@ -146,7 +177,7 @@ service: method: GET auth: true docs: | - Get an Asset + Get details about an asset Required scope | `assets:read` source: @@ -159,6 +190,7 @@ service: response: docs: Request was successful type: root.Asset + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -170,25 +202,27 @@ service: asset_id: 580e63fc8c9a982ac9b8b745 response: body: - id: 55131cd036c09f7d07883dfc + id: 63e5889e7fe4eafa7384cea4 contentType: image/png - size: 1500 - siteId: 62749158efef318abc8d5a0f - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: example-image-123.png - lastUpdated: '2016-09-06T21:12:22Z' - createdOn: '2016-09-02T23:26:22Z' + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Candy-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' variants: - - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: A brown dog - format: format - width: 1500 + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 height: 900 - quality: 1 - error: error - altText: A red chair + quality: 100 + altText: A single candy wrapper delete: path: /assets/{asset_id} method: DELETE @@ -218,7 +252,7 @@ service: method: PATCH auth: true docs: | - Update an Asset + Update details of an Asset. Required scope | `assets:write` source: @@ -244,6 +278,7 @@ service: response: docs: Request was successful type: root.Asset + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -256,25 +291,27 @@ service: request: {} response: body: - id: 55131cd036c09f7d07883dfc + id: 63e5889e7fe4eafa7384cea4 contentType: image/png - size: 1500 - siteId: 62749158efef318abc8d5a0f - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: example-image-123.png - lastUpdated: '2016-09-06T21:12:22Z' - createdOn: '2016-09-02T23:26:22Z' + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Candy-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' variants: - - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: A brown dog - format: format - width: 1500 + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 height: 900 - quality: 1 - error: error - altText: A red chair + quality: 100 + altText: A single candy wrapper list-folders: path: /sites/{site_id}/asset_folders method: GET @@ -293,6 +330,7 @@ service: response: docs: Request was successful type: root.AssetFolderList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -307,7 +345,6 @@ service: assetFolders: - id: 6390c49774a71f0e3c1a08ee displayName: emoji icons - parentFolder: 6390c49774a71f99f21a08eb assets: - 63e5889e7fe4eafa7384cea4 - 659595234426a9fcbad57043 @@ -349,6 +386,7 @@ service: response: docs: Request was successful type: root.AssetFolder + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -389,6 +427,7 @@ service: response: docs: Request was successful type: root.AssetFolder + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/collections.yml b/.mock/definition/collections.yml index 661b54b..effcb1d 100644 --- a/.mock/definition/collections.yml +++ b/.mock/definition/collections.yml @@ -22,6 +22,7 @@ service: response: docs: Request was successful type: root.CollectionList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -56,8 +57,16 @@ service: path: /sites/{site_id}/collections method: POST auth: true - docs: | - Create a Collection for a site. + docs: > + Create a Collection for a site with collection fields. + + + Each collection includes the required _name_ and _slug_ fields, which + are generated automatically. You can update the `displayName` of these + fields, but the slug for them cannot be changed. Fields slugs are + automatically converted to lowercase. Spaces in slugs are replaced with + hyphens. + Required scope | `cms:write` source: @@ -80,14 +89,19 @@ service: slug: type: optional docs: Part of a URL that identifier + fields: + type: optional> + docs: An array of custom fields to add to the collection content-type: application/json response: docs: Request was successful type: root.Collection + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: @@ -97,22 +111,51 @@ service: displayName: Blog Posts singularName: Blog Post slug: posts + fields: + - isRequired: true + type: PlainText + displayName: Title + helpText: The title of the blog post + - isRequired: true + type: RichText + displayName: Content + helpText: The content of the blog post + - isRequired: true + type: Reference + displayName: Author + helpText: The author of the blog post + metadata: + collectionId: 23cc2d952d4e4631ffd4345d2743db4e response: body: - id: 580e63fc8c9a982ac9b8b745 + id: 562ac0395358780a1f5e6fbd displayName: Blog Posts singularName: Blog Post - slug: post + slug: posts createdOn: '2016-10-24T19:41:48Z' lastUpdated: '2016-10-24T19:42:38Z' fields: - - id: 23cc2d952d4e4631ffd4345d2743db4e + - id: id isRequired: true isEditable: true type: PlainText - slug: name - displayName: Name - helpText: helpText + slug: title + displayName: Title + helpText: The title of the blog post + - id: id + isRequired: true + isEditable: true + type: RichText + slug: content + displayName: Content + helpText: The content of the blog post + - id: id + isRequired: true + isEditable: true + type: Reference + slug: author + displayName: Author + helpText: The author of the blog post get: path: /collections/{collection_id} method: GET @@ -131,6 +174,7 @@ service: response: docs: Request was successful type: root.Collection + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -142,20 +186,129 @@ service: collection_id: 580e63fc8c9a982ac9b8b745 response: body: - id: 580e63fc8c9a982ac9b8b745 - displayName: Blog Posts - singularName: Blog Post - slug: post - createdOn: '2016-10-24T19:41:48Z' - lastUpdated: '2016-10-24T19:42:38Z' + id: 7f15043107e2fc95644e93807ee25dd6 + displayName: Guide Entries + singularName: Guide Entry + slug: guide-entry + createdOn: '2024-04-12T12:42:00Z' + lastUpdated: '2024-04-12T12:42:00Z' fields: - - id: 23cc2d952d4e4631ffd4345d2743db4e + - id: 5e2a1b3c4d5e6f7890a1b2c3 isRequired: true isEditable: true type: PlainText slug: name - displayName: Name - helpText: helpText + displayName: Entry Title + helpText: Name of the entry. + - id: 5e2a1b3c4d5e6f7890a1b2c4 + isRequired: true + isEditable: true + type: PlainText + slug: slug + displayName: Slug + helpText: Slug of the entry. + - id: 6f7e8d9c0b1a2e3d4c5b6a7f + isRequired: false + isEditable: true + type: PlainText + slug: summary + displayName: Summary + helpText: A short summary of the entry. + - id: 1a2b3c4d5e6f7a8b9c0d1e2f + isRequired: false + isEditable: true + type: RichText + slug: entry-html + displayName: Entry HTML + helpText: The HTML content of the entry. + - id: 7e8d9c0b1a2e3d4c5b6a7f8e + isRequired: false + isEditable: true + type: Image + slug: illustration-image + displayName: Illustration Image + helpText: An image of the entry. + - id: 2f3e4d5c6b7a8e9d0c1b2a3f + isRequired: false + isEditable: true + type: VideoLink + slug: demonstration-video + displayName: Demonstration Video + helpText: A video of the entry. + - id: 8e9d0c1b2a3f4e5d6c7b8a9e + isRequired: false + isEditable: true + type: Link + slug: more-info-link + displayName: More Info Link + helpText: A link to more information about the entry. + - id: 3f4e5d6c7b8a9e0d1c2b3a4f + isRequired: false + isEditable: true + type: Number + slug: importance-level + displayName: Importance Level + helpText: The importance level of the entry. + - id: 9e0d1c2b3a4f5e6d7c8b9a0e + isRequired: false + isEditable: true + type: Switch + slug: is-essential + displayName: Is Essential + helpText: Is this entry essential? + - id: 4f5e6d7c8b9a0e1d2c3b4a5f + isRequired: false + isEditable: true + type: Color + slug: first-mentioned + displayName: First Mentioned + helpText: Date of the first mention of the subject. + - id: 0e1d2c3b4a5f6e7d8c9b0a1e + isRequired: false + isEditable: true + type: Color + slug: towel-color + displayName: Towel Color + helpText: The color of the towel. + - id: 5f6e7d8c9b0a1e2d3c4b5a6f + isRequired: false + isEditable: true + type: Reference + slug: related-entry + displayName: Related Entry + helpText: A related entry. + - id: 1e2d3c4b5a6f7e8d9c0b1a2f + isRequired: false + isEditable: true + type: MultiReference + slug: mentioned-in-entries + displayName: Mentioned In Entries + helpText: Entries that mention this subject. + - id: 6f7e8d9c0b1a2e3d4c5b6a8f + isRequired: false + isEditable: true + type: Option + slug: item-type + displayName: Item Type + helpText: The type of item. + - id: 2e3d4c5b6a7f8e9d0c1b2a4f + isRequired: false + isEditable: true + type: File + slug: guide-file + displayName: Guide File + - id: 7f8e9d0c1b2a3f4e5d6c8b9e + isRequired: false + isEditable: true + type: Email + slug: contributor-email + displayName: Contributor Email + - id: 3a4f5e6d7c8b9a0e1d2c4b5f + isRequired: false + isEditable: true + type: Phone + slug: emergency-contact + displayName: Emergency Contact delete: path: /collections/{collection_id} method: DELETE diff --git a/.mock/definition/collections/fields.yml b/.mock/definition/collections/fields.yml index 08dc554..a7af253 100644 --- a/.mock/definition/collections/fields.yml +++ b/.mock/definition/collections/fields.yml @@ -1,24 +1,3 @@ -types: - FieldCreateType: - enum: - - Color - - DateTime - - Email - - ExtFileRef - - File - - Image - - Link - - MultiImage - - Number - - Phone - - PlainText - - RichText - - Switch - - Video - docs: Choose these appropriate field type for your collection data - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml imports: root: ../__package__.yml service: @@ -30,20 +9,15 @@ service: method: POST auth: true docs: > - Create a custom field in a collection. + Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. + Field validation is currently not available through the API. - If you pass a string with uppercase letters and/or spaces to the "Slug" - property, Webflow will - convert the slug to lowercase and replace spaces with "-." - - - Only some field types can be created through the API. - - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add + multiple fields at once, include them when you [create the + collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -55,48 +29,88 @@ service: docs: Unique identifier for a Collection display-name: Create Collection Field request: - name: FieldCreate - body: - properties: - isRequired: - type: optional - docs: define whether a field is required in a collection - type: - type: FieldCreateType - docs: Choose these appropriate field type for your collection data - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field + body: root.FieldCreate content-type: application/json response: docs: Request was successful - type: root.Field + type: root.FieldCreate + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: StaticField + path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: + id: 562ac0395358780a1f5e6fbc + isEditable: true isRequired: false type: RichText displayName: Post Body helpText: Add the body of your post here response: body: - id: 75821f618da60c18383330bcc0ca488b - isRequired: false + id: 562ac0395358780a1f5e6fbc isEditable: true + isRequired: false type: RichText - slug: post-body displayName: Post Body helpText: Add the body of your post here + - name: OptionField + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + id: 562ac0395358780a1f5e6fbc + isEditable: true + isRequired: false + type: Option + displayName: Post Type + helpText: Add the body of your post here + metadata: + options: + - name: Feature + - name: News + - name: Product Highlight + response: + body: + id: 562ac0395358780a1f5e6fbc + isEditable: true + isRequired: false + type: Option + displayName: Post Type + helpText: Add the body of your post here + metadata: + options: + - name: Feature + - name: News + - name: Product Highlight + - name: ReferenceField + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + id: 562ac0395358780a1f5e6fbd + isEditable: true + isRequired: false + type: Reference + displayName: Author + helpText: Add the post author here + metadata: + collectionId: 63692ab61fb2852f582ba8f5 + response: + body: + id: 562ac0395358780a1f5e6fbd + isEditable: true + isRequired: false + type: Reference + displayName: Author + helpText: Add the post author here + metadata: + collectionId: 63692ab61fb2852f582ba8f5 delete: path: /collections/{collection_id}/fields/{field_id} method: DELETE @@ -162,6 +176,7 @@ service: response: docs: Request was successful type: root.Field + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -185,5 +200,7 @@ service: slug: post-body displayName: Post Body helpText: Add the body of your post here + validations: + additionalProperties: additionalProperties source: openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/collections/items.yml b/.mock/definition/collections/items.yml index f765817..2227057 100644 --- a/.mock/definition/collections/items.yml +++ b/.mock/definition/collections/items.yml @@ -1,3 +1,5 @@ +imports: + root: ../__package__.yml types: ItemsListItemsRequestSortBy: enum: @@ -20,11 +22,11 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ItemsCreateItemRequest: + ItemsCreateItemRequestBody: discriminated: false union: - root.CollectionItemPostSingle - - Multiple Items + - type: Multiple Items source: openapi: ../../../openapi/referenced-specs/v2.yml ItemsDeleteItemsRequestItemsItem: @@ -38,6 +40,13 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true + ItemsUpdateItemsResponse: + discriminated: false + union: + - type: root.CollectionItem + - type: root.CollectionItemList + source: + openapi: ../../../openapi/referenced-specs/v2.yml ItemsListItemsLiveRequestSortBy: enum: - lastPublished @@ -59,16 +68,16 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ItemsCreateItemLiveRequest: + ItemsCreateItemLiveRequestBody: discriminated: false union: - - root.CollectionItem - - Multiple Live Items + - type: root.CollectionItem + - type: Multiple Live Items source: openapi: ../../../openapi/referenced-specs/v2.yml ItemsDeleteItemsLiveRequestItemsItem: properties: - itemId: + id: type: string docs: Unique identifier for the Item cmsLocaleIds: @@ -113,20 +122,54 @@ types: CreateBulkCollectionItemRequestBodyFieldData: discriminated: false union: - - Single CMS Item + - type: Single CMS Item - docs: A list of CMS items to create type: list source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true + Item IDs: + docs: An array of Item IDs in a single locale + properties: + itemIds: + type: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsPublishItemRequestItemsItemsItem: + properties: + id: + type: string + docs: The ID of the CMS item + cmsLocaleIds: + type: optional> + docs: Array of identifiers for the locales where the item will be published + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Item IDs with Locales: + docs: An array of Item IDs with included `cmsLocaleIds` + properties: + items: + type: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsPublishItemRequest: + discriminated: false + union: + - type: Item IDs + docs: An array of Item IDs in a single locale + - type: Item IDs with Locales + docs: An array of Item IDs with included `cmsLocaleIds` + source: + openapi: ../../../openapi/referenced-specs/v2.yml ItemsPublishItemResponse: properties: publishedItemIds: optional> errors: optional> source: openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: ../__package__.yml service: auth: false base-path: '' @@ -166,10 +209,13 @@ service: docs: 'Maximum number of records to be returned (max limit: 100)' name: type: optional - docs: The name of the item(s) + docs: Filter by the exact name of the item(s) slug: type: optional - docs: The slug of the item + docs: Filter by the exact slug of the item + lastPublished: + type: optional + docs: Filter by the last published date of the item(s) sortBy: type: optional docs: Sort results by the provided value @@ -179,6 +225,7 @@ service: response: docs: Request was successful type: root.CollectionItemList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -229,7 +276,7 @@ service: To create items across multiple locales, please use [this - endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -241,11 +288,20 @@ service: docs: Unique identifier for a Collection display-name: Create Collection Item(s) request: - body: ItemsCreateItemRequest + body: ItemsCreateItemRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsCreateItemRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -322,8 +378,8 @@ service: Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary + locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -338,7 +394,7 @@ service: name: ItemsDeleteItemsRequest body: properties: - items: optional> + items: list content-type: application/json errors: - root.BadRequestError @@ -350,17 +406,22 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 - request: {} + request: + items: + - id: 580e64008c9a982ac9b8b754 update-items: path: /collections/{collection_id}/items method: PATCH auth: true docs: > - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. + + + The limit for this endpoint is 100 items. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary + locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -373,13 +434,21 @@ service: display-name: Update Collection Items request: name: ItemsUpdateItemsRequest + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: items: optional> content-type: application/json response: docs: Request was successful - type: root.CollectionItem + type: ItemsUpdateItemsResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -418,19 +487,55 @@ service: featured: false response: body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + pagination: + limit: 25 + offset: 0 + total: 4 - name: MultipleItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 @@ -454,113 +559,46 @@ service: department: Product response: body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Multiple items updated across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Mulitple items updated in a single locale - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' + items: + - id: 62b720ef280c7a7a3be8cabe + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2022-06-30T13:35:20.878Z' + lastUpdated: '2022-06-25T14:51:27.809Z' + createdOn: '2022-06-25T14:51:27.809Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 62c880ef281c7b7b4cf9dabc + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2023-04-15T10:25:18.123Z' + lastUpdated: '2023-04-10T11:45:30.567Z' + createdOn: '2023-04-10T11:45:30.567Z' + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + pagination: + limit: 25 + offset: 0 + total: 2 list-items-live: path: /collections/{collection_id}/items/live method: GET auth: true docs: | - List of all live Items within a Collection. + List all published items in a collection. + + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + Required scope | `CMS:read` source: @@ -590,10 +628,13 @@ service: docs: 'Maximum number of records to be returned (max limit: 100)' name: type: optional - docs: The name of the item(s) + docs: Filter by the exact name of the item(s) slug: type: optional - docs: The slug of the item + docs: Filter by the exact slug of the item + lastPublished: + type: optional + docs: Filter by the last published date of the item(s) sortBy: type: optional docs: Sort results by the provided value @@ -603,6 +644,8 @@ service: response: docs: Request was successful type: root.CollectionItemList + status-code: 200 + url: Data API errors: - root.BadRequestError - root.UnauthorizedError @@ -648,13 +691,13 @@ service: method: POST auth: true docs: > - Create live Item(s) in a Collection. The Item(s) will be published to - the live site. + Create item(s) in a collection that will be immediately published to the + live site. To create items across multiple locales, [please use this - endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + endpoint.](/data/reference/cms/collection-items/staged-items/create-items) @@ -667,11 +710,20 @@ service: docs: Unique identifier for a Collection display-name: Create Live Collection Item(s) request: - body: ItemsCreateItemLiveRequest + body: ItemsCreateItemLiveRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsCreateItemLiveRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -745,14 +797,12 @@ service: method: DELETE auth: true docs: > - Remove an item or multiple items (up to 100 items) from the live site. - Deleting published items will unpublish the items from the live site and - set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` + property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be unpublished only in the primary - locale. + Items will only be unpublished in the + primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -762,12 +812,12 @@ service: collection_id: type: string docs: Unique identifier for a Collection - display-name: Delete Live Collection Items + display-name: Unpublish Live Collection Items request: name: ItemsDeleteItemsLiveRequest body: properties: - items: optional> + items: list content-type: application/json errors: - root.BadRequestError @@ -778,18 +828,20 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 - request: {} + request: + items: + - id: 580e64008c9a982ac9b8b754 update-items-live: path: /collections/{collection_id}/items/live method: PATCH auth: true docs: > - Update a single live item or multiple live items (up to 100) in a - Collection + Update a single published item or multiple published items (up to 100) + in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary + locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -802,6 +854,13 @@ service: display-name: Update Live Collection Items request: name: ItemsUpdateItemsLiveRequest + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: items: optional> @@ -809,10 +868,12 @@ service: response: docs: Request was successful type: root.CollectionItemListNoPagination + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: @@ -850,44 +911,44 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias @@ -918,44 +979,44 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias @@ -994,49 +1055,49 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias featured: false - - name: Mulitple items updated in a single locale + - name: Multiple items updated in a single locale path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: @@ -1101,9 +1162,11 @@ service: corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + + Required scope | `CMS:write` source: @@ -1115,6 +1178,13 @@ service: display-name: Create Collection Items request: name: CreateBulkCollectionItemRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: cmsLocaleIds: @@ -1129,12 +1199,13 @@ service: isDraft: type: optional docs: Indicates whether the item is in draft state. - default: false + default: true fieldData: CreateBulkCollectionItemRequestBodyFieldData content-type: application/json response: docs: Request was successful type: root.BulkCollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -1173,7 +1244,7 @@ service: date: '2022-11-18T00:00:00.000Z' featured: false color: '#db4b68' - - name: Create multiple items across multipel locales + - name: Create multiple items across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: @@ -1298,6 +1369,8 @@ service: response: docs: Request was successful type: root.CollectionItem + status-code: 200 + url: Production errors: - root.BadRequestError - root.UnauthorizedError @@ -1327,10 +1400,8 @@ service: path: /collections/{collection_id}/items/{item_id} method: DELETE auth: true - docs: > - Delete an Item from a Collection. This endpoint does not currently - support bulk deletion. - + docs: | + Delete an item from a collection. Required scope | `CMS:write` source: @@ -1383,10 +1454,19 @@ service: display-name: Update Collection Item request: body: root.CollectionItemPatchSingle + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsUpdateItemRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1428,6 +1508,11 @@ service: docs: | Get details of a selected Collection live Item. + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + + Required scope | `CMS:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -1452,6 +1537,8 @@ service: response: docs: Request was successful type: root.CollectionItem + status-code: 200 + url: Data API errors: - root.BadRequestError - root.UnauthorizedError @@ -1482,11 +1569,12 @@ service: 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. + Unpublish a live item from the site and set the `isDraft` property to + `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this + endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -1499,7 +1587,7 @@ service: item_id: type: string docs: Unique identifier for an Item - display-name: Delete Live Collection Item + display-name: Unpublish Live Collection Item request: name: ItemsDeleteItemLiveRequest query-parameters: @@ -1542,14 +1630,24 @@ service: display-name: Update Live Collection Item request: body: root.CollectionItemPatchSingle + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsUpdateItemLiveRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: @@ -1596,14 +1694,12 @@ service: docs: Unique identifier for a Collection display-name: Publish Collection Item request: - name: ItemsPublishItemRequest - body: - properties: - itemIds: list + body: ItemsPublishItemRequest content-type: application/json response: docs: Request was successful type: ItemsPublishItemResponse + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -1612,11 +1708,52 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: PrimaryLocale + path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: itemIds: - - itemIds + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + - 643fd856d66b6528195ee2cc + response: + body: + publishedItemIds: + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + errors: + - Staging item ID 643fd856d66b6528195ee2cf not found. + - name: SecondaryLocale + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 643fd856d66b6528195ee2ca + cmsLocaleIds: + - 653ad57de882f528b32e810e + - id: 643fd856d66b6528195ee2cb + cmsLocaleIds: + - 653ad57de882f528b32e810e + - id: 643fd856d66b6528195ee2cc + cmsLocaleIds: + - 653ad57de882f528b32e810e + response: + body: + publishedItemIds: + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + errors: + - Staging item ID 643fd856d66b6528195ee2cf not found. + - name: MultipleLocales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 643fd856d66b6528195ee2ca + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 response: body: publishedItemIds: diff --git a/.mock/definition/comments.yml b/.mock/definition/comments.yml new file mode 100644 index 0000000..91de1be --- /dev/null +++ b/.mock/definition/comments.yml @@ -0,0 +1,40 @@ +imports: + root: __package__.yml +webhooks: + comment_created: + audiences: [] + method: POST + display-name: New Comment Thread + headers: {} + payload: root.Comment + examples: + - payload: + triggerType: comment_created + payload: + threadId: 679d2ddb5196117ad04d1ffa + commentId: 679d2ddb5196117ad04d1ff8 + type: new_comment + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ffa&pageId=679826b3b20b045e176bc4bc + content: 'This comment mentions another user [[6287ec36a841b25637c663df]] ' + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + docs: | + Information about a new comment thread or reply + + + There may be a delay of up to 5 minutes before new comments appear in the system and trigger the webhook notification. + diff --git a/.mock/definition/components.yml b/.mock/definition/components.yml index b9eb7d6..2aacf19 100644 --- a/.mock/definition/components.yml +++ b/.mock/definition/components.yml @@ -22,6 +22,9 @@ service: request: name: ComponentsListRequest query-parameters: + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: type: optional docs: 'Maximum number of records to be returned (max limit: 100)' @@ -33,6 +36,7 @@ service: response: docs: Request was successful type: root.ComponentList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -42,6 +46,8 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + branchId: 68026fa68ef6dc744c75b833 response: body: components: @@ -59,13 +65,9 @@ service: 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 @@ -77,7 +79,8 @@ service: auth: true docs: > Get static content from a component definition. This includes text - nodes, image nodes and nested component instances. + nodes, image nodes, select nodes, text input nodes, submit button nodes, + and nested component instances. To retrieve dynamic content set by component properties, use the [get component @@ -109,6 +112,9 @@ service: docs: >- Unique identifier for a specific locale. Applicable, when using localization. + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: type: optional docs: 'Maximum number of records to be returned (max limit: 100)' @@ -120,6 +126,7 @@ service: response: docs: Request was successful type: root.ComponentDom + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -127,76 +134,58 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - name: ComponentDOM - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - response: - body: - componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 - nodes: - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad623 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad627 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad629 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad631 - componentId: 6258612d1ee792848f805dcf - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 - type: Plain Text - text: - text: Don't Panic! - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - type: Rich Text - text: - html:

Always know where your towel is.

- pagination: - limit: 4 - offset: 0 - total: 4 - - name: LocalizedComponentDOM - path-parameters: + - path-parameters: site_id: 580e63e98c9a982ac9b8b741 component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 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 + - id: id + text: {} + attributes: + key: value + type: text + - id: id + text: {} + attributes: + key: value + type: text + - id: id + image: {} + attributes: + key: value + type: image + - id: id + placeholder: placeholder + attributes: + key: value + type: text-input + - id: id + choices: + - value: value + text: text + attributes: + key: value + type: select + - id: id + value: value + waitingText: waitingText + attributes: + key: value + type: submit-button + - id: id + componentId: componentId propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: 69118560-d0bc-15fc-bbf8-b8fe5f6535c2 - componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + type: component-instance pagination: - limit: 100 + limit: 7 offset: 0 - total: 3 + total: 7 update-content: path: /sites/{site_id}/components/{component_id}/dom method: POST @@ -244,6 +233,9 @@ service: docs: >- Unique identifier for a specific locale. Applicable, when using localization. + branchId: + type: optional + docs: Scope the operation to work on a specific branch. body: properties: nodes: @@ -255,6 +247,7 @@ service: response: docs: Request was successful type: ComponentsUpdateContentResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -268,6 +261,7 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 request: nodes: - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 @@ -276,6 +270,17 @@ service: text: >-

Don't Panic!

Always know where your towel is.

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad635 + choices: + - value: choice-1 + text: First choice + - value: choice-2 + text: Second choice + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad642 + placeholder: Enter something here... + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad671 + value: Submit + waitingText: Submitting... - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 @@ -291,10 +296,10 @@ service: method: GET auth: true docs: > - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. @@ -318,6 +323,9 @@ service: docs: >- Unique identifier for a specific locale. Applicable, when using localization. + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: type: optional docs: 'Maximum number of records to be returned (max limit: 100)' @@ -329,6 +337,7 @@ service: response: docs: Request was successful type: root.ComponentProperties + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -341,6 +350,7 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 response: body: componentId: 658205daa3e8206a523b5ad4 @@ -366,18 +376,17 @@ service: method: POST auth: true docs: > - Update the property default values of a component definition in a + Update the default property values of a component definition in a specificed locale. - Before making updates: - - 1. Use the [get component + Before making updates, use the [get component properties](/data/reference/pages-and-components/components/get-properties) - endpoint to identify available properties + endpoint to identify properties that can be updated in a secondary + locale. - The request requires a secondary locale ID. If a locale is + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. @@ -401,6 +410,9 @@ service: docs: >- Unique identifier for a specific locale. Applicable, when using localization. + branchId: + type: optional + docs: Scope the operation to work on a specific branch. body: properties: properties: @@ -412,6 +424,7 @@ service: response: docs: Request was successful type: ComponentsUpdatePropertiesResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -424,6 +437,7 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 request: properties: - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 @@ -442,8 +456,12 @@ types: ComponentDomWriteNodesItem: discriminated: false union: - - root.TextNodeWrite - - root.ComponentInstanceNodePropertyOverridesWrite + - type: root.Text Node + - type: root.Component Instance + - type: root.Select + - type: root.Text Input + - type: root.Submit Button + - type: root.Search Button source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true diff --git a/.mock/definition/ecommerce.yml b/.mock/definition/ecommerce.yml index 1a2ca95..b3e9857 100644 --- a/.mock/definition/ecommerce.yml +++ b/.mock/definition/ecommerce.yml @@ -22,6 +22,7 @@ service: response: docs: Request was successful type: root.EcommerceSettings + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/forms.yml b/.mock/definition/forms.yml index 9eac177..f7044cf 100644 --- a/.mock/definition/forms.yml +++ b/.mock/definition/forms.yml @@ -33,6 +33,7 @@ service: response: docs: Request was successful type: root.FormList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -108,6 +109,7 @@ service: response: docs: Request was successful type: root.Form + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -127,7 +129,6 @@ service: 660d5bcc9c0772150459dfb1: displayName: Name type: Plain - placeholder: Enter your email userVisible: true 589a331aa51e760df7ccb89d: displayName: Email @@ -137,7 +138,6 @@ service: responseSettings: redirectUrl: https://example.com redirectMethod: GET - redirectAction: POST https://example.com sendEmailConfirmation: true id: 589a331aa51e760df7ccb89e siteId: 580e63e98c9a982ac9b8b741 @@ -153,6 +153,12 @@ service: docs: | List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -175,6 +181,7 @@ service: response: docs: Request was successful type: root.FormSubmissionList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -226,6 +233,7 @@ service: response: docs: Request was successful type: root.FormSubmission + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -246,6 +254,33 @@ service: 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 @@ -274,6 +309,7 @@ service: response: docs: Request was successful type: root.FormSubmission + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -296,7 +332,119 @@ service: formResponse: First Name: Arthur Last Name: Dent + list-submissions-by-site: + path: /sites/{site_id}/form_submissions + method: GET + auth: true + docs: > + List form submissions for a given site. This endpoint differs from the + existing [List Form Submissions + endpoint](/data/reference/forms/form-submissions/list-submissions) by + accepting `siteId` as a path parameter and `elementId` as a query + parameter. You can get the `elementId` from the [List forms + endpoint](/data/reference/forms/forms/list). + + + + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Form Submissions by Site + request: + name: FormsListSubmissionsBySiteRequest + query-parameters: + elementId: + type: optional + docs: Identifier for an element + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.FormSubmissionList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + elementId: 18259716-3e5a-646a-5f41-5dc4b9405aa0 + 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 source: openapi: ../../../openapi/referenced-specs/v2.yml display-name: Forms docs: Forms are forms that are created on your Webflow site. +webhooks: + form_submission: + audiences: [] + method: POST + display-name: Form Submission + headers: {} + payload: root.FormSubmissionTrigger + examples: + - payload: + triggerType: form_submission + payload: + name: Contact Us + siteId: 65427cf400e02b306eaa049c + data: + First Name: Zaphod + Last Name: Beeblebrox + email: zaphod@heartofgold.ai + Phone Number: 15550000000 + schema: + - fieldName: First Name + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c4 + - fieldName: Last Name + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c5 + - fieldName: email + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c6 + - fieldName: Phone Number + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c7 + submittedAt: '2022-09-14T12:35:16.117Z' + id: 6321ca84df3949bfc6752327 + formId: 65429eadebe8a9f3a30f62d0 + formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 + docs: Information about a form that was subitted diff --git a/.mock/definition/inventory.yml b/.mock/definition/inventory.yml index 5e69c29..13694c0 100644 --- a/.mock/definition/inventory.yml +++ b/.mock/definition/inventory.yml @@ -5,7 +5,7 @@ service: base-path: '' endpoints: list: - path: /collections/{collection_id}/items/{item_id}/inventory + path: /collections/{sku_collection_id}/items/{sku_id}/inventory method: GET auth: true docs: | @@ -15,16 +15,19 @@ service: source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: - collection_id: + sku_collection_id: type: string - docs: Unique identifier for a Collection - item_id: + docs: >- + Unique identifier for a SKU collection. Use the List Collections API + to find this ID. + sku_id: type: string - docs: Unique identifier for an Item + docs: Unique identifier for a SKU display-name: List Inventory response: docs: Request was successful type: root.InventoryItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -35,15 +38,15 @@ service: - root.InternalServerError examples: - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 + sku_collection_id: 6377a7c4b7a79608c34a46f7 + sku_id: 5e8518516e147040726cc415 response: body: id: 5bfedb42bab0ad90fa7dad39 quantity: 100 inventoryType: finite update: - path: /collections/{collection_id}/items/{item_id}/inventory + path: /collections/{sku_collection_id}/items/{sku_id}/inventory method: PATCH auth: true docs: > @@ -64,12 +67,14 @@ service: source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: - collection_id: + sku_collection_id: type: string - docs: Unique identifier for a Collection - item_id: + docs: >- + Unique identifier for a SKU collection. Use the List Collections API + to find this ID. + sku_id: type: string - docs: Unique identifier for an Item + docs: Unique identifier for a SKU display-name: Update Item Inventory request: name: InventoryUpdateRequest @@ -88,6 +93,7 @@ service: response: docs: Request was successful type: root.InventoryItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -98,8 +104,8 @@ service: - root.InternalServerError examples: - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 + sku_collection_id: 6377a7c4b7a79608c34a46f7 + sku_id: 5e8518516e147040726cc415 request: inventoryType: infinite response: @@ -120,3 +126,23 @@ types: inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml + EcommInventoryChangedPayload: + properties: + triggerType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml +webhooks: + ecomm_inventory_changed: + audiences: [] + method: POST + display-name: Updated eComm Inventory + headers: {} + payload: EcommInventoryChangedPayload + examples: + - name: WebhookInventoryChanged + payload: + triggerType: ecomm_inventory_changed + payload: + ref: ./schemas/inventory.yml#/InventoryItem/example + docs: Information about updated ecommerce inventory values diff --git a/.mock/definition/items.yml b/.mock/definition/items.yml new file mode 100644 index 0000000..f65b6d7 --- /dev/null +++ b/.mock/definition/items.yml @@ -0,0 +1,111 @@ +imports: + root: __package__.yml +webhooks: + collection_item_created: + audiences: [] + method: POST + display-name: Collection Item Created + headers: {} + payload: root.CollectionItemCreated + examples: + - payload: + triggerType: collection_item_created + payload: + id: 580e64008c9a982ac9b8b754 + workspaceId: 625860a7a6c16d624927122f + siteId: 65427cf400e02b306eaa049c + collectionId: 664243617fcc8b464b23c4ee + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + isArchived: false + isDraft: false + fieldData: + name: Pan-Galactic Gargle Blaster + slug: pan-galactic-gargle-blaster + docs: Information about a new collection item + collection_item_changed: + audiences: [] + method: POST + display-name: Collection Item Updated + headers: {} + payload: root.CollectionItemChanged + examples: + - payload: + triggerType: collection_item_changed + payload: + id: id + workspaceId: workspaceId + siteId: siteId + collectionId: collectionId + fieldData: + name: name + slug: slug + docs: Information about an updated collection item + collection_item_deleted: + audiences: [] + method: POST + display-name: Collection Item Deleted + headers: {} + payload: root.CollectionItemRemoved + examples: + - payload: + triggerType: collection_item_deleted + payload: + id: 66424365e972c886137a1cf1 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + cmsLocaleId: 681442a144bb80bd00480fda + lastUpdated: '2025-05-28T04:44:33Z' + createdOn: '2025-05-28T04:27:12Z' + isArchived: false + isDraft: false + fieldData: + name: Earth + slug: earth + description: Mostly harmless + color: '#0000FF' + type: planet + galaxy: Milky Way + docs: Information about a deleted collection item + collection_item_published: + audiences: [] + method: POST + display-name: Collection Item Published + headers: {} + payload: root.CollectionItemPublished + examples: + - payload: + triggerType: collection_item_published + payload: + id: 6321ca84df3949bfc6752327 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + docs: Information about a collection item that was published + collection_item_unpublished: + audiences: [] + method: POST + display-name: Collection Item Unpublished + headers: {} + payload: root.CollectionItemUnpublished + examples: + - payload: + triggerType: collection_item_unpublished + payload: + id: 66424365e972c886137a1cf1 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + cmsLocaleId: 681442a144bb80bd00480fda + lastUpdated: '2025-05-28T04:44:33Z' + createdOn: '2025-05-28T04:27:12Z' + isArchived: false + isDraft: false + fieldData: + name: Anna Gunn + slug: anna-gunn + _locale: 681442a144bb80bd00480fda + _noSearch: false + docs: Information about a collection item that was removed from the live site diff --git a/.mock/definition/orders.yml b/.mock/definition/orders.yml index b2802cf..d7243c7 100644 --- a/.mock/definition/orders.yml +++ b/.mock/definition/orders.yml @@ -57,6 +57,7 @@ service: response: docs: Request was successful type: root.OrderList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -81,11 +82,6 @@ service: 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' @@ -155,7 +151,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -180,7 +176,7 @@ service: variantSKU: incredible-bronze-towels-sleek-frozen-incredible-metal variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg variantPrice: unit: USD value: '5892' @@ -201,13 +197,6 @@ service: expires: year: 2025 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -235,11 +224,7 @@ service: 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' @@ -308,7 +293,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -335,7 +320,7 @@ service: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -359,13 +344,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -436,6 +414,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -537,7 +516,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -560,7 +539,7 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -571,12 +550,10 @@ service: 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: @@ -586,13 +563,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -677,6 +647,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -779,7 +750,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -802,7 +773,7 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -813,12 +784,10 @@ service: 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: @@ -828,13 +797,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -909,6 +871,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1011,7 +974,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -1034,7 +997,7 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -1045,12 +1008,10 @@ service: 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: @@ -1060,13 +1021,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -1132,6 +1086,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1233,7 +1188,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -1256,7 +1211,7 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -1267,12 +1222,10 @@ service: 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: @@ -1282,13 +1235,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -1363,6 +1309,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1465,7 +1412,7 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' @@ -1488,7 +1435,7 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' @@ -1499,12 +1446,10 @@ service: 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: @@ -1514,13 +1459,6 @@ service: expires: year: 2024 month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq customData: - key: value metadata: @@ -1569,3 +1507,371 @@ service: openapi: ../../../openapi/referenced-specs/v2.yml display-name: Orders docs: Orders are the orders for your Webflow site. +webhooks: + ecomm_new_order: + audiences: [] + method: POST + display-name: New eComm Order + headers: {} + payload: root.NewOrder + examples: + - payload: + triggerType: ecomm_new_order + payload: + orderId: fc7-128 + status: unfulfilled + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + docs: Information about a new ecommerce order + ecomm_order_changed: + audiences: [] + method: POST + display-name: Updated eComm Order + headers: {} + payload: root.UpdatedOrder + examples: + - payload: + triggerType: ecomm_order_changed + payload: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + docs: Information about an updated ecommerce order diff --git a/.mock/definition/pages.yml b/.mock/definition/pages.yml index 62de7dc..4f46a95 100644 --- a/.mock/definition/pages.yml +++ b/.mock/definition/pages.yml @@ -38,6 +38,7 @@ service: response: docs: Request was successful type: root.PageList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -56,15 +57,13 @@ service: 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 + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -83,15 +82,12 @@ service: 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: >- @@ -138,6 +134,7 @@ service: response: docs: Request was successful type: root.Page + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -155,15 +152,13 @@ service: 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 + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -185,6 +180,10 @@ service: docs: | Update Page-level metadata, including SEO and Open Graph fields. + + Note: When updating Page Metadata in secondary locales, you may only add `slug` to the request if your Site has the [Advanced or Enterprise Localization](https://webflow.com/localization) add-on. + + Required scope | `pages:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -194,18 +193,32 @@ service: docs: Unique identifier for a Page display-name: Update Page Metadata request: - body: root.Page + name: PageMetadataWrite query-parameters: localeId: type: optional docs: >- Unique identifier for a specific locale. Applicable, when using localization. - name: UpdatePageSettingsRequest + body: + properties: + title: + type: optional + docs: Title for the page + slug: + type: optional + docs: Slug for the page + seo: + type: optional + docs: SEO-related fields for the Page + openGraph: + type: optional + docs: Open Graph fields for the Page content-type: application/json response: docs: Request was successful type: root.Page + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -218,16 +231,8 @@ service: query-parameters: localeId: 65427cf400e02b306eaa04a0 request: - id: 6596da6045e56dee495bcbba - siteId: 6258612d1ee792848f805dcf title: Guide to the Galaxy slug: guide-to-the-galaxy - createdOn: '2024-03-11T10:42:00Z' - lastUpdated: '2024-03-11T10:42:42Z' - archived: false - draft: false - canBranch: true - isBranch: false seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -240,23 +245,19 @@ service: Dive deep into the mysteries of the universe with your guide to everything galactic. descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/guide-to-the-galaxy response: body: id: 6596da6045e56dee495bcbba 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 + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -276,16 +277,19 @@ service: method: GET auth: true docs: > - Get static content from a static page. This includes text nodes, image - nodes and component instances. + Get content from a static page. This includes text nodes, image nodes, + select nodes, text input nodes, submit button 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 contents of components in the page use the [get - component - content](/data/reference/pages-and-components/components/get-content) + + 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 provide a Locale ID in your request, the response + If you do not include a `localeId` in your request, the response will return any content that can be localized from the Primary locale. @@ -317,6 +321,7 @@ service: response: docs: Request was successful type: root.Dom + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -325,48 +330,57 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - name: PageDOM - path-parameters: + - path-parameters: page_id: 63c720f9347c2139b248e552 query-parameters: localeId: 65427cf400e02b306eaa04a0 response: body: pageId: 658205daa3e8206a523b5ad4 + branchId: 68026fa68ef6dc744c75b833 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 + - id: id + text: {} + attributes: + key: value + type: text + - id: id + text: {} + attributes: + key: value + type: text + - id: id + image: {} + attributes: + key: value + type: image + - id: id + choices: + - value: value + text: text + attributes: + key: value + type: select + - id: id + placeholder: placeholder + attributes: + key: value + type: text-input + - id: id + text: {} + attributes: + key: value + type: text + - id: id + componentId: componentId propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad631 - componentId: 6258612d1ee792848f805dcf - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 - type: Plain Text - label: Catchphrase - text: - text: Don't Panic! - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - type: Rich Text - label: Tagline - text: - html:

Always know where your towel is.

+ type: component-instance pagination: limit: 4 offset: 0 total: 4 + lastUpdated: '2016-10-24T19:42:38Z' update-static-content: path: /pages/{page_id}/dom method: POST @@ -418,6 +432,7 @@ service: response: docs: Request was successful type: UpdateStaticContentResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -438,6 +453,17 @@ service: text: >-

Don't Panic!

Always know where your towel is.

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

Required scope | `site_activity:read` + 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: @@ -32,6 +38,7 @@ service: response: docs: A list of site activity logs type: root.SiteActivityLogResponse + status-code: 200 errors: - root.ForbiddenError - root.NotFoundError @@ -53,10 +60,6 @@ service: displayName: John Doe resourceId: 654c16c7b229e56bcf26870c resourceName: foo-bar - newValue: newValue - previousValue: previousValue - payload: - key: value pagination: limit: 25 offset: 0 diff --git a/.mock/definition/sites/comments.yml b/.mock/definition/sites/comments.yml new file mode 100644 index 0000000..b14a9e5 --- /dev/null +++ b/.mock/definition/sites/comments.yml @@ -0,0 +1,323 @@ +types: + CommentsListCommentThreadsRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentThreadsRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsGetCommentThreadRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsGetCommentThreadRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentRepliesRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentRepliesRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list-comment-threads: + path: /sites/{site_id}/comments + method: GET + auth: true + docs: | + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Comment Threads + request: + name: CommentsListCommentThreadsRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentThreadList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + comments: + - id: 679d2ddb5196117ad04d1ffa + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: 'Let''s go to the pub! [[6287ec36a841b25637c663df]] ' + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + - id: 679d2ddb5196117ad04d1ffc + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: >- + You have five minutes left to drink it + [[6287ec36a841b25637c663df]] + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + pagination: + limit: 2 + offset: 0 + total: 2 + get-comment-thread: + path: /sites/{site_id}/comments/{comment_thread_id} + method: GET + auth: true + docs: | + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + comment_thread_id: + type: string + docs: Unique identifier for a Comment Thread + display-name: Get Comment Thread + request: + name: CommentsGetCommentThreadRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentThread + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + comment_thread_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + id: 580e64008c9a982ac9b8b754 + siteId: 580e64008c9a982ac9b8b754 + pageId: 580e64008c9a982ac9b8b754 + localeId: 580e64008c9a982ac9b8b754 + itemId: 580e64008c9a982ac9b8b754 + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: This is a comment reply + isResolved: true + author: + userId: userId + email: email + name: name + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + list-comment-replies: + path: /sites/{site_id}/comments/{comment_thread_id}/replies + method: GET + auth: true + docs: | + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + comment_thread_id: + type: string + docs: Unique identifier for a Comment Thread + display-name: List Comment Replies + request: + name: CommentsListCommentRepliesRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentReplyList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + comment_thread_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + comments: + - id: 679d2ddb5196117ad04d1ffa + commentId: 679d2ddb5196117ad04d1ff8 + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + breakpoint: main + content: >- + This comment mentions another user + [[6287ec36a841b25637c663df]] + isResolved: false + author: + id: id + email: email + name: name + mentionedUsers: + - id: id + email: arthur.dent@example.com + name: Arthur Dent + lastUpdated: '2025-01-31T20:08:59.759Z' + createdOn: '2025-01-31T20:08:59.759Z' + pagination: + limit: 2 + offset: 0 + total: 1 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/plans.yml b/.mock/definition/sites/plans.yml index ae9de6d..f507373 100644 --- a/.mock/definition/sites/plans.yml +++ b/.mock/definition/sites/plans.yml @@ -8,9 +8,14 @@ service: path: /sites/{site_id}/plan method: GET auth: true - docs: | + docs: > Get site plan details for the specified Site. + + This endpoint requires an Enterprise + workspace. + + Required scope | `sites:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -22,6 +27,7 @@ service: response: docs: Request was successful type: root.SitePlan + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/sites/redirects.yml b/.mock/definition/sites/redirects.yml index b104d86..746923b 100644 --- a/.mock/definition/sites/redirects.yml +++ b/.mock/definition/sites/redirects.yml @@ -9,13 +9,16 @@ service: method: GET auth: true docs: > - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise + workspace. + Required scope: `sites:read` source: @@ -24,10 +27,11 @@ service: site_id: type: string docs: Unique identifier for a Site - display-name: Get URL redirects + display-name: Get 301 redirects response: docs: Request was successful type: root.Redirects + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -55,7 +59,7 @@ service: method: POST auth: true docs: > - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its @@ -64,6 +68,10 @@ service: restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -71,13 +79,14 @@ service: site_id: type: string docs: Unique identifier for a Site - display-name: Create a URL redirect + display-name: Create a 301 redirect request: body: root.Redirect content-type: application/json response: docs: Request was successful type: root.Redirect + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -101,12 +110,18 @@ service: method: DELETE auth: true docs: > - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -117,10 +132,11 @@ service: redirect_id: type: string docs: Unique identifier site rediect - display-name: Delete URL redirects + display-name: Delete 301 redirects response: docs: Request was successful type: root.Redirects + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -148,8 +164,14 @@ service: path: /sites/{site_id}/redirects/{redirect_id} method: PATCH auth: true - docs: | - Update a URL redirection rule from a site. + docs: > + Update a 301 redirection rule from a site. + + + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -160,13 +182,14 @@ service: redirect_id: type: string docs: Unique identifier site rediect - display-name: Update URL redirect + display-name: Update 301 redirect request: body: root.Redirect content-type: application/json response: docs: Request was successful type: root.Redirect + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/sites/robotsTxt.yml b/.mock/definition/sites/robotsTxt.yml new file mode 100644 index 0000000..1259a14 --- /dev/null +++ b/.mock/definition/sites/robotsTxt.yml @@ -0,0 +1,221 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get: + path: /sites/{site_id}/robots_txt + method: GET + auth: true + docs: > + Retrieve the robots.txt configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get robots.txt + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + put: + path: /sites/{site_id}/robots_txt + method: PUT + auth: true + docs: > + Replace the `robots.txt` configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope | `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Replace robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + delete: + path: /sites/{site_id}/robots_txt + method: DELETE + auth: true + docs: > + Remove specific rules for a user-agent in your `robots.txt` file. To + delete all rules for a user-agent, provide an empty rule set. This will + remove the user-agent's entry entirely, leaving it subject to your + site's default crawling behavior. + + + **Note:** Deleting a user-agent with no rules will make the user-agent's + access unrestricted unless other directives apply. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: '*' + allows: + - /public + disallows: + - /bubbles + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + patch: + path: /sites/{site_id}/robots_txt + method: PATCH + auth: true + docs: > + Update the `robots.txt` configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope | `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Update robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/scripts.yml b/.mock/definition/sites/scripts.yml index 92ad0e4..042c848 100644 --- a/.mock/definition/sites/scripts.yml +++ b/.mock/definition/sites/scripts.yml @@ -8,13 +8,12 @@ service: path: /sites/{site_id}/custom_code method: GET auth: true - docs: > - Get all registered scripts that have been applied to a specific Site. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + docs: | + Get all scripts applied to a site by the App. + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` source: @@ -27,6 +26,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -56,20 +56,16 @@ service: method: PUT auth: true docs: > - Add a registered script to a Site. - - - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered + Apply registered scripts to a site. If you have multiple scripts your + App needs to apply or maintain on a site, ensure they are always + included in the request body for this endpoint. To remove individual + scripts, simply call this endpoint without the script in the request + body. - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - `custom_code` endpoints. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -86,6 +82,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -125,11 +122,18 @@ service: method: DELETE auth: true docs: > - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will + not remove scripts from the site's registered scripts. + + + To remove individual scripts applied by the App, use the [Add/Update + Custom + Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) + endpoint. - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an + [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -154,11 +158,15 @@ service: method: GET auth: true docs: > - Get all instances of Custom Code applied to a Site or Pages. + Get a list of scripts that have been applied to a site and/or individual + pages. - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -183,6 +191,7 @@ service: response: docs: Request was successful type: root.ListCustomCodeBlocks + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -196,7 +205,6 @@ service: body: blocks: - siteId: 6258612d1ee792848f805dcf - pageId: pageId type: site scripts: - id: chartjs diff --git a/.mock/definition/sites/wellKnown.yml b/.mock/definition/sites/wellKnown.yml new file mode 100644 index 0000000..0ba91e1 --- /dev/null +++ b/.mock/definition/sites/wellKnown.yml @@ -0,0 +1,114 @@ +types: + WellKnownFileContentType: + enum: + - value: application/json + name: ApplicationJson + - value: text/plain + name: TextPlain + docs: The content type of the file. Defaults to application/json + default: application/json + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + put: + path: /sites/{site_id}/well_known + method: PUT + auth: true + docs: > + Upload a supported well-known file to a site. + + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Set a well-known file + request: + name: WellKnownFile + body: + properties: + fileName: + type: string + docs: The name of the file + fileData: + type: string + docs: The contents of the file + contentType: + type: optional + docs: The content type of the file. Defaults to application/json + default: application/json + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + fileName: fileName + fileData: fileData + delete: + path: /sites/{site_id}/well_known + method: DELETE + auth: true + docs: > + Delete existing well-known files from a site. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete a well-known file + request: + name: WellKnownDeleteRequest + body: + properties: + fileNames: + type: optional> + docs: A list of file names to delete + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: {} + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/token.yml b/.mock/definition/token.yml index 033c5c3..4b1cc1a 100644 --- a/.mock/definition/token.yml +++ b/.mock/definition/token.yml @@ -18,6 +18,7 @@ service: response: docs: Request was successful type: root.AuthorizedUser + status-code: 200 errors: - root.UnauthorizedError - root.ForbiddenError @@ -44,6 +45,7 @@ service: response: docs: Request was successful type: root.Authorization + status-code: 200 errors: - root.UnauthorizedError examples: diff --git a/.mock/definition/users.yml b/.mock/definition/users.yml index 19a17cc..58a505f 100644 --- a/.mock/definition/users.yml +++ b/.mock/definition/users.yml @@ -33,23 +33,144 @@ types: docs: Sorts users in descending order based on their update date source: openapi: ../../../openapi/referenced-specs/v2.yml - UsersUpdateRequestData: + UserAccountAddedPayloadPayloadData: + docs: The data about the user account that was added properties: - name: + accept-privacy-policy: optional + accept-communications: optional + email: optional + name: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserAccountAddedPayloadPayload: + properties: + data: + type: optional + docs: The data about the user account that was added + id: type: optional - docs: | - The name of the user - accept-privacy: + docs: Unique identifier for the User + isEmailVerified: type: optional - docs: | - Boolean indicating if the user has accepted the privacy policy - accept-communications: + 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: optional + accessGroups: + type: optional> + docs: Access groups the user belongs to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserAccountAddedPayload: + properties: + triggerType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccountUpdatedPayloadPayloadData: + docs: The data about the user account that was added + properties: + accept-privacy-policy: optional + accept-communications: optional + email: optional + name: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserAccountUpdatedPayloadPayload: + properties: + data: + type: optional + docs: The data about the user account that was added + id: + type: optional + docs: Unique identifier for the User + isEmailVerified: type: optional - docs: | - Boolean indicating if the user has accepted to receive communications + 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: optional + accessGroups: + type: optional> + docs: Access groups the user belongs to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserAccountUpdatedPayload: + properties: + triggerType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccountDeletedPayloadPayloadData: + docs: The data about the user account that was added + properties: + accept-privacy-policy: optional + accept-communications: optional + email: optional + name: optional source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true + UserAccountDeletedPayloadPayload: + properties: + data: + type: optional + docs: The data about the user account that was added + 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: optional + accessGroups: + type: optional> + docs: Access groups the user belongs to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserAccountDeletedPayload: + properties: + triggerType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml imports: root: __package__.yml service: @@ -93,6 +214,7 @@ service: response: docs: Request was successful type: root.UserList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -181,6 +303,7 @@ service: response: docs: Request was successful type: root.User + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -262,20 +385,12 @@ service: 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. + body: root.User content-type: application/json response: docs: Request was successful type: root.User + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -288,14 +403,16 @@ service: site_id: 580e63e98c9a982ac9b8b741 user_id: 580e63e98c9a982ac9b8b741 request: - data: - name: Some One - accept-privacy: false - accept-communications: false + 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: - - webflowers - - platinum - - free-tier + - slug: webflowers + type: admin response: body: id: 6287ec36a841b25637c663df @@ -354,6 +471,7 @@ service: response: docs: Request was successful type: root.User + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -368,7 +486,7 @@ service: request: email: some.one@home.com accessGroups: - - webflowers + - accessGroups response: body: id: 6287ec36a841b25637c663df @@ -390,3 +508,73 @@ service: additionalProperties: additionalProperties source: openapi: ../../../openapi/referenced-specs/v2.yml +webhooks: + user_account_added: + audiences: [] + method: POST + display-name: New User Added + headers: {} + payload: UserAccountAddedPayload + examples: + - payload: + triggerType: user_account_added + payload: + id: 6287ec36a841b25637c663df + lastUpdated: '2022-05-20T13:46:12.093Z' + createdOn: '2022-05-20T13:46:12.093Z' + isEmailVerified: false + data: + accept-privacy: false + accept-communications: false + email: arthur.dent@heartofgold.ship + name: Arthur Dent + accessGroups: + - slug: webflowers + type: admin + docs: Information about a new user account + user_account_updated: + audiences: [] + method: POST + display-name: Account Updated + headers: {} + payload: UserAccountUpdatedPayload + examples: + - payload: + triggerType: user_account_updated + payload: + id: 6287ec36a841b25637c663df + lastUpdated: '2022-05-20T13:46:12.093Z' + createdOn: '2022-05-20T13:46:12.093Z' + isEmailVerified: false + data: + accept-privacy: false + accept-communications: false + email: arthur.dent@heartofgold.ship + name: Arthur Dent + accessGroups: + - slug: webflowers + type: admin + docs: Information about an updated user account + user_account_deleted: + audiences: [] + method: POST + display-name: Account Deleted + headers: {} + payload: UserAccountDeletedPayload + examples: + - payload: + triggerType: user_account_deleted + payload: + id: 6287ec36a841b25637c663df + lastUpdated: '2022-05-20T13:46:12.093Z' + createdOn: '2022-05-20T13:46:12.093Z' + isEmailVerified: false + data: + accept-privacy: false + accept-communications: false + email: arthur.dent@heartofgold.ship + name: Arthur Dent + accessGroups: + - slug: webflowers + type: admin + docs: Information about a deleted user account diff --git a/.mock/definition/webhooks.yml b/.mock/definition/webhooks.yml index d40e3e4..47dbfc0 100644 --- a/.mock/definition/webhooks.yml +++ b/.mock/definition/webhooks.yml @@ -22,6 +22,7 @@ service: response: docs: Request was successful type: root.WebhookList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -33,10 +34,6 @@ service: site_id: 580e63e98c9a982ac9b8b741 response: body: - pagination: - limit: 100 - offset: 0 - total: 100 webhooks: - id: 57ca0a9e418c504a6e1acbb6 triggerType: form_submission @@ -65,6 +62,10 @@ service: name: Email Form lastTriggered: '2023-02-08T23:59:28Z' createdOn: '2016-07-19T01:43:40Z' + pagination: + limit: 100 + offset: 0 + total: 100 create: path: /sites/{site_id}/webhooks method: POST @@ -93,6 +94,7 @@ service: response: docs: Request was successful type: root.Webhook + status-code: 201 errors: - root.BadRequestError - root.UnauthorizedError @@ -117,8 +119,6 @@ service: 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: @@ -139,6 +139,7 @@ service: response: docs: Request was successful type: root.Webhook + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -155,8 +156,6 @@ service: 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: diff --git a/.mock/definition/workspaces/auditLogs.yml b/.mock/definition/workspaces/auditLogs.yml new file mode 100644 index 0000000..73ae4df --- /dev/null +++ b/.mock/definition/workspaces/auditLogs.yml @@ -0,0 +1,119 @@ +types: + AuditLogsGetWorkspaceAuditLogsRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AuditLogsGetWorkspaceAuditLogsRequestEventType: + enum: + - user_access + - custom_role + - workspace_membership + - site_membership + - workspace_invitation + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get-workspace-audit_logs: + path: /workspaces/{workspace_id_or_slug}/audit_logs + method: GET + auth: true + docs: > + Get audit logs for a workspace. + + + This endpoint + requires an Enterprise workspace and a workspace token with the + `workspace_activity:read` scope. Create a workspace token from your + workspace dashboard integrations page to use this endpoint. + + + Required scope | `workspace_activity:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + workspace_id_or_slug: + type: string + docs: Unique identifier or slug for a Workspace + display-name: Get Workspace Audit Logs + request: + name: AuditLogsGetWorkspaceAuditLogsRequest + query-parameters: + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + sortOrder: + type: optional + docs: Sorts the results by asc or desc + eventType: + type: optional + docs: The event type to filter by + from: + type: optional + docs: The start date to filter by + to: + type: optional + docs: The end date to filter by + response: + docs: A list of workspace audit logs + type: root.WorkspaceAuditLogResponse + status-code: 200 + errors: + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + workspace_id_or_slug: hitchhikers-workspace + query-parameters: + from: '2024-04-22T16:00:31Z' + to: '2024-04-22T16:00:31Z' + response: + body: + items: + - eventSubType: login + eventType: user_access + timestamp: '2025-04-29T20:30:06Z' + actor: + id: 6661ccb359b561c69f29d554 + email: someone@email.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + - eventSubType: user_added + eventType: workspace_membership + timestamp: '2025-04-30T20:30:06Z' + actor: + id: 60492e55bbddce079561cd7a + email: someone@webflow.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + - eventSubType: user_added + eventType: site_membership + timestamp: '2025-04-30T00:33:31Z' + actor: + id: 671fe00d185fc8c1ad409d37 + email: someone@webflow.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + pagination: + limit: 10 + offset: 0 + total: 3 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/fern.config.json b/.mock/fern.config.json index 8b3316e..ab4ae42 100644 --- a/.mock/fern.config.json +++ b/.mock/fern.config.json @@ -1,4 +1,4 @@ { "organization" : "webflow", - "version" : "0.46.19" + "version" : "0.65.36" } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index a563308..dfe67d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2024.12.14" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, - {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, ] [[package]] @@ -60,43 +60,46 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.2" +version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + [package.extras] test = ["pytest (>=6)"] [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] name = "httpcore" -version = "1.0.7" +version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, ] [package.dependencies] certifi = "*" -h11 = ">=0.13,<0.15" +h11 = ">=0.16" [package.extras] asyncio = ["anyio (>=4.0,<5.0)"] @@ -144,13 +147,13 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] @@ -201,24 +204,24 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "packaging" -version = "24.2" +version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] @@ -238,13 +241,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.10.5" +version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, - {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, ] [package.dependencies] @@ -525,13 +528,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [metadata] diff --git a/pyproject.toml b/pyproject.toml index 749aa8e..66a8846 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "webflow" -version = "2.0.0b1" +version = "1.2.1" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index 5001bba..c1b66aa 100644 --- a/reference.md +++ b/reference.md @@ -137,7 +137,9 @@ client.token.introspect()
-Create a site. This endpoint requires an Enterprise workspace. +Create a site. + +This endpoint requires an Enterprise workspace. Required scope | `workspace:write`
@@ -368,7 +370,9 @@ client.sites.get(
-Delete a site. This endpoint requires an Enterprise workspace. +Delete a site. + +This endpoint requires an Enterprise workspace. Required scope | `sites:write`
@@ -440,7 +444,9 @@ client.sites.delete(
-Update a site. This endpoint requires an Enterprise workspace. +Update a site. + +This endpoint requires an Enterprise workspace. Required scope | `sites:write`
@@ -600,9 +606,11 @@ client.sites.get_custom_domain(
-Publishes a site to one or more more domains. +Publishes a site to one or more more domains. + +To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. -This endpoint has a limit of one successful publish queue per minute. +This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write`
@@ -626,6 +634,8 @@ client = Webflow( ) client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) ``` @@ -763,7 +773,9 @@ client.collections.list(
-Create a Collection for a site. +Create a Collection for a site with collection fields. + +Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write`
@@ -780,7 +792,7 @@ Required scope | `cms:write`
```python -from webflow import Webflow +from webflow import ReferenceField, ReferenceFieldMetadata, StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -790,6 +802,29 @@ client.collections.create( display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) ``` @@ -838,6 +873,14 @@ client.collections.create(
+**fields:** `typing.Optional[typing.Sequence[FieldCreate]]` — An array of custom fields to add to the collection + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -1187,6 +1230,10 @@ client.pages.get_metadata( Update Page-level metadata, including SEO and Open Graph fields. + + Note: When updating Page Metadata in secondary locales, you may only add `slug` to the request if your Site has the [Advanced or Enterprise Localization](https://webflow.com/localization) add-on. + + Required scope | `pages:write`
@@ -1202,9 +1249,11 @@ Required scope | `pages:write`
```python -import datetime - -from webflow import PageOpenGraph, PageSeo, Webflow +from webflow import Webflow +from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -1212,32 +1261,18 @@ client = Webflow( client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) ``` @@ -1262,14 +1297,6 @@ client.pages.update_page_settings(
-**id:** `str` — Unique identifier for the Page - -
-
- -
-
- **locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -1278,39 +1305,7 @@ client.pages.update_page_settings(
-**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. +**title:** `typing.Optional[str]` — Title for the page
@@ -1318,7 +1313,7 @@ client.pages.update_page_settings(
-**created_on:** `typing.Optional[dt.datetime]` — The date the Page was created +**slug:** `typing.Optional[str]` — Slug for the page
@@ -1326,7 +1321,7 @@ client.pages.update_page_settings(
-**last_updated:** `typing.Optional[dt.datetime]` — The date the Page was most recently updated +**seo:** `typing.Optional[PageMetadataWriteSeo]` — SEO-related fields for the Page
@@ -1334,71 +1329,7 @@ client.pages.update_page_settings(
-**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 +**open_graph:** `typing.Optional[PageMetadataWriteOpenGraph]` — Open Graph fields for the Page
@@ -1430,10 +1361,11 @@ client.pages.update_page_settings(
-Get static content from a static page. This includes text nodes, image nodes and component instances. -To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. +Get content from a static page. This includes text nodes, image nodes, select nodes, text input nodes, submit button 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). -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. +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`
@@ -1556,9 +1488,13 @@ Required scope | `pages:write` ```python from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, Webflow, ) @@ -1569,15 +1505,37 @@ client.pages.update_static_content( page_id="63c720f9347c2139b248e552", locale_id="localeId", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -1680,6 +1638,7 @@ client = Webflow( ) client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", ) ``` @@ -1704,6 +1663,14 @@ client.components.list(
+**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch. + +
+
+ +
+
+ **limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -1744,7 +1711,7 @@ client.components.list(
-Get static content from a component definition. This includes text nodes, image nodes and nested component instances. +Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -1773,6 +1740,7 @@ client.components.get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) ``` @@ -1813,6 +1781,14 @@ client.components.get_content(
+**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch. + +
+
+ +
+
+ **limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -1879,9 +1855,13 @@ Required scope | `components:write` ```python from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, Webflow, ) @@ -1892,16 +1872,39 @@ client.components.update_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -1963,6 +1966,14 @@ client.components.update_content(
+**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch. + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -1987,9 +1998,9 @@ client.components.update_content(
-Get the property default values of a component definition. +Get the default property values of a component definition. -If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. +If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read`
@@ -2015,6 +2026,7 @@ client.components.get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) ``` @@ -2055,6 +2067,14 @@ client.components.get_properties(
+**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch. + +
+
+ +
+
+ **limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2095,12 +2115,11 @@ client.components.get_properties(
-Update the property default values of a component definition in a specificed locale. +Update the default property values of a component definition in a specificed locale. -Before making updates: -1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties +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 locale is missing, the request will not be processed and will result in an error. +The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write`
@@ -2127,6 +2146,7 @@ client.components.update_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -2185,6 +2205,14 @@ client.components.update_properties(
+**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch. + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -2210,14 +2238,11 @@ client.components.update_properties(
-List of scripts registered to a Site. +Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. -Additionally, Scripts can be remotely hosted, or registered as inline snippets. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read`
@@ -2289,14 +2314,11 @@ client.scripts.list(
-Add a script to a Site's Custom Code registry. +Register a hosted 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. -Additionally, Scripts can be remotely hosted, or registered as inline snippets. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -2412,13 +2434,11 @@ client.scripts.register_hosted(
-Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. +Register an inline script to a site. Inline scripts are limited to 2000 characters. -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -2534,7 +2554,7 @@ client.scripts.register_inline(
-List assets for a given site +List of assets uploaded to a site Required scope | `assets:read`
@@ -2606,15 +2626,18 @@ client.assets.list(
-Create a new asset entry. +The first step in uploading an asset to a site. -This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. -You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) -request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. +This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - -Required scope | `assets:write` + +Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + +To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write`
@@ -2710,7 +2733,7 @@ client.assets.create(
-Get an Asset +Get details about an asset Required scope | `assets:read`
@@ -2854,7 +2877,7 @@ client.assets.delete(
-Update an Asset +Update details of an Asset. Required scope | `assets:write`
@@ -3707,6 +3730,12 @@ client.forms.get( List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read`
@@ -3853,7 +3882,7 @@ client.forms.get_submission(
-
client.forms.update_submission(...) +
client.forms.delete_submission(...)
@@ -3865,7 +3894,8 @@ client.forms.get_submission(
-Update hidden fields on a form submission +Delete a form submission + Required scope | `forms:write`
@@ -3887,7 +3917,7 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.update_submission( +client.forms.delete_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) @@ -3913,14 +3943,6 @@ client.forms.update_submission(
-**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3933,8 +3955,7 @@ client.forms.update_submission(
-## Users -
client.users.list(...) +
client.forms.update_submission(...)
@@ -3946,9 +3967,9 @@ client.forms.update_submission(
-Get a list of users for a site +Update hidden fields on a form submission -Required scope | `users:read` +Required scope | `forms:write`
@@ -3968,8 +3989,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.list( - site_id="580e63e98c9a982ac9b8b741", +client.forms.update_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3986,23 +4007,7 @@ client.users.list(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records - -
-
- -
-
- -**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -4010,13 +4015,7 @@ client.users.list(
-**sort:** `typing.Optional[UsersListRequestSort]` - -Sort string to use when ordering users - -Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - -Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set
@@ -4036,7 +4035,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-
client.users.get(...) +
client.forms.list_submissions_by_site(...)
@@ -4048,9 +4047,11 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Get a User by ID +List form submissions for a given site. This endpoint differs from the existing [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) by accepting `siteId` as a path parameter and `elementId` as a query parameter. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list). -Required scope | `users:read` + + +Required scope | `forms:read`
@@ -4070,9 +4071,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.get( +client.forms.list_submissions_by_site( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", ) ``` @@ -4097,7 +4098,23 @@ client.users.get(
-**user_id:** `str` — Unique identifier for a User +**element_id:** `typing.Optional[str]` — Identifier for an element + +
+
+ +
+
+ +**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)
@@ -4117,7 +4134,8 @@ client.users.get(
-
client.users.delete(...) +## Users +
client.users.list(...)
@@ -4129,9 +4147,9 @@ client.users.get(
-Delete a User by ID +Get a list of users for a site -Required scope | `users:write` +Required scope | `users:read`
@@ -4151,9 +4169,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.delete( +client.users.list( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", ) ``` @@ -4178,7 +4195,29 @@ client.users.delete(
-**user_id:** `str` — Unique identifier for a User +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort:** `typing.Optional[UsersListRequestSort]` + +Sort string to use when ordering users + +Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -4198,7 +4237,7 @@ client.users.delete(
-
client.users.update(...) +
client.users.get(...)
@@ -4210,12 +4249,9 @@ client.users.delete(
-Update a User by ID - - Required scope | `users:write` +Get a User by ID -The email and password -fields cannot be updated using this endpoint +Required scope | `users:read`
@@ -4231,20 +4267,13 @@ fields cannot be updated using this endpoint ```python from webflow import Webflow -from webflow.resources.users import UsersUpdateRequestData client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.update( +client.users.get( site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, - ), - access_groups=["webflowers", "platinum", "free-tier"], ) ``` @@ -4271,23 +4300,6 @@ client.users.update( **user_id:** `str` — Unique identifier for a User - -
- -
-
- -**data:** `typing.Optional[UsersUpdateRequestData]` - -
-
- -
-
- -**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - -
@@ -4306,7 +4318,7 @@ client.users.update(
-
client.users.invite(...) +
client.users.delete(...)
@@ -4318,9 +4330,7 @@ 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 any paid access group. +Delete a User by ID Required scope | `users:write`
@@ -4342,10 +4352,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.invite( +client.users.delete( site_id="580e63e98c9a982ac9b8b741", - email="some.one@home.com", - access_groups=["webflowers"], + user_id="580e63e98c9a982ac9b8b741", ) ``` @@ -4370,16 +4379,7 @@ client.users.invite(
-**email:** `str` — Email address of user to send invite to - -
-
- -
-
- -**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - +**user_id:** `str` — Unique identifier for a User
@@ -4399,8 +4399,7 @@ client.users.invite(
-## AccessGroups -
client.access_groups.list(...) +
client.users.update(...)
@@ -4412,9 +4411,12 @@ client.users.invite(
-Get a list of access groups for a site +Update a User by ID -Required scope | `users:read` + Required scope | `users:write` + +The email and password +fields cannot be updated using this endpoint
@@ -4429,13 +4431,37 @@ Required scope | `users:read`
```python -from webflow import Webflow +import datetime + +from webflow import UserAccessGroupsItem, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.access_groups.list( +client.users.update( site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + id="6287ec36a841b25637c663df", + is_email_verified=True, + last_updated=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + invited_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + last_login=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + status="verified", + access_groups=[ + UserAccessGroupsItem( + slug="webflowers", + type="admin", + ) + ], ) ``` @@ -4460,7 +4486,7 @@ client.access_groups.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**user_id:** `str` — Unique identifier for a User
@@ -4468,7 +4494,7 @@ client.access_groups.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**id:** `typing.Optional[str]` — Unique identifier for the User
@@ -4476,10 +4502,63 @@ client.access_groups.list(
-**sort:** `typing.Optional[AccessGroupsListRequestSort]` +**is_email_verified:** `typing.Optional[bool]` — Shows whether the user has verified their email address + +
+
-Sort string to use when ordering access groups -Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +
+
+ +**last_updated:** `typing.Optional[dt.datetime]` — The timestamp the user was updated + +
+
+ +
+
+ +**invited_on:** `typing.Optional[dt.datetime]` — The timestamp the user was invited + +
+
+ +
+
+ +**created_on:** `typing.Optional[dt.datetime]` — The timestamp the user was created + +
+
+ +
+
+ +**last_login:** `typing.Optional[dt.datetime]` — The timestamp the user was logged in + +
+
+ +
+
+ +**status:** `typing.Optional[UserStatus]` + +
+
+ +
+
+ +**access_groups:** `typing.Optional[typing.Sequence[UserAccessGroupsItem]]` — Access groups the user belongs to + +
+
+ +
+
+ +**data:** `typing.Optional[UserData]`
@@ -4499,8 +4578,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-## Products -
client.products.list(...) +
client.users.invite(...)
@@ -4512,12 +4590,11 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Retrieve all products for a site. +Create and invite a user with an email address. -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. +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 | `ecommerce:read` +Required scope | `users:write`
@@ -4537,8 +4614,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.list( +client.users.invite( site_id="580e63e98c9a982ac9b8b741", + email="some.one@home.com", + access_groups=["accessGroups"], ) ``` @@ -4563,7 +4642,7 @@ client.products.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**email:** `str` — Email address of user to send invite to
@@ -4571,7 +4650,7 @@ client.products.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**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.
@@ -4591,7 +4670,8 @@ client.products.list(
-
client.products.create(...) +## AccessGroups +
client.access_groups.list(...)
@@ -4603,20 +4683,9 @@ client.products.list(
-Create a new product and SKU. - -When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - -To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) - -Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. +Get a list of access groups for a site -Required scope | `ecommerce:write` +Required scope | `users:read`
@@ -4636,7 +4705,7 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.create( +client.access_groups.list( site_id="580e63e98c9a982ac9b8b741", ) @@ -4662,7 +4731,7 @@ client.products.create(
-**publish_status:** `typing.Optional[PublishStatus]` +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -4670,7 +4739,7 @@ client.products.create(
-**product:** `typing.Optional[Product]` +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -4678,7 +4747,10 @@ client.products.create(
-**sku:** `typing.Optional[Sku]` +**sort:** `typing.Optional[AccessGroupsListRequestSort]` + +Sort string to use when ordering access groups +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -4698,7 +4770,8 @@ client.products.create(
-
client.products.get(...) +## Products +
client.products.list(...)
@@ -4710,8 +4783,10 @@ client.products.create(
-Retrieve a single product by its ID. All of its SKUs will also be -retrieved. +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`
@@ -4733,9 +4808,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.get( +client.products.list( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4760,7 +4834,15 @@ client.products.get(
-**product_id:** `str` — Unique identifier for a Product +**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)
@@ -4780,7 +4862,7 @@ client.products.get(
-
client.products.update(...) +
client.products.create(...)
@@ -4792,9 +4874,14 @@ client.products.get(
-Update an existing Product. +Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. -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. +To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) + +Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write`
@@ -4811,14 +4898,88 @@ Required scope | `ecommerce:write`
```python -from webflow import Webflow +from webflow import ( + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + Webflow, +) +from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.update( +client.products.create( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) ``` @@ -4843,15 +5004,7 @@ client.products.update(
-**product_id:** `str` — Unique identifier for a Product - -
-
- -
-
- -**publish_status:** `typing.Optional[PublishStatus]` +**product:** `ProductSkuCreateProduct`
@@ -4859,7 +5012,7 @@ client.products.update(
-**product:** `typing.Optional[Product]` +**sku:** `ProductSkuCreateSku`
@@ -4867,7 +5020,7 @@ client.products.update(
-**sku:** `typing.Optional[Sku]` +**publish_status:** `typing.Optional[PublishStatus]`
@@ -4887,7 +5040,196 @@ client.products.update(
-
client.products.create_sku(...) +
client.products.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.get( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +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` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.update( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**product:** `typing.Optional[Product]` + +
+
+ +
+
+ +**sku:** `typing.Optional[Sku]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.create_sku(...)
@@ -4918,7 +5260,9 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku, Webflow +import datetime + +from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -4926,7 +5270,30 @@ client = Webflow( client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) ``` @@ -5018,7 +5385,9 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku, Webflow +import datetime + +from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -5027,7 +5396,28 @@ client.products.update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) ``` @@ -5686,8 +6076,8 @@ client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) ``` @@ -5704,7 +6094,7 @@ client.inventory.list(
-**collection_id:** `str` — Unique identifier for a Collection +**sku_collection_id:** `str` — Unique identifier for a SKU collection. Use the List Collections API to find this ID.
@@ -5712,7 +6102,7 @@ client.inventory.list(
-**item_id:** `str` — Unique identifier for an Item +**sku_id:** `str` — Unique identifier for a SKU
@@ -5771,8 +6161,8 @@ client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", inventory_type="infinite", ) @@ -5790,7 +6180,7 @@ client.inventory.update(
-**collection_id:** `str` — Unique identifier for a Collection +**sku_collection_id:** `str` — Unique identifier for a SKU collection. Use the List Collections API to find this ID.
@@ -5798,7 +6188,7 @@ client.inventory.update(
-**item_id:** `str` — Unique identifier for an Item +**sku_id:** `str` — Unique identifier for a SKU
@@ -5928,14 +6318,11 @@ client.ecommerce.get_settings(
-Create a custom field in a collection. +Create a custom field in a collection. -Slugs must be all lowercase letters without spaces. -If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will -convert the slug to lowercase and replace spaces with "-." +Field validation is currently not available through the API. -Only some field types can be created through the API. -This endpoint does not currently support bulk creation. +Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write`
@@ -5952,17 +6339,24 @@ Required scope | `cms:write`
```python -from webflow import Webflow +from webflow import ReferenceField, ReferenceFieldMetadata, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=ReferenceField( + id="562ac0395358780a1f5e6fbd", + is_editable=True, + is_required=False, + type="Reference", + display_name="Author", + help_text="Add the post author here", + metadata=ReferenceFieldMetadata( + collection_id="63692ab61fb2852f582ba8f5", + ), + ), ) ``` @@ -5987,31 +6381,7 @@ client.collections.fields.create(
-**type:** `FieldCreateType` — Choose these appropriate field type for your collection data - -
-
- -
-
- -**display_name:** `str` — The name of a field - -
-
- -
-
- -**is_required:** `typing.Optional[bool]` — define whether a field is required in a collection - -
-
- -
-
- -**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field +**request:** `FieldCreate`
@@ -6305,7 +6675,15 @@ client.collections.items.list_items(
-**name:** `typing.Optional[str]` — The name of the item(s) +**name:** `typing.Optional[str]` — Filter by the exact name of the item(s) + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — Filter by the exact slug of the item
@@ -6313,7 +6691,7 @@ client.collections.items.list_items(
-**slug:** `typing.Optional[str]` — The slug of the item +**last_published:** `typing.Optional[ItemsListItemsRequestLastPublished]` — Filter by the last published date of the item(s)
@@ -6364,7 +6742,7 @@ client.collections.items.list_items( Create Item(s) in a Collection. -To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) +To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write`
@@ -6437,7 +6815,7 @@ client.collections.items.create_item(
-**request:** `ItemsCreateItemRequest` +**request:** `ItemsCreateItemRequestBody`
@@ -6445,13 +6823,21 @@ client.collections.items.create_item(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
-
-
- + +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ +
+ @@ -6471,7 +6857,7 @@ client.collections.items.create_item( Delete Items from a Collection. -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. +Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -6489,12 +6875,20 @@ Required scope | `CMS:write` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) ``` @@ -6519,7 +6913,7 @@ client.collections.items.delete_items(
-**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]]` +**items:** `typing.Sequence[ItemsDeleteItemsRequestItemsItem]`
@@ -6551,9 +6945,11 @@ client.collections.items.delete_items(
-Update a single item or multiple items (up to 100) in a Collection. +Update a single item or multiple items in a Collection. -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. +The limit for this endpoint is 100 items. + +Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write`
@@ -6583,35 +6979,21 @@ 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", + id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", - slug="au-revoir-et-merci", + name="Senior Data Analyst", + slug="senior-data-analyst", ), ), CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", + id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", - slug="hasta-luego-y-gracias", + name="Product Manager", + slug="product-manager", ), ), ], @@ -6639,6 +7021,14 @@ client.collections.items.update_items(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -6671,7 +7061,12 @@ client.collections.items.update_items(
-List of all live Items within a Collection. +List all published items in a collection. + + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + Required scope | `CMS:read`
@@ -6743,7 +7138,15 @@ client.collections.items.list_items_live(
-**name:** `typing.Optional[str]` — The name of the item(s) +**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
@@ -6751,7 +7154,7 @@ client.collections.items.list_items_live(
-**slug:** `typing.Optional[str]` — The slug of the item +**last_published:** `typing.Optional[ItemsListItemsLiveRequestLastPublished]` — Filter by the last published date of the item(s)
@@ -6799,10 +7202,10 @@ client.collections.items.list_items_live(
-Create live Item(s) in a Collection. The Item(s) will be published to the live site. +Create item(s) in a collection that will be immediately published to the live site. -To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) +To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -6872,7 +7275,15 @@ client.collections.items.create_item_live(
-**request:** `ItemsCreateItemLiveRequest` +**request:** `ItemsCreateItemLiveRequestBody` + +
+
+ +
+
+ +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -6904,9 +7315,9 @@ client.collections.items.create_item_live(
-Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. +Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. +Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write`
@@ -6924,12 +7335,20 @@ Required scope | `CMS:write` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) ``` @@ -6954,7 +7373,7 @@ client.collections.items.delete_items_live(
-**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]]` +**items:** `typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]`
@@ -6986,9 +7405,9 @@ client.collections.items.delete_items_live(
-Update a single live item or multiple live items (up to 100) in a Collection +Update a single published item or multiple published items (up to 100) in a Collection -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. +Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write`
@@ -7074,6 +7493,14 @@ client.collections.items.update_items_live(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -7108,9 +7535,10 @@ client.collections.items.update_items_live( Create an item or multiple items in a CMS Collection across multiple corresponding locales. -**Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + Required scope | `CMS:write`
@@ -7178,6 +7606,14 @@ client.collections.items.create_items(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created
@@ -7315,7 +7751,7 @@ client.collections.items.get_item(
-Delete an Item from a Collection. This endpoint does not currently support bulk deletion. +Delete an item from a collection. Required scope | `CMS:write`
@@ -7467,6 +7903,14 @@ client.collections.items.update_item(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -7557,6 +8001,11 @@ client.collections.items.update_item( Get details of a selected Collection live Item. + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + + Required scope | `CMS:read`
@@ -7644,9 +8093,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. +Unpublish a live item from the site and set the `isDraft` property to `true`. -This endpoint does not currently support bulk deletion. +For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write`
@@ -7798,6 +8247,14 @@ client.collections.items.update_item_live(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -7904,13 +8361,28 @@ Required scope | `cms:write` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemIDsWithLocales, + ItemsPublishItemRequestItemsItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], + request=ItemIDsWithLocales( + items=[ + ItemsPublishItemRequestItemsItemsItem( + id="643fd856d66b6528195ee2ca", + cms_locale_ids=[ + "653ad57de882f528b32e810e", + "6514390aea353fc691d69827", + "65143930ea353fc691d69cd8", + ], + ) + ], + ), ) ``` @@ -7935,7 +8407,7 @@ client.collections.items.publish_item(
-**item_ids:** `typing.Sequence[str]` +**request:** `ItemsPublishItemRequest`
@@ -7968,13 +8440,7 @@ client.collections.items.publish_item(
-Get all registered scripts that have been applied to a specific Page. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +Get all scripts applied to a page. Required scope | `custom_code:read`
@@ -8046,15 +8512,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. - -A site can have a maximum of 800 registered scripts. +Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -8163,13 +8625,11 @@ client.pages.scripts.upsert_custom_code(
-Delete the custom code block that an app has created for a page +Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. +To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write`
@@ -8242,10 +8702,11 @@ client.pages.scripts.delete_custom_code(
-Fetch a list of all URL redirect rules configured for a specific site. +Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. +This endpoint requires an Enterprise workspace. Required scope: `sites:read`
@@ -8317,10 +8778,12 @@ client.sites.redirects.list(
-Add a new URL redirection rule to a site. +Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. +This endpoint requires an Enterprise workspace. + Required scope: `sites:write`
@@ -8386,7 +8849,839 @@ client.sites.redirects.create(
-**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ +
+ + + +
+ + +
client.sites.redirects.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove a 301 redirection rule from a site. + +This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**redirect_id:** `str` — Unique identifier site rediect + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.redirects.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a 301 redirection rule from a site. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**redirect_id:** `str` — Unique identifier site rediect + +
+
+ +
+
+ +**id:** `typing.Optional[str]` — The ID of the specific redirect rule + +
+
+ +
+
+ +**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. + +
+
+ +
+
+ +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites Plans +
client.sites.plans.get_site_plan(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get site plan details for the specified Site. + +This endpoint requires an Enterprise workspace. + +Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.plans.get_site_plan( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites RobotsTxt +
client.sites.robots_txt.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve the robots.txt configuration for various user agents. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.robots_txt.put(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Replace the `robots.txt` configuration for various user agents. + +This endpoint requires an Enterprise workspace. + +Required scope | `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import RobotsRulesItem, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. + +
+
+ +
+
+ +**sitemap:** `typing.Optional[str]` — URL to the sitemap. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.robots_txt.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + +**Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import RobotsRulesItem, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. + +
+
+ +
+
+ +**sitemap:** `typing.Optional[str]` — URL to the sitemap. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.robots_txt.patch(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update the `robots.txt` configuration for various user agents. + +This endpoint requires an Enterprise workspace. + +Required scope | `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import RobotsRulesItem, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. + +
+
+ +
+
+ +**sitemap:** `typing.Optional[str]` — URL to the sitemap. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites WellKnown +
client.sites.well_known.put(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Upload a supported well-known file to a site. + +The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="fileName", + file_data="fileData", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**file_name:** `str` — The name of the file + +
+
+ +
+
+ +**file_data:** `str` — The contents of the file + +
+
+ +
+
+ +**content_type:** `typing.Optional[WellKnownFileContentType]` — The content type of the file. Defaults to application/json + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.well_known.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete existing well-known files from a site. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**file_names:** `typing.Optional[typing.Sequence[str]]` — A list of file names to delete
@@ -8406,7 +9701,8 @@ client.sites.redirects.create(
-
client.sites.redirects.delete(...) +## Sites ActivityLogs +
client.sites.activity_logs.list(...)
@@ -8418,9 +9714,11 @@ client.sites.redirects.create(
-Remove a URL redirection rule from a site. -This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. -Required scope: `sites:write` +Retrieve Activity Logs for a specific Site. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_activity:read`
@@ -8440,9 +9738,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.delete( +client.sites.activity_logs.list( site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", ) ``` @@ -8467,7 +9764,15 @@ client.sites.redirects.delete(
-**redirect_id:** `str` — Unique identifier site rediect +**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
@@ -8487,7 +9792,8 @@ client.sites.redirects.delete(
-
client.sites.redirects.update(...) +## Sites Comments +
client.sites.comments.list_comment_threads(...)
@@ -8499,8 +9805,13 @@ client.sites.redirects.delete(
-Update a URL redirection rule from a site. -Required scope: `sites:write` +List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + +Required scope | `comments:read`
@@ -8520,12 +9831,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.update( +client.sites.comments.list_comment_threads( site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", - id="42e1a2b7aa1a13f768a0042a", - from_url="/mostly-harmless", - to_url="/earth", + locale_id="65427cf400e02b306eaa04a0", ) ``` @@ -8550,7 +9858,7 @@ client.sites.redirects.update(
-**redirect_id:** `str` — Unique identifier site rediect +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -8558,7 +9866,7 @@ client.sites.redirects.update(
-**id:** `typing.Optional[str]` — The ID of the specific redirect rule +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -8566,7 +9874,7 @@ client.sites.redirects.update(
-**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -8574,7 +9882,15 @@ client.sites.redirects.update(
-**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**sort_by:** `typing.Optional[CommentsListCommentThreadsRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsListCommentThreadsRequestSortOrder]` — Sorts the results by asc or desc
@@ -8594,8 +9910,7 @@ client.sites.redirects.update(
-## Sites Plans -
client.sites.plans.get_site_plan(...) +
client.sites.comments.get_comment_thread(...)
@@ -8607,9 +9922,13 @@ client.sites.redirects.update(
-Get site plan details for the specified Site. +Get details of a specific comment thread. -Required scope | `sites:read` + + There may be a delay of up to 5 minutes before new comments appear in the system. + + +Required scope | `comments:read`
@@ -8629,8 +9948,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.plans.get_site_plan( +client.sites.comments.get_comment_thread( site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", ) ``` @@ -8655,6 +9976,54 @@ client.sites.plans.get_site_plan(
+**comment_thread_id:** `str` — Unique identifier for a Comment Thread + +
+
+ +
+
+ +**locale_id:** `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 + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[CommentsGetCommentThreadRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsGetCommentThreadRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -8667,8 +10036,7 @@ client.sites.plans.get_site_plan(
-## Sites ActivityLogs -
client.sites.activity_logs.list(...) +
client.sites.comments.list_comment_replies(...)
@@ -8680,7 +10048,13 @@ client.sites.plans.get_site_plan(
-Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` +List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + +Required scope | `comments:read`
@@ -8700,8 +10074,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.activity_logs.list( +client.sites.comments.list_comment_replies( site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", ) ``` @@ -8726,7 +10102,15 @@ client.sites.activity_logs.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**comment_thread_id:** `str` — Unique identifier for a Comment Thread + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -8742,6 +10126,30 @@ client.sites.activity_logs.list(
+**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[CommentsListCommentRepliesRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsListCommentRepliesRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -8767,9 +10175,11 @@ client.sites.activity_logs.list(
-Get all registered scripts that have been applied to a specific Site. +Get all scripts applied to a site by the App. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read`
@@ -8841,13 +10251,11 @@ client.sites.scripts.get_custom_code(
-Add a registered script to a Site. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. +Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -8956,9 +10364,11 @@ client.sites.scripts.upsert_custom_code(
-Delete the custom code block that an app created for a Site +Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + +To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write`
@@ -9030,9 +10440,13 @@ client.sites.scripts.delete_custom_code(
-Get all instances of Custom Code applied to a Site or Pages. +Get a list of scripts that have been applied to a site and/or individual pages. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read`
@@ -9108,3 +10522,134 @@ client.sites.scripts.list_custom_code_blocks(
+## Workspaces AuditLogs +
client.workspaces.audit_logs.get_workspace_audit_logs(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get audit logs for a workspace. + +This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + +Required scope | `workspace_activity:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + from_=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workspace_id_or_slug:** `str` — Unique identifier or slug for a Workspace + +
+
+ +
+
+ +**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 + +
+
+ +
+
+ +**sort_order:** `typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ +**event_type:** `typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType]` — The event type to filter by + +
+
+ +
+
+ +**from_:** `typing.Optional[dt.datetime]` — The start date to filter by + +
+
+ +
+
+ +**to:** `typing.Optional[dt.datetime]` — The end date to filter by + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/src/webflow/__init__.py b/src/webflow/__init__.py index 0d82d59..72ae369 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -20,6 +20,8 @@ BulkCollectionItemFieldData, Collection, CollectionItem, + CollectionItemChanged, + CollectionItemCreated, CollectionItemFieldData, CollectionItemList, CollectionItemListNoPagination, @@ -28,24 +30,49 @@ CollectionItemPatchSingleFieldData, CollectionItemPostSingle, CollectionItemPostSingleFieldData, + CollectionItemPublished, + CollectionItemRemoved, + CollectionItemRemovedPayload, + CollectionItemRemovedPayloadFieldData, + CollectionItemUnpublished, + CollectionItemUnpublishedPayload, + CollectionItemUnpublishedPayloadFieldData, CollectionItemWithIdInput, CollectionItemWithIdInputFieldData, CollectionList, CollectionListArrayItem, + Comment, + CommentPayload, + CommentPayloadAuthor, + CommentPayloadMentionedUsersItem, + CommentReply, + CommentReplyAuthor, + CommentReplyList, + CommentReplyListPagination, + CommentReplyMentionedUsersItem, + CommentThread, + CommentThreadAuthor, + CommentThreadList, + CommentThreadListPagination, + CommentThreadMentionedUsersItem, Component, ComponentDom, - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, ComponentList, - ComponentNode, + ComponentNodeDom, ComponentProperties, ComponentProperty, ComponentPropertyType, + Conflict, ConflictErrorBody, CustomCodeBlock, CustomCodeBlockType, CustomCodeHostedResponse, CustomCodeInlineResponse, + CustomRole, + CustomRoleAuditLogItem, + CustomRoleAuditLogItemEventSubType, Dom, Domain, Domains, @@ -54,7 +81,11 @@ Error, ErrorCode, Field, + FieldCreate, FieldType, + FieldValidations, + FieldValidationsAdditionalProperties, + FieldValidationsAdditionalPropertiesAdditionalProperties, ForbiddenErrorBody, Form, FormField, @@ -64,26 +95,43 @@ FormResponseSettings, FormSubmission, FormSubmissionList, - ImageNode, + FormSubmissionTrigger, + FormSubmissionTriggerPayload, + FormSubmissionTriggerPayloadSchemaItem, + FormSubmissionTriggerPayloadSchemaItemFieldType, + ImageNodeDom, ImageNodeImage, InvalidDomain, InvalidScopes, InventoryItem, InventoryItemInventoryType, + ItemsListItemsLiveRequestLastPublished, + ItemsListItemsRequestLastPublished, ListCustomCodeBlocks, Locale, Locales, + Metadata, + MetadataOptionsItem, + NewOrder, NoDomains, Node, Node_ComponentInstance, Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, Node_Text, + Node_TextInput, NotEnterprisePlanSite, NotEnterprisePlanWorkspace, + OptionField, Order, OrderAddress, OrderAddressJapanType, OrderAddressType, + OrderBillingAddress, + OrderBillingAddressJapanType, + OrderBillingAddressType, OrderCustomerInfo, OrderDisputeLastStatus, OrderDownloadFilesItem, @@ -94,15 +142,26 @@ OrderPurchasedItemVariantImage, OrderPurchasedItemVariantImageFile, OrderPurchasedItemVariantImageFileVariantsItem, + OrderShippingAddress, + OrderShippingAddressJapanType, + OrderShippingAddressType, OrderStatus, OrderTotals, OrderTotalsExtrasItem, OrderTotalsExtrasItemType, Page, + PageCreatedWebhook, + PageCreatedWebhookPayload, + PageDeletedWebhook, + PageDeletedWebhookPayload, PageList, + PageMetadataUpdatedWebhook, + PageMetadataUpdatedWebhookPayload, PageOpenGraph, PageSeo, Pagination, + Payload, + PayloadFieldData, PaypalDetails, Product, ProductAndSkUs, @@ -113,11 +172,24 @@ PublishStatus, Redirect, Redirects, + ReferenceField, + ReferenceFieldMetadata, + ReferenceFieldType, RegisteredScriptList, + Robots, + RobotsRulesItem, ScriptApply, ScriptApplyList, ScriptApplyLocation, Scripts, + SearchButton, + SearchButtonNodeDom, + Select, + SelectNodeChoicesItem, + SelectNodeDom, + SelectNodeWriteChoicesItem, + SingleLocaleCreatedPayload, + SingleLocaleCreatedPayloadFieldData, Site, SiteActivityLogItem, SiteActivityLogItemEvent, @@ -125,9 +197,14 @@ SiteActivityLogItemUser, SiteActivityLogResponse, SiteDataCollectionType, + SiteMembership, + SiteMembershipAuditLogItem, + SiteMembershipAuditLogItemEventSubType, SitePlan, SitePlanId, SitePlanName, + SitePublish, + SitePublishPayload, Sites, Sku, SkuFieldData, @@ -141,16 +218,26 @@ SkuPropertyList, SkuPropertyListEnumItem, SkuValueList, + StaticField, + StaticFieldType, StripeCard, StripeCardBrand, StripeCardExpires, StripeDetails, + SubmitButton, + SubmitButtonNodeDom, Text, + TextInput, + TextInputNodeDom, TextNode, + TextNodeDom, TextNodeText, - TextNodeWrite, TriggerType, + UpdatedOrder, User, + UserAccess, + UserAccessAuditLogItem, + UserAccessAuditLogItemEventSubType, UserAccessGroupsItem, UserAccessGroupsItemType, UserData, @@ -162,6 +249,32 @@ Webhook, WebhookFilter, WebhookList, + WorkspaceAuditLogItem, + WorkspaceAuditLogItemActor, + WorkspaceAuditLogItemPayloadSiteMembershipMethod, + WorkspaceAuditLogItemPayloadSiteMembershipSite, + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, + WorkspaceAuditLogItemPayloadSiteMembershipUserType, + WorkspaceAuditLogItemPayloadUserAccessMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, + WorkspaceAuditLogItemWorkspace, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogResponse, + WorkspaceInvitation, + WorkspaceInvitationAuditLogItem, + WorkspaceInvitationAuditLogItemEventSubType, + WorkspaceMembership, + WorkspaceMembershipAuditLogItem, + WorkspaceMembershipAuditLogItemEventSubType, ) from .errors import ( BadRequestError, @@ -178,15 +291,28 @@ ComponentPropertiesWritePropertiesItem, ComponentsUpdateContentResponse, ComponentsUpdatePropertiesResponse, + EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType, OrdersListRequestStatus, OrdersRefundRequestReason, PageDomWriteNodesItem, + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ProductSkuCreateProduct, + ProductSkuCreateSku, ProductsCreateSkuResponse, SitesPublishResponse, UpdateStaticContentResponse, + UserAccountAddedPayload, + UserAccountAddedPayloadPayload, + UserAccountAddedPayloadPayloadData, + UserAccountDeletedPayload, + UserAccountDeletedPayloadPayload, + UserAccountDeletedPayloadPayloadData, + UserAccountUpdatedPayload, + UserAccountUpdatedPayloadPayload, + UserAccountUpdatedPayloadPayloadData, UsersListRequestSort, - UsersUpdateRequestData, access_groups, assets, collections, @@ -202,6 +328,7 @@ token, users, webhooks, + workspaces, ) from .client import AsyncWebflow, Webflow from .environment import WebflowEnvironment @@ -230,6 +357,8 @@ "BulkCollectionItemFieldData", "Collection", "CollectionItem", + "CollectionItemChanged", + "CollectionItemCreated", "CollectionItemFieldData", "CollectionItemList", "CollectionItemListNoPagination", @@ -238,38 +367,68 @@ "CollectionItemPatchSingleFieldData", "CollectionItemPostSingle", "CollectionItemPostSingleFieldData", + "CollectionItemPublished", + "CollectionItemRemoved", + "CollectionItemRemovedPayload", + "CollectionItemRemovedPayloadFieldData", + "CollectionItemUnpublished", + "CollectionItemUnpublishedPayload", + "CollectionItemUnpublishedPayloadFieldData", "CollectionItemWithIdInput", "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Comment", + "CommentPayload", + "CommentPayloadAuthor", + "CommentPayloadMentionedUsersItem", + "CommentReply", + "CommentReplyAuthor", + "CommentReplyList", + "CommentReplyListPagination", + "CommentReplyMentionedUsersItem", + "CommentThread", + "CommentThreadAuthor", + "CommentThreadList", + "CommentThreadListPagination", + "CommentThreadMentionedUsersItem", "Component", "ComponentDom", "ComponentDomWriteNodesItem", - "ComponentInstanceNodePropertyOverridesWrite", + "ComponentInstance", "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem", "ComponentList", - "ComponentNode", + "ComponentNodeDom", "ComponentProperties", "ComponentPropertiesWritePropertiesItem", "ComponentProperty", "ComponentPropertyType", "ComponentsUpdateContentResponse", "ComponentsUpdatePropertiesResponse", + "Conflict", "ConflictError", "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", "CustomCodeHostedResponse", "CustomCodeInlineResponse", + "CustomRole", + "CustomRoleAuditLogItem", + "CustomRoleAuditLogItemEventSubType", "Dom", "Domain", "Domains", "DuplicateUserEmail", + "EcommInventoryChangedPayload", "EcommerceSettings", "Error", "ErrorCode", "Field", + "FieldCreate", "FieldType", + "FieldValidations", + "FieldValidationsAdditionalProperties", + "FieldValidationsAdditionalPropertiesAdditionalProperties", "ForbiddenError", "ForbiddenErrorBody", "Form", @@ -280,7 +439,11 @@ "FormResponseSettings", "FormSubmission", "FormSubmissionList", - "ImageNode", + "FormSubmissionTrigger", + "FormSubmissionTriggerPayload", + "FormSubmissionTriggerPayloadSchemaItem", + "FormSubmissionTriggerPayloadSchemaItemFieldType", + "ImageNodeDom", "ImageNodeImage", "InternalServerError", "InvalidDomain", @@ -288,21 +451,34 @@ "InventoryItem", "InventoryItemInventoryType", "InventoryUpdateRequestInventoryType", + "ItemsListItemsLiveRequestLastPublished", + "ItemsListItemsRequestLastPublished", "ListCustomCodeBlocks", "Locale", "Locales", + "Metadata", + "MetadataOptionsItem", + "NewOrder", "NoDomains", "Node", "Node_ComponentInstance", "Node_Image", + "Node_SearchButton", + "Node_Select", + "Node_SubmitButton", "Node_Text", + "Node_TextInput", "NotEnterprisePlanSite", "NotEnterprisePlanWorkspace", "NotFoundError", + "OptionField", "Order", "OrderAddress", "OrderAddressJapanType", "OrderAddressType", + "OrderBillingAddress", + "OrderBillingAddressJapanType", + "OrderBillingAddressType", "OrderCustomerInfo", "OrderDisputeLastStatus", "OrderDownloadFilesItem", @@ -313,6 +489,9 @@ "OrderPurchasedItemVariantImage", "OrderPurchasedItemVariantImageFile", "OrderPurchasedItemVariantImageFileVariantsItem", + "OrderShippingAddress", + "OrderShippingAddressJapanType", + "OrderShippingAddressType", "OrderStatus", "OrderTotals", "OrderTotalsExtrasItem", @@ -320,11 +499,21 @@ "OrdersListRequestStatus", "OrdersRefundRequestReason", "Page", + "PageCreatedWebhook", + "PageCreatedWebhookPayload", + "PageDeletedWebhook", + "PageDeletedWebhookPayload", "PageDomWriteNodesItem", "PageList", + "PageMetadataUpdatedWebhook", + "PageMetadataUpdatedWebhookPayload", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", "PageOpenGraph", "PageSeo", "Pagination", + "Payload", + "PayloadFieldData", "PaypalDetails", "Product", "ProductAndSkUs", @@ -332,15 +521,30 @@ "ProductFieldData", "ProductFieldDataEcProductType", "ProductFieldDataTaxCategory", + "ProductSkuCreateProduct", + "ProductSkuCreateSku", "ProductsCreateSkuResponse", "PublishStatus", "Redirect", "Redirects", + "ReferenceField", + "ReferenceFieldMetadata", + "ReferenceFieldType", "RegisteredScriptList", + "Robots", + "RobotsRulesItem", "ScriptApply", "ScriptApplyList", "ScriptApplyLocation", "Scripts", + "SearchButton", + "SearchButtonNodeDom", + "Select", + "SelectNodeChoicesItem", + "SelectNodeDom", + "SelectNodeWriteChoicesItem", + "SingleLocaleCreatedPayload", + "SingleLocaleCreatedPayloadFieldData", "Site", "SiteActivityLogItem", "SiteActivityLogItemEvent", @@ -348,9 +552,14 @@ "SiteActivityLogItemUser", "SiteActivityLogResponse", "SiteDataCollectionType", + "SiteMembership", + "SiteMembershipAuditLogItem", + "SiteMembershipAuditLogItemEventSubType", "SitePlan", "SitePlanId", "SitePlanName", + "SitePublish", + "SitePublishPayload", "Sites", "SitesPublishResponse", "Sku", @@ -365,21 +574,40 @@ "SkuPropertyList", "SkuPropertyListEnumItem", "SkuValueList", + "StaticField", + "StaticFieldType", "StripeCard", "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "SubmitButton", + "SubmitButtonNodeDom", "Text", + "TextInput", + "TextInputNodeDom", "TextNode", + "TextNodeDom", "TextNodeText", - "TextNodeWrite", "TooManyRequestsError", "TriggerType", "UnauthorizedError", "UpdateStaticContentResponse", + "UpdatedOrder", "User", + "UserAccess", + "UserAccessAuditLogItem", + "UserAccessAuditLogItemEventSubType", "UserAccessGroupsItem", "UserAccessGroupsItemType", + "UserAccountAddedPayload", + "UserAccountAddedPayloadPayload", + "UserAccountAddedPayloadPayloadData", + "UserAccountDeletedPayload", + "UserAccountDeletedPayloadPayload", + "UserAccountDeletedPayloadPayloadData", + "UserAccountUpdatedPayload", + "UserAccountUpdatedPayloadPayload", + "UserAccountUpdatedPayloadPayloadData", "UserData", "UserDataData", "UserLimitReached", @@ -387,12 +615,37 @@ "UserStatus", "UsersListRequestSort", "UsersNotEnabled", - "UsersUpdateRequestData", "Webflow", "WebflowEnvironment", "Webhook", "WebhookFilter", "WebhookList", + "WorkspaceAuditLogItem", + "WorkspaceAuditLogItemActor", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipSite", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType", + "WorkspaceAuditLogItemPayloadUserAccessMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType", + "WorkspaceAuditLogItemWorkspace", + "WorkspaceAuditLogItem_CustomRole", + "WorkspaceAuditLogItem_SiteMembership", + "WorkspaceAuditLogItem_UserAccess", + "WorkspaceAuditLogItem_WorkspaceInvitation", + "WorkspaceAuditLogItem_WorkspaceMembership", + "WorkspaceAuditLogResponse", + "WorkspaceInvitation", + "WorkspaceInvitationAuditLogItem", + "WorkspaceInvitationAuditLogItemEventSubType", + "WorkspaceMembership", + "WorkspaceMembershipAuditLogItem", + "WorkspaceMembershipAuditLogItemEventSubType", "__version__", "access_groups", "assets", @@ -409,4 +662,5 @@ "token", "users", "webhooks", + "workspaces", ] diff --git a/src/webflow/client.py b/src/webflow/client.py index 90c233d..88d7a1a 100644 --- a/src/webflow/client.py +++ b/src/webflow/client.py @@ -1,7 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import typing from .environment import WebflowEnvironment +import typing import httpx from .core.client_wrapper import SyncClientWrapper from .resources.token.client import TokenClient @@ -19,6 +19,7 @@ from .resources.orders.client import OrdersClient from .resources.inventory.client import InventoryClient from .resources.ecommerce.client import EcommerceClient +from .resources.workspaces.client import WorkspacesClient from .core.client_wrapper import AsyncClientWrapper from .resources.token.client import AsyncTokenClient from .resources.sites.client import AsyncSitesClient @@ -35,6 +36,7 @@ from .resources.orders.client import AsyncOrdersClient from .resources.inventory.client import AsyncInventoryClient from .resources.ecommerce.client import AsyncEcommerceClient +from .resources.workspaces.client import AsyncWorkspacesClient class Webflow: @@ -43,15 +45,12 @@ class Webflow: Parameters ---------- - base_url : typing.Optional[str] - The base url to use for requests from the client. - environment : WebflowEnvironment The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT + Defaults to WebflowEnvironment.DATA_API @@ -77,8 +76,7 @@ class Webflow: def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, + environment: WebflowEnvironment = WebflowEnvironment.DATA_API, access_token: typing.Union[str, typing.Callable[[], str]], timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, @@ -86,7 +84,7 @@ def __init__( ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = SyncClientWrapper( - base_url=_get_base_url(base_url=base_url, environment=environment), + environment=environment, access_token=access_token, httpx_client=httpx_client if httpx_client is not None @@ -110,6 +108,7 @@ def __init__( self.orders = OrdersClient(client_wrapper=self._client_wrapper) self.inventory = InventoryClient(client_wrapper=self._client_wrapper) self.ecommerce = EcommerceClient(client_wrapper=self._client_wrapper) + self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper) class AsyncWebflow: @@ -118,15 +117,12 @@ class AsyncWebflow: Parameters ---------- - base_url : typing.Optional[str] - The base url to use for requests from the client. - environment : WebflowEnvironment The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT + Defaults to WebflowEnvironment.DATA_API @@ -152,8 +148,7 @@ class AsyncWebflow: def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, + environment: WebflowEnvironment = WebflowEnvironment.DATA_API, access_token: typing.Union[str, typing.Callable[[], str]], timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, @@ -161,7 +156,7 @@ def __init__( ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = AsyncClientWrapper( - base_url=_get_base_url(base_url=base_url, environment=environment), + environment=environment, access_token=access_token, httpx_client=httpx_client if httpx_client is not None @@ -185,12 +180,4 @@ def __init__( self.orders = AsyncOrdersClient(client_wrapper=self._client_wrapper) self.inventory = AsyncInventoryClient(client_wrapper=self._client_wrapper) self.ecommerce = AsyncEcommerceClient(client_wrapper=self._client_wrapper) - - -def _get_base_url(*, base_url: typing.Optional[str] = None, environment: WebflowEnvironment) -> str: - if base_url is not None: - return base_url - elif environment is not None: - return environment.value - else: - raise Exception("Please pass in either base_url or environment to construct the client") + self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 84ed6fb..e363dd0 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing +from ..environment import WebflowEnvironment import httpx from .http_client import HttpClient from .http_client import AsyncHttpClient @@ -11,18 +12,18 @@ def __init__( self, *, access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, ): self._access_token = access_token - self._base_url = base_url + self._environment = environment self._timeout = timeout def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "2.0.0b1", + "X-Fern-SDK-Version": "1.2.1", } headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers @@ -33,8 +34,8 @@ def _get_access_token(self) -> str: else: return self._access_token() - def get_base_url(self) -> str: - return self._base_url + def get_environment(self) -> WebflowEnvironment: + return self._environment def get_timeout(self) -> typing.Optional[float]: return self._timeout @@ -45,16 +46,13 @@ def __init__( self, *, access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, httpx_client: httpx.Client, ): - super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + super().__init__(access_token=access_token, environment=environment, timeout=timeout) self.httpx_client = HttpClient( - httpx_client=httpx_client, - base_headers=self.get_headers, - base_timeout=self.get_timeout, - base_url=self.get_base_url, + httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout ) @@ -63,14 +61,11 @@ def __init__( self, *, access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, httpx_client: httpx.AsyncClient, ): - super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + super().__init__(access_token=access_token, environment=environment, timeout=timeout) self.httpx_client = AsyncHttpClient( - httpx_client=httpx_client, - base_headers=self.get_headers, - base_timeout=self.get_timeout, - base_url=self.get_base_url, + httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout ) diff --git a/src/webflow/environment.py b/src/webflow/environment.py index ed0e03d..e6fd331 100644 --- a/src/webflow/environment.py +++ b/src/webflow/environment.py @@ -1,7 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -import enum +from __future__ import annotations -class WebflowEnvironment(enum.Enum): - DEFAULT = "https://api.webflow.com/v2" +class WebflowEnvironment: + DATA_API: WebflowEnvironment + + def __init__(self, *, base: str, data_api: str, content_delivery_api: str, production: str, cdn: str): + self.base = base + self.data_api = data_api + self.content_delivery_api = content_delivery_api + self.production = production + self.cdn = cdn + + +WebflowEnvironment.DATA_API = WebflowEnvironment( + base="https://api.webflow.com/v2", + data_api="https://api.webflow.com/v2", + content_delivery_api="https://api-cdn.webflow.com/v2", + production="https://api.webflow.com/v2", + cdn="https://api-cdn.webflow.com/v2", +) diff --git a/src/webflow/resources/__init__.py b/src/webflow/resources/__init__.py index 9122eee..54d7371 100644 --- a/src/webflow/resources/__init__.py +++ b/src/webflow/resources/__init__.py @@ -16,6 +16,7 @@ token, users, webhooks, + workspaces, ) from .access_groups import AccessGroupsListRequestSort from .components import ( @@ -24,12 +25,23 @@ ComponentsUpdateContentResponse, ComponentsUpdatePropertiesResponse, ) -from .inventory import InventoryUpdateRequestInventoryType +from .inventory import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType from .orders import OrdersListRequestStatus, OrdersRefundRequestReason -from .pages import PageDomWriteNodesItem, UpdateStaticContentResponse -from .products import ProductsCreateSkuResponse +from .pages import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse +from .products import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse from .sites import SitesPublishResponse -from .users import UsersListRequestSort, UsersUpdateRequestData +from .users import ( + UserAccountAddedPayload, + UserAccountAddedPayloadPayload, + UserAccountAddedPayloadPayloadData, + UserAccountDeletedPayload, + UserAccountDeletedPayloadPayload, + UserAccountDeletedPayloadPayloadData, + UserAccountUpdatedPayload, + UserAccountUpdatedPayloadPayload, + UserAccountUpdatedPayloadPayloadData, + UsersListRequestSort, +) __all__ = [ "AccessGroupsListRequestSort", @@ -37,15 +49,28 @@ "ComponentPropertiesWritePropertiesItem", "ComponentsUpdateContentResponse", "ComponentsUpdatePropertiesResponse", + "EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType", "OrdersListRequestStatus", "OrdersRefundRequestReason", "PageDomWriteNodesItem", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", + "ProductSkuCreateProduct", + "ProductSkuCreateSku", "ProductsCreateSkuResponse", "SitesPublishResponse", "UpdateStaticContentResponse", + "UserAccountAddedPayload", + "UserAccountAddedPayloadPayload", + "UserAccountAddedPayloadPayloadData", + "UserAccountDeletedPayload", + "UserAccountDeletedPayloadPayload", + "UserAccountDeletedPayloadPayloadData", + "UserAccountUpdatedPayload", + "UserAccountUpdatedPayloadPayload", + "UserAccountUpdatedPayloadPayloadData", "UsersListRequestSort", - "UsersUpdateRequestData", "access_groups", "assets", "collections", @@ -61,4 +86,5 @@ "token", "users", "webhooks", + "workspaces", ] diff --git a/src/webflow/resources/access_groups/client.py b/src/webflow/resources/access_groups/client.py index ee7668a..71654e3 100644 --- a/src/webflow/resources/access_groups/client.py +++ b/src/webflow/resources/access_groups/client.py @@ -73,6 +73,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/accessgroups", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -218,6 +219,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/accessgroups", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, diff --git a/src/webflow/resources/assets/client.py b/src/webflow/resources/assets/client.py index 61e141a..c6e39ef 100644 --- a/src/webflow/resources/assets/client.py +++ b/src/webflow/resources/assets/client.py @@ -30,7 +30,7 @@ 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 + List of assets uploaded to a site Required scope | `assets:read` @@ -60,6 +60,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -137,15 +138,18 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` Parameters ---------- @@ -184,6 +188,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "fileName": file_name, @@ -262,7 +267,7 @@ def create( def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset + Get details about an asset Required scope | `assets:read` @@ -292,6 +297,7 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -390,6 +396,7 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -460,7 +467,7 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset + Update details of an Asset. Required scope | `assets:write` @@ -496,6 +503,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "localeId": locale_id, @@ -603,6 +611,7 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -716,6 +725,7 @@ def create_folder( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, @@ -825,6 +835,7 @@ def get_folder( """ _response = self._client_wrapper.httpx_client.request( f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -899,7 +910,7 @@ 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 + List of assets uploaded to a site Required scope | `assets:read` @@ -937,6 +948,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1014,15 +1026,18 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` Parameters ---------- @@ -1069,6 +1084,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "fileName": file_name, @@ -1147,7 +1163,7 @@ async def main() -> None: async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset + Get details about an asset Required scope | `assets:read` @@ -1185,6 +1201,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1291,6 +1308,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -1361,7 +1379,7 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset + Update details of an Asset. Required scope | `assets:write` @@ -1405,6 +1423,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "localeId": locale_id, @@ -1522,6 +1541,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1643,6 +1663,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, @@ -1760,6 +1781,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/collections/__init__.py b/src/webflow/resources/collections/__init__.py index cb6aaf8..3796806 100644 --- a/src/webflow/resources/collections/__init__.py +++ b/src/webflow/resources/collections/__init__.py @@ -3,16 +3,20 @@ from .resources import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - FieldCreateType, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -23,16 +27,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "FieldCreateType", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/client.py b/src/webflow/resources/collections/client.py index 1e44aae..61495ae 100644 --- a/src/webflow/resources/collections/client.py +++ b/src/webflow/resources/collections/client.py @@ -16,7 +16,10 @@ from ...errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from ...core.api_error import ApiError +from ...types.field_create import FieldCreate from ...types.collection import Collection +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.conflict_error import ConflictError from ...core.client_wrapper import AsyncClientWrapper from .resources.fields.client import AsyncFieldsClient from .resources.items.client import AsyncItemsClient @@ -63,6 +66,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -137,10 +141,13 @@ def create( display_name: str, singular_name: str, slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site. + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write` @@ -158,6 +165,9 @@ def create( slug : typing.Optional[str] Part of a URL that identifier + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -168,7 +178,7 @@ def create( Examples -------- - from webflow import Webflow + from webflow import ReferenceField, ReferenceFieldMetadata, StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -178,15 +188,42 @@ def create( display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, "singularName": singular_name, "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), }, headers={ "content-type": "application/json", @@ -233,6 +270,16 @@ def create( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -290,6 +337,7 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -388,6 +436,7 @@ def delete(self, collection_id: str, *, request_options: typing.Optional[Request """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -496,6 +545,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -570,10 +620,13 @@ async def create( display_name: str, singular_name: str, slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site. + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write` @@ -591,6 +644,9 @@ async def create( slug : typing.Optional[str] Part of a URL that identifier + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -603,7 +659,12 @@ async def create( -------- import asyncio - from webflow import AsyncWebflow + from webflow import ( + AsyncWebflow, + ReferenceField, + ReferenceFieldMetadata, + StaticField, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -616,6 +677,29 @@ async def main() -> None: display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) @@ -623,11 +707,15 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, "singularName": singular_name, "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), }, headers={ "content-type": "application/json", @@ -674,6 +762,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -739,6 +837,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -845,6 +944,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/collections/resources/__init__.py b/src/webflow/resources/collections/resources/__init__.py index f9325ee..4ad4d58 100644 --- a/src/webflow/resources/collections/resources/__init__.py +++ b/src/webflow/resources/collections/resources/__init__.py @@ -1,19 +1,23 @@ # This file was auto-generated by Fern from our API Definition. from . import fields, items -from .fields import FieldCreateType from .items import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -22,16 +26,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "FieldCreateType", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/fields/__init__.py b/src/webflow/resources/collections/resources/fields/__init__.py index 5a5b167..f3ea265 100644 --- a/src/webflow/resources/collections/resources/fields/__init__.py +++ b/src/webflow/resources/collections/resources/fields/__init__.py @@ -1,5 +1,2 @@ # This file was auto-generated by Fern from our API Definition. -from .types import FieldCreateType - -__all__ = ["FieldCreateType"] diff --git a/src/webflow/resources/collections/resources/fields/client.py b/src/webflow/resources/collections/resources/fields/client.py index 40b66cf..c2b7ebc 100644 --- a/src/webflow/resources/collections/resources/fields/client.py +++ b/src/webflow/resources/collections/resources/fields/client.py @@ -2,19 +2,21 @@ import typing from .....core.client_wrapper import SyncClientWrapper -from .types.field_create_type import FieldCreateType +from .....types.field_create import FieldCreate from .....core.request_options import RequestOptions -from .....types.field import Field from .....core.jsonable_encoder import jsonable_encoder +from .....core.serialization import convert_and_respect_annotation_metadata from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError from .....errors.unauthorized_error import UnauthorizedError from .....types.error import Error from .....errors.not_found_error import NotFoundError +from .....errors.conflict_error import ConflictError from .....errors.too_many_requests_error import TooManyRequestsError from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from .....core.api_error import ApiError +from .....types.field import Field from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters @@ -26,24 +28,14 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def create( - self, - collection_id: str, - *, - type: FieldCreateType, - display_name: str, - is_required: typing.Optional[bool] = OMIT, - help_text: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Field: + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> FieldCreate: """ Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. - If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will - convert the slug to lowercase and replace spaces with "-." + Field validation is currently not available through the API. - Only some field types can be created through the API. - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -52,62 +44,49 @@ def create( collection_id : str Unique identifier for a Collection - type : FieldCreateType - Choose these appropriate field type for your collection data - - display_name : str - The name of a field - - is_required : typing.Optional[bool] - define whether a field is required in a collection - - help_text : typing.Optional[str] - Additional text to help anyone filling out this field + request : FieldCreate request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - Field + FieldCreate Request was successful Examples -------- - from webflow import Webflow + from webflow import StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "isRequired": is_required, - "type": type, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: return typing.cast( - Field, + FieldCreate, parse_obj_as( - type_=Field, # type: ignore + type_=FieldCreate, # type: ignore object_=_response.json(), ), ) @@ -141,6 +120,16 @@ def create( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -203,6 +192,7 @@ def delete( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -321,6 +311,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "isRequired": is_required, @@ -403,24 +394,14 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def create( - self, - collection_id: str, - *, - type: FieldCreateType, - display_name: str, - is_required: typing.Optional[bool] = OMIT, - help_text: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Field: + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> FieldCreate: """ Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. - If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will - convert the slug to lowercase and replace spaces with "-." + Field validation is currently not available through the API. - Only some field types can be created through the API. - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -429,31 +410,21 @@ async def create( collection_id : str Unique identifier for a Collection - type : FieldCreateType - Choose these appropriate field type for your collection data - - display_name : str - The name of a field - - is_required : typing.Optional[bool] - define whether a field is required in a collection - - help_text : typing.Optional[str] - Additional text to help anyone filling out this field + request : FieldCreate request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - Field + FieldCreate Request was successful Examples -------- import asyncio - from webflow import AsyncWebflow + from webflow import AsyncWebflow, StaticField client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -463,10 +434,14 @@ async def create( async def main() -> None: await client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) @@ -474,25 +449,18 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "isRequired": is_required, - "type": type, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: return typing.cast( - Field, + FieldCreate, parse_obj_as( - type_=Field, # type: ignore + type_=FieldCreate, # type: ignore object_=_response.json(), ), ) @@ -526,6 +494,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -596,6 +574,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -722,6 +701,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "isRequired": is_required, diff --git a/src/webflow/resources/collections/resources/fields/types/__init__.py b/src/webflow/resources/collections/resources/fields/types/__init__.py deleted file mode 100644 index c17230e..0000000 --- a/src/webflow/resources/collections/resources/fields/types/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .field_create_type import FieldCreateType - -__all__ = ["FieldCreateType"] diff --git a/src/webflow/resources/collections/resources/items/__init__.py b/src/webflow/resources/collections/resources/items/__init__.py index fbccd1b..7dce40c 100644 --- a/src/webflow/resources/collections/resources/items/__init__.py +++ b/src/webflow/resources/collections/resources/items/__init__.py @@ -3,15 +3,20 @@ from .types import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -20,15 +25,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/items/client.py b/src/webflow/resources/collections/resources/items/client.py index 47f8f90..d09f352 100644 --- a/src/webflow/resources/collections/resources/items/client.py +++ b/src/webflow/resources/collections/resources/items/client.py @@ -2,11 +2,13 @@ import typing from .....core.client_wrapper import SyncClientWrapper +from .....types.items_list_items_request_last_published import ItemsListItemsRequestLastPublished from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder from .....core.request_options import RequestOptions from .....types.collection_item_list import CollectionItemList from .....core.jsonable_encoder import jsonable_encoder +from .....core.serialization import convert_and_respect_annotation_metadata from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError from .....errors.unauthorized_error import UnauthorizedError @@ -16,20 +18,22 @@ from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from .....core.api_error import ApiError -from .types.items_create_item_request import ItemsCreateItemRequest +from .types.items_create_item_request_body import ItemsCreateItemRequestBody from .....types.collection_item import CollectionItem -from .....core.serialization import convert_and_respect_annotation_metadata from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem from .....errors.conflict_error import ConflictError from .....types.collection_item_with_id_input import CollectionItemWithIdInput +from .types.items_update_items_response import ItemsUpdateItemsResponse +from .....types.items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder -from .types.items_create_item_live_request import ItemsCreateItemLiveRequest +from .types.items_create_item_live_request_body import ItemsCreateItemLiveRequestBody from .types.items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData from .....types.bulk_collection_item import BulkCollectionItem from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .types.items_publish_item_request import ItemsPublishItemRequest from .types.items_publish_item_response import ItemsPublishItemResponse from .....core.client_wrapper import AsyncClientWrapper @@ -50,6 +54,7 @@ def list_items( limit: typing.Optional[float] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, @@ -74,10 +79,13 @@ 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 + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -106,6 +114,7 @@ def list_items( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -113,6 +122,9 @@ def list_items( "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -186,14 +198,15 @@ def create_item( self, collection_id: str, *, - request: ItemsCreateItemRequest, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Create Item(s) in a Collection. - To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -202,7 +215,10 @@ def create_item( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemRequest + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -237,9 +253,13 @@ def create_item( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequest, direction="write" + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -312,13 +332,13 @@ def delete_items( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -327,7 +347,7 @@ def delete_items( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -339,16 +359,25 @@ def delete_items( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -433,13 +462,16 @@ def update_items( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItem: + ) -> ItemsUpdateItemsResponse: """ - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + The limit for this endpoint is 100 items. + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -448,6 +480,9 @@ def update_items( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -455,7 +490,7 @@ def update_items( Returns ------- - CollectionItem + ItemsUpdateItemsResponse Request was successful Examples @@ -509,7 +544,11 @@ def update_items( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -524,9 +563,9 @@ def update_items( try: if 200 <= _response.status_code < 300: return typing.cast( - CollectionItem, + ItemsUpdateItemsResponse, parse_obj_as( - type_=CollectionItem, # type: ignore + type_=ItemsUpdateItemsResponse, # type: ignore object_=_response.json(), ), ) @@ -594,12 +633,18 @@ def list_items_live( limit: typing.Optional[float] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all live Items within a Collection. + List all published items in a collection. + + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + Required scope | `CMS:read` @@ -618,10 +663,13 @@ 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 + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] Sort results by the provided value @@ -650,6 +698,7 @@ def list_items_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -657,6 +706,9 @@ def list_items_live( "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -730,14 +782,15 @@ def create_item_live( self, collection_id: str, *, - request: ItemsCreateItemLiveRequest, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Create live Item(s) in a Collection. The Item(s) will be published to the live site. + Create item(s) in a collection that will be immediately published to the live site. - To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -747,7 +800,10 @@ def create_item_live( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemLiveRequest + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -778,9 +834,13 @@ def create_item_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -853,13 +913,13 @@ def delete_items_live( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -868,7 +928,7 @@ def delete_items_live( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -880,16 +940,25 @@ def delete_items_live( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -964,13 +1033,14 @@ def update_items_live( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemListNoPagination: """ - Update a single live item or multiple live items (up to 100) in a Collection + Update a single published item or multiple published items (up to 100) in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -979,6 +1049,9 @@ def update_items_live( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -1040,7 +1113,11 @@ def update_items_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -1091,6 +1168,16 @@ def update_items_live( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -1121,6 +1208,7 @@ def create_items( collection_id: str, *, field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, @@ -1129,9 +1217,10 @@ def create_items( """ Create an item or multiple items in a CMS Collection across multiple corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + Required scope | `CMS:write` @@ -1142,6 +1231,9 @@ def create_items( field_data : CreateBulkCollectionItemRequestBodyFieldData + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + cms_locale_ids : typing.Optional[typing.Sequence[str]] Array of identifiers for the locales where the item will be created @@ -1184,7 +1276,11 @@ def create_items( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "cmsLocaleIds": cms_locale_ids, "isArchived": is_archived, @@ -1309,6 +1405,7 @@ def get_item( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().production, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -1388,7 +1485,7 @@ def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + Delete an item from a collection. Required scope | `CMS:write` @@ -1424,6 +1521,7 @@ def delete_item( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -1493,6 +1591,7 @@ def update_item( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -1516,6 +1615,9 @@ def update_item( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -1567,7 +1669,11 @@ def update_item( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -1658,6 +1764,11 @@ def get_item_live( """ Get details of a selected Collection live Item. + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + + Required scope | `CMS:read` Parameters @@ -1693,6 +1804,7 @@ def get_item_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -1772,9 +1884,9 @@ def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + Unpublish a live item from the site and set the `isDraft` property to `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -1810,6 +1922,7 @@ def delete_item_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -1879,6 +1992,7 @@ def update_item_live( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -1902,6 +2016,9 @@ def update_item_live( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -1953,7 +2070,11 @@ def update_item_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -2008,6 +2129,16 @@ def update_item_live( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -2037,7 +2168,7 @@ def publish_item( self, collection_id: str, *, - item_ids: typing.Sequence[str], + request: ItemsPublishItemRequest, request_options: typing.Optional[RequestOptions] = None, ) -> ItemsPublishItemResponse: """ @@ -2050,7 +2181,7 @@ def publish_item( collection_id : str Unique identifier for a Collection - item_ids : typing.Sequence[str] + request : ItemsPublishItemRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2063,24 +2194,29 @@ def publish_item( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ItemIDs client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], + request=ItemIDs( + item_ids=[ + "643fd856d66b6528195ee2ca", + "643fd856d66b6528195ee2cb", + "643fd856d66b6528195ee2cc", + ], + ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "itemIds": item_ids, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) @@ -2172,6 +2308,7 @@ async def list_items( limit: typing.Optional[float] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, @@ -2196,10 +2333,13 @@ 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 + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -2236,6 +2376,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -2243,6 +2384,9 @@ async def main() -> None: "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -2316,14 +2460,15 @@ async def create_item( self, collection_id: str, *, - request: ItemsCreateItemRequest, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Create Item(s) in a Collection. - To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -2332,7 +2477,10 @@ async def create_item( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemRequest + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2375,9 +2523,13 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequest, direction="write" + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -2450,13 +2602,13 @@ async def delete_items( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -2465,7 +2617,7 @@ async def delete_items( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2479,6 +2631,9 @@ async def delete_items( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -2488,6 +2643,11 @@ async def delete_items( async def main() -> None: await client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) @@ -2495,6 +2655,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -2579,13 +2740,16 @@ async def update_items( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItem: + ) -> ItemsUpdateItemsResponse: """ - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. + + The limit for this endpoint is 100 items. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -2594,6 +2758,9 @@ async def update_items( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -2601,7 +2768,7 @@ async def update_items( Returns ------- - CollectionItem + ItemsUpdateItemsResponse Request was successful Examples @@ -2663,7 +2830,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -2678,9 +2849,9 @@ async def main() -> None: try: if 200 <= _response.status_code < 300: return typing.cast( - CollectionItem, + ItemsUpdateItemsResponse, parse_obj_as( - type_=CollectionItem, # type: ignore + type_=ItemsUpdateItemsResponse, # type: ignore object_=_response.json(), ), ) @@ -2748,12 +2919,18 @@ async def list_items_live( limit: typing.Optional[float] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all live Items within a Collection. + List all published items in a collection. + + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + Required scope | `CMS:read` @@ -2772,10 +2949,13 @@ async 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 + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] Sort results by the provided value @@ -2812,6 +2992,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -2819,6 +3000,9 @@ async def main() -> None: "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -2892,14 +3076,15 @@ async def create_item_live( self, collection_id: str, *, - request: ItemsCreateItemLiveRequest, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Create live Item(s) in a Collection. The Item(s) will be published to the live site. + Create item(s) in a collection that will be immediately published to the live site. - To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -2909,7 +3094,10 @@ async def create_item_live( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemLiveRequest + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2948,9 +3136,13 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -3023,13 +3215,13 @@ async def delete_items_live( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -3038,7 +3230,7 @@ async def delete_items_live( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -3052,6 +3244,9 @@ async def delete_items_live( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -3061,6 +3256,11 @@ async def delete_items_live( async def main() -> None: await client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) @@ -3068,6 +3268,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -3142,13 +3343,14 @@ async def update_items_live( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemListNoPagination: """ - Update a single live item or multiple live items (up to 100) in a Collection + Update a single published item or multiple published items (up to 100) in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -3157,6 +3359,9 @@ async def update_items_live( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -3226,7 +3431,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -3277,6 +3486,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -3307,6 +3526,7 @@ async def create_items( collection_id: str, *, field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, @@ -3315,9 +3535,10 @@ async def create_items( """ Create an item or multiple items in a CMS Collection across multiple corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + Required scope | `CMS:write` @@ -3328,6 +3549,9 @@ async def create_items( field_data : CreateBulkCollectionItemRequestBodyFieldData + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + cms_locale_ids : typing.Optional[typing.Sequence[str]] Array of identifiers for the locales where the item will be created @@ -3378,7 +3602,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "cmsLocaleIds": cms_locale_ids, "isArchived": is_archived, @@ -3511,6 +3739,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().production, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -3590,7 +3819,7 @@ async def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + Delete an item from a collection. Required scope | `CMS:write` @@ -3634,6 +3863,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -3703,6 +3933,7 @@ async def update_item( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -3726,6 +3957,9 @@ async def update_item( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -3785,7 +4019,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -3876,6 +4114,11 @@ async def get_item_live( """ Get details of a selected Collection live Item. + + To serve content to your other frontends applications, enterprise sites have access to a dedicated [content delivery API](/data/docs/cms-content-delivery), available at api-cdn.webflow.com. + + + Required scope | `CMS:read` Parameters @@ -3919,6 +4162,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -3998,9 +4242,9 @@ async def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + Unpublish a live item from the site and set the `isDraft` property to `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -4044,6 +4288,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -4113,6 +4358,7 @@ async def update_item_live( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -4136,6 +4382,9 @@ async def update_item_live( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -4195,7 +4444,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -4250,6 +4503,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -4279,7 +4542,7 @@ async def publish_item( self, collection_id: str, *, - item_ids: typing.Sequence[str], + request: ItemsPublishItemRequest, request_options: typing.Optional[RequestOptions] = None, ) -> ItemsPublishItemResponse: """ @@ -4292,7 +4555,7 @@ async def publish_item( collection_id : str Unique identifier for a Collection - item_ids : typing.Sequence[str] + request : ItemsPublishItemRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -4307,6 +4570,7 @@ async def publish_item( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ItemIDs client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -4316,7 +4580,13 @@ async def publish_item( async def main() -> None: await client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], + request=ItemIDs( + item_ids=[ + "643fd856d66b6528195ee2ca", + "643fd856d66b6528195ee2cb", + "643fd856d66b6528195ee2cc", + ], + ), ) @@ -4324,13 +4594,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "itemIds": item_ids, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) diff --git a/src/webflow/resources/collections/resources/items/types/__init__.py b/src/webflow/resources/collections/resources/items/types/__init__.py index 67040fb..2d9a604 100644 --- a/src/webflow/resources/collections/resources/items/types/__init__.py +++ b/src/webflow/resources/collections/resources/items/types/__init__.py @@ -2,15 +2,20 @@ from .create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem -from .items_create_item_live_request import ItemsCreateItemLiveRequest -from .items_create_item_request import ItemsCreateItemRequest +from .item_i_ds import ItemIDs +from .item_i_ds_with_locales import ItemIDsWithLocales +from .items_create_item_live_request_body import ItemsCreateItemLiveRequestBody +from .items_create_item_request_body import ItemsCreateItemRequestBody from .items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem from .items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder +from .items_publish_item_request import ItemsPublishItemRequest +from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem from .items_publish_item_response import ItemsPublishItemResponse +from .items_update_items_response import ItemsUpdateItemsResponse from .multiple_items import MultipleItems from .multiple_live_items import MultipleLiveItems from .single_cms_item import SingleCmsItem @@ -18,15 +23,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds.py b/src/webflow/resources/collections/resources/items/types/item_i_ds.py new file mode 100644 index 0000000..b9b138e --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ItemIDs(UniversalBaseModel): + """ + An array of Item IDs in a single locale + """ + + item_ids: typing_extensions.Annotated[typing.Optional[typing.List[str]], FieldMetadata(alias="itemIds")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py new file mode 100644 index 0000000..ba98ae7 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing +from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ItemIDsWithLocales(UniversalBaseModel): + """ + An array of Item IDs with included `cmsLocaleIds` + """ + + items: typing.Optional[typing.List[ItemsPublishItemRequestItemsItemsItem]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py similarity index 69% rename from src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py rename to src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py index dc2f963..348e0be 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py @@ -4,4 +4,4 @@ from ......types.collection_item import CollectionItem from .multiple_live_items import MultipleLiveItems -ItemsCreateItemLiveRequest = typing.Union[CollectionItem, MultipleLiveItems] +ItemsCreateItemLiveRequestBody = typing.Union[CollectionItem, MultipleLiveItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py similarity index 70% rename from src/webflow/resources/collections/resources/items/types/items_create_item_request.py rename to src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py index 7627c55..af4860a 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_request.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py @@ -4,4 +4,4 @@ from ......types.collection_item_post_single import CollectionItemPostSingle from .multiple_items import MultipleItems -ItemsCreateItemRequest = typing.Union[CollectionItemPostSingle, MultipleItems] +ItemsCreateItemRequestBody = typing.Union[CollectionItemPostSingle, MultipleItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py index 63e00bc..544df88 100644 --- a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py @@ -1,15 +1,15 @@ # This file was auto-generated by Fern from our API Definition. from ......core.pydantic_utilities import UniversalBaseModel -import typing_extensions -from ......core.serialization import FieldMetadata import pydantic +import typing_extensions import typing +from ......core.serialization import FieldMetadata from ......core.pydantic_utilities import IS_PYDANTIC_V2 class ItemsDeleteItemsLiveRequestItemsItem(UniversalBaseModel): - item_id: typing_extensions.Annotated[str, FieldMetadata(alias="itemId")] = pydantic.Field() + id: str = pydantic.Field() """ Unique identifier for the Item """ diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py new file mode 100644 index 0000000..4f7a82b --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .item_i_ds import ItemIDs +from .item_i_ds_with_locales import ItemIDsWithLocales + +ItemsPublishItemRequest = typing.Union[ItemIDs, ItemIDsWithLocales] diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py new file mode 100644 index 0000000..08b2e17 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsPublishItemRequestItemsItemsItem(UniversalBaseModel): + id: str = pydantic.Field() + """ + The ID of the CMS item + """ + + cms_locale_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") + ] = pydantic.Field(default=None) + """ + Array of identifiers for the locales where the item will be published + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_update_items_response.py b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py new file mode 100644 index 0000000..c073f18 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ......types.collection_item import CollectionItem +from ......types.collection_item_list import CollectionItemList + +ItemsUpdateItemsResponse = typing.Union[CollectionItem, CollectionItemList] diff --git a/src/webflow/resources/components/client.py b/src/webflow/resources/components/client.py index ef50ac9..b507e83 100644 --- a/src/webflow/resources/components/client.py +++ b/src/webflow/resources/components/client.py @@ -36,6 +36,7 @@ def list( self, site_id: str, *, + branch_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, @@ -50,6 +51,9 @@ def list( site_id : str Unique identifier for a Site + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -73,12 +77,15 @@ def list( ) client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -154,12 +161,13 @@ def get_content( component_id: str, *, locale_id: typing.Optional[str] = None, + branch_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. + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -177,6 +185,9 @@ def get_content( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -202,13 +213,16 @@ def get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -285,6 +299,7 @@ def update_content( *, nodes: typing.Sequence[ComponentDomWriteNodesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdateContentResponse: """ @@ -314,6 +329,9 @@ def update_content( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -325,9 +343,13 @@ def update_content( Examples -------- from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, Webflow, ) @@ -338,16 +360,39 @@ def update_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -365,9 +410,11 @@ def update_content( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "nodes": convert_and_respect_annotation_metadata( @@ -460,14 +507,15 @@ def get_properties( component_id: str, *, locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentProperties: """ - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read` @@ -482,6 +530,9 @@ def get_properties( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -507,13 +558,16 @@ def get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -590,15 +644,15 @@ def update_properties( *, properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdatePropertiesResponse: """ - Update the property default values of a component definition in a specificed locale. + Update the default property values of a component definition in a specificed locale. - Before making updates: - 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + 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 locale is missing, the request will not be processed and will result in an error. + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write` @@ -616,6 +670,9 @@ def update_properties( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -636,6 +693,7 @@ def update_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -650,9 +708,11 @@ def update_properties( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "properties": convert_and_respect_annotation_metadata( @@ -740,6 +800,7 @@ async def list( self, site_id: str, *, + branch_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, @@ -754,6 +815,9 @@ async def list( site_id : str Unique identifier for a Site + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -782,6 +846,7 @@ async def list( async def main() -> None: await client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", ) @@ -789,8 +854,10 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -866,12 +933,13 @@ async def get_content( component_id: str, *, locale_id: typing.Optional[str] = None, + branch_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. + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -889,6 +957,9 @@ async def get_content( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -919,6 +990,7 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) @@ -926,9 +998,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -1005,6 +1079,7 @@ async def update_content( *, nodes: typing.Sequence[ComponentDomWriteNodesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdateContentResponse: """ @@ -1034,6 +1109,9 @@ async def update_content( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1048,9 +1126,13 @@ async def update_content( from webflow import ( AsyncWebflow, - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, ) client = AsyncWebflow( @@ -1063,16 +1145,39 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -1093,9 +1198,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "nodes": convert_and_respect_annotation_metadata( @@ -1188,14 +1295,15 @@ async def get_properties( component_id: str, *, locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentProperties: """ - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read` @@ -1210,6 +1318,9 @@ async def get_properties( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + limit : typing.Optional[float] Maximum number of records to be returned (max limit: 100) @@ -1240,6 +1351,7 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) @@ -1247,9 +1359,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -1326,15 +1440,15 @@ async def update_properties( *, properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdatePropertiesResponse: """ - Update the property default values of a component definition in a specificed locale. + Update the default property values of a component definition in a specificed locale. - Before making updates: - 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + 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 locale is missing, the request will not be processed and will result in an error. + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write` @@ -1352,6 +1466,9 @@ async def update_properties( locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1377,6 +1494,7 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -1394,9 +1512,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "properties": convert_and_respect_annotation_metadata( diff --git a/src/webflow/resources/components/types/component_dom_write_nodes_item.py b/src/webflow/resources/components/types/component_dom_write_nodes_item.py index 27888e6..7bc7435 100644 --- a/src/webflow/resources/components/types/component_dom_write_nodes_item.py +++ b/src/webflow/resources/components/types/component_dom_write_nodes_item.py @@ -1,7 +1,11 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ....types.text_node_write import TextNodeWrite -from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.text_node import TextNode +from ....types.component_instance import ComponentInstance +from ....types.select import Select +from ....types.text_input import TextInput +from ....types.submit_button import SubmitButton +from ....types.search_button import SearchButton -ComponentDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] +ComponentDomWriteNodesItem = typing.Union[TextNode, ComponentInstance, Select, TextInput, SubmitButton, SearchButton] diff --git a/src/webflow/resources/ecommerce/client.py b/src/webflow/resources/ecommerce/client.py index bbd3a5d..04ddba6 100644 --- a/src/webflow/resources/ecommerce/client.py +++ b/src/webflow/resources/ecommerce/client.py @@ -57,6 +57,7 @@ def get_settings( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -191,6 +192,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/forms/client.py b/src/webflow/resources/forms/client.py index 515b631..05b3da5 100644 --- a/src/webflow/resources/forms/client.py +++ b/src/webflow/resources/forms/client.py @@ -74,6 +74,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -197,6 +198,7 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -285,6 +287,12 @@ def list_submissions( """ List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` Parameters @@ -319,6 +327,7 @@ def list_submissions( """ _response = self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -434,6 +443,7 @@ def get_submission( """ _response = self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -511,6 +521,122 @@ def get_submission( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.forms.delete_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def update_submission( self, form_submission_id: str, @@ -552,6 +678,7 @@ def update_submission( """ _response = self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "formSubmissionData": form_submission_data, @@ -646,6 +773,141 @@ def update_submission( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def list_submissions_by_site( + self, + site_id: str, + *, + element_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> FormSubmissionList: + """ + List form submissions for a given site. This endpoint differs from the existing [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) by accepting `siteId` as a path parameter and `elementId` as a query parameter. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list). + + + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[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. + + Returns + ------- + FormSubmissionList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "elementId": element_id, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncFormsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -704,6 +966,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -835,6 +1098,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -923,6 +1187,12 @@ async def list_submissions( """ List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` Parameters @@ -965,6 +1235,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -1088,6 +1359,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1165,6 +1437,130 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + async def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.forms.delete_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def update_submission( self, form_submission_id: str, @@ -1214,6 +1610,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "formSubmissionData": form_submission_data, @@ -1307,3 +1704,146 @@ async def main() -> None: 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_by_site( + self, + site_id: str, + *, + element_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> FormSubmissionList: + """ + List form submissions for a given site. This endpoint differs from the existing [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) by accepting `siteId` as a path parameter and `elementId` as a query parameter. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list). + + + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[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. + + Returns + ------- + FormSubmissionList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "elementId": element_id, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/inventory/__init__.py b/src/webflow/resources/inventory/__init__.py index f95deee..e76ae2e 100644 --- a/src/webflow/resources/inventory/__init__.py +++ b/src/webflow/resources/inventory/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import InventoryUpdateRequestInventoryType +from .types import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType -__all__ = ["InventoryUpdateRequestInventoryType"] +__all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/client.py b/src/webflow/resources/inventory/client.py index 27e4f3c..db582a9 100644 --- a/src/webflow/resources/inventory/client.py +++ b/src/webflow/resources/inventory/client.py @@ -28,7 +28,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def list( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> InventoryItem: """ List the current inventory levels for a particular SKU item. @@ -37,11 +37,11 @@ def list( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -59,12 +59,13 @@ def list( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -154,8 +155,8 @@ def list( def update( self, - collection_id: str, - item_id: str, + sku_collection_id: str, + sku_id: str, *, inventory_type: InventoryUpdateRequestInventoryType, update_quantity: typing.Optional[float] = OMIT, @@ -173,11 +174,11 @@ def update( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU inventory_type : InventoryUpdateRequestInventoryType infinite or finite @@ -204,13 +205,14 @@ def update( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", inventory_type="infinite", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "inventoryType": inventory_type, @@ -313,7 +315,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def list( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> InventoryItem: """ List the current inventory levels for a particular SKU item. @@ -322,11 +324,11 @@ async def list( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -349,15 +351,16 @@ async def list( async def main() -> None: await client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -447,8 +450,8 @@ async def main() -> None: async def update( self, - collection_id: str, - item_id: str, + sku_collection_id: str, + sku_id: str, *, inventory_type: InventoryUpdateRequestInventoryType, update_quantity: typing.Optional[float] = OMIT, @@ -466,11 +469,11 @@ async def update( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU inventory_type : InventoryUpdateRequestInventoryType infinite or finite @@ -502,8 +505,8 @@ async def update( async def main() -> None: await client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", inventory_type="infinite", ) @@ -511,7 +514,8 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "inventoryType": inventory_type, diff --git a/src/webflow/resources/inventory/types/__init__.py b/src/webflow/resources/inventory/types/__init__.py index e929f4e..4cf7822 100644 --- a/src/webflow/resources/inventory/types/__init__.py +++ b/src/webflow/resources/inventory/types/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +from .ecomm_inventory_changed_payload import EcommInventoryChangedPayload from .inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType -__all__ = ["InventoryUpdateRequestInventoryType"] +__all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py new file mode 100644 index 0000000..f4a969e --- /dev/null +++ b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from ....types.inventory_item import InventoryItem +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class EcommInventoryChangedPayload(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["ecomm_inventory_changed"]], FieldMetadata(alias="triggerType") + ] = None + payload: typing.Optional[InventoryItem] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/orders/client.py b/src/webflow/resources/orders/client.py index 4aa4b77..9b79918 100644 --- a/src/webflow/resources/orders/client.py +++ b/src/webflow/resources/orders/client.py @@ -78,6 +78,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "status": status, @@ -207,6 +208,7 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -354,6 +356,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "comment": comment, @@ -497,6 +500,7 @@ def update_fulfill( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sendOrderFulfilledEmail": send_order_fulfilled_email, @@ -629,6 +633,7 @@ def update_unfulfill( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", request_options=request_options, ) @@ -763,6 +768,7 @@ def refund( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "reason": reason, @@ -919,6 +925,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "status": status, @@ -1058,6 +1065,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1213,6 +1221,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "comment": comment, @@ -1364,6 +1373,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sendOrderFulfilledEmail": send_order_fulfilled_email, @@ -1504,6 +1514,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", request_options=request_options, ) @@ -1646,6 +1657,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "reason": reason, diff --git a/src/webflow/resources/pages/__init__.py b/src/webflow/resources/pages/__init__.py index 0fed8e6..898d3de 100644 --- a/src/webflow/resources/pages/__init__.py +++ b/src/webflow/resources/pages/__init__.py @@ -1,6 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from .types import PageDomWriteNodesItem, UpdateStaticContentResponse +from .types import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse from .resources import scripts -__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse", "scripts"] +__all__ = [ + "PageDomWriteNodesItem", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", + "UpdateStaticContentResponse", + "scripts", +] diff --git a/src/webflow/resources/pages/client.py b/src/webflow/resources/pages/client.py index 851f4e7..382a3ae 100644 --- a/src/webflow/resources/pages/client.py +++ b/src/webflow/resources/pages/client.py @@ -16,9 +16,8 @@ from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...types.page import Page -import datetime as dt -from ...types.page_seo import PageSeo -from ...types.page_open_graph import PageOpenGraph +from .types.page_metadata_write_seo import PageMetadataWriteSeo +from .types.page_metadata_write_open_graph import PageMetadataWriteOpenGraph from ...core.serialization import convert_and_respect_annotation_metadata from ...types.dom import Dom from ...errors.forbidden_error import ForbiddenError @@ -86,6 +85,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -200,6 +200,7 @@ def get_metadata( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -274,29 +275,20 @@ def update_page_settings( self, page_id: str, *, - id: str, locale_id: typing.Optional[str] = None, - site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, - parent_id: typing.Optional[str] = OMIT, - collection_id: typing.Optional[str] = OMIT, - created_on: typing.Optional[dt.datetime] = OMIT, - last_updated: typing.Optional[dt.datetime] = OMIT, - archived: typing.Optional[bool] = OMIT, - draft: typing.Optional[bool] = OMIT, - can_branch: typing.Optional[bool] = OMIT, - is_branch: typing.Optional[bool] = OMIT, - is_members_only: typing.Optional[bool] = OMIT, - seo: typing.Optional[PageSeo] = OMIT, - open_graph: typing.Optional[PageOpenGraph] = OMIT, - page_locale_id: typing.Optional[str] = OMIT, - published_path: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Page: """ Update Page-level metadata, including SEO and Open Graph fields. + + Note: When updating Page Metadata in secondary locales, you may only add `slug` to the request if your Site has the [Advanced or Enterprise Localization](https://webflow.com/localization) add-on. + + Required scope | `pages:write` Parameters @@ -304,60 +296,21 @@ def update_page_settings( page_id : str Unique identifier for a Page - id : str - Unique identifier for the Page - locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. - site_id : typing.Optional[str] - Unique identifier for the Site - title : typing.Optional[str] - Title of the Page + Title for the page slug : typing.Optional[str] - slug of the Page (derived from title) - - parent_id : typing.Optional[str] - Identifier of the parent folder - - collection_id : typing.Optional[str] - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - - created_on : typing.Optional[dt.datetime] - The date the Page was created - - last_updated : typing.Optional[dt.datetime] - The date the Page was most recently updated + Slug for the page - archived : typing.Optional[bool] - Whether the Page has been archived - - draft : typing.Optional[bool] - Whether the Page is a draft - - can_branch : typing.Optional[bool] - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) - - is_branch : typing.Optional[bool] - Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) - - is_members_only : typing.Optional[bool] - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - - seo : typing.Optional[PageSeo] + seo : typing.Optional[PageMetadataWriteSeo] SEO-related fields for the Page - open_graph : typing.Optional[PageOpenGraph] + open_graph : typing.Optional[PageMetadataWriteOpenGraph] Open Graph fields for the Page - page_locale_id : typing.Optional[str] - Unique ID of the page locale - - published_path : typing.Optional[str] - Relative path of the published page URL - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -368,9 +321,11 @@ def update_page_settings( Examples -------- - import datetime - - from webflow import PageOpenGraph, PageSeo, Webflow + from webflow import Webflow + from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -378,60 +333,39 @@ def update_page_settings( client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="PUT", params={ "localeId": locale_id, }, json={ - "id": id, - "siteId": site_id, "title": title, "slug": slug, - "parentId": parent_id, - "collectionId": collection_id, - "createdOn": created_on, - "lastUpdated": last_updated, - "archived": archived, - "draft": draft, - "canBranch": can_branch, - "isBranch": is_branch, - "isMembersOnly": is_members_only, - "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageOpenGraph, direction="write" + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" ), - "localeId": locale_id, - "publishedPath": published_path, + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -510,10 +444,11 @@ def get_content( request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page. This includes text nodes, image nodes and component instances. - To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + Get content from a static page. This includes text nodes, image nodes, select nodes, text input nodes, submit button 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 provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + 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` @@ -553,6 +488,7 @@ def get_content( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -678,9 +614,13 @@ def update_static_content( Examples -------- from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, Webflow, ) @@ -691,15 +631,37 @@ def update_static_content( page_id="63c720f9347c2139b248e552", locale_id="localeId", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -717,6 +679,7 @@ def update_static_content( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, @@ -870,6 +833,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -992,6 +956,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -1066,29 +1031,20 @@ async def update_page_settings( self, page_id: str, *, - id: str, locale_id: typing.Optional[str] = None, - site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, - parent_id: typing.Optional[str] = OMIT, - collection_id: typing.Optional[str] = OMIT, - created_on: typing.Optional[dt.datetime] = OMIT, - last_updated: typing.Optional[dt.datetime] = OMIT, - archived: typing.Optional[bool] = OMIT, - draft: typing.Optional[bool] = OMIT, - can_branch: typing.Optional[bool] = OMIT, - is_branch: typing.Optional[bool] = OMIT, - is_members_only: typing.Optional[bool] = OMIT, - seo: typing.Optional[PageSeo] = OMIT, - open_graph: typing.Optional[PageOpenGraph] = OMIT, - page_locale_id: typing.Optional[str] = OMIT, - published_path: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Page: """ Update Page-level metadata, including SEO and Open Graph fields. + + Note: When updating Page Metadata in secondary locales, you may only add `slug` to the request if your Site has the [Advanced or Enterprise Localization](https://webflow.com/localization) add-on. + + Required scope | `pages:write` Parameters @@ -1096,60 +1052,21 @@ async def update_page_settings( page_id : str Unique identifier for a Page - id : str - Unique identifier for the Page - locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. - site_id : typing.Optional[str] - Unique identifier for the Site - title : typing.Optional[str] - Title of the Page + Title for the page slug : typing.Optional[str] - slug of the Page (derived from title) - - parent_id : typing.Optional[str] - Identifier of the parent folder - - collection_id : typing.Optional[str] - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - - created_on : typing.Optional[dt.datetime] - The date the Page was created + Slug for the page - 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 : typing.Optional[PageMetadataWriteSeo] SEO-related fields for the Page - open_graph : typing.Optional[PageOpenGraph] + open_graph : typing.Optional[PageMetadataWriteOpenGraph] Open Graph fields for the Page - page_locale_id : typing.Optional[str] - Unique ID of the page locale - - published_path : typing.Optional[str] - Relative path of the published page URL - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1161,9 +1078,12 @@ async def update_page_settings( Examples -------- import asyncio - import datetime - from webflow import AsyncWebflow, PageOpenGraph, PageSeo + from webflow import AsyncWebflow + from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1174,32 +1094,18 @@ async def main() -> None: await client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) @@ -1207,30 +1113,23 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="PUT", params={ "localeId": locale_id, }, json={ - "id": id, - "siteId": site_id, "title": title, "slug": slug, - "parentId": parent_id, - "collectionId": collection_id, - "createdOn": created_on, - "lastUpdated": last_updated, - "archived": archived, - "draft": draft, - "canBranch": can_branch, - "isBranch": is_branch, - "isMembersOnly": is_members_only, - "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageOpenGraph, direction="write" + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" ), - "localeId": locale_id, - "publishedPath": published_path, + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -1309,10 +1208,11 @@ async def get_content( request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page. This includes text nodes, image nodes and component instances. - To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + Get content from a static page. This includes text nodes, image nodes, select nodes, text input nodes, submit button 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 provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + 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` @@ -1360,6 +1260,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -1488,9 +1389,13 @@ async def update_static_content( from webflow import ( AsyncWebflow, - ComponentInstanceNodePropertyOverridesWrite, + ComponentInstance, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - TextNodeWrite, + Select, + SelectNodeWriteChoicesItem, + SubmitButton, + TextInput, + TextNode, ) client = AsyncWebflow( @@ -1503,15 +1408,37 @@ async def main() -> None: page_id="63c720f9347c2139b248e552", locale_id="localeId", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInput( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButton( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -1532,6 +1459,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, diff --git a/src/webflow/resources/pages/resources/scripts/client.py b/src/webflow/resources/pages/resources/scripts/client.py index 56bd39a..cd1086f 100644 --- a/src/webflow/resources/pages/resources/scripts/client.py +++ b/src/webflow/resources/pages/resources/scripts/client.py @@ -31,13 +31,7 @@ def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Get all scripts applied to a page. Required scope | `custom_code:read` @@ -67,6 +61,7 @@ def get_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -144,15 +139,11 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - A site can have a maximum of 800 registered scripts. + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -204,6 +195,7 @@ def upsert_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -291,13 +283,11 @@ def upsert_custom_code( def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app has created for a page + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -326,6 +316,7 @@ def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -396,13 +387,7 @@ async def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Get all scripts applied to a page. Required scope | `custom_code:read` @@ -440,6 +425,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -517,15 +503,11 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - A site can have a maximum of 800 registered scripts. + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -585,6 +567,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -674,13 +657,11 @@ async def delete_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app has created for a page + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -717,6 +698,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/pages/types/__init__.py b/src/webflow/resources/pages/types/__init__.py index 08c0325..6e07bcf 100644 --- a/src/webflow/resources/pages/types/__init__.py +++ b/src/webflow/resources/pages/types/__init__.py @@ -1,6 +1,8 @@ # This file was auto-generated by Fern from our API Definition. from .page_dom_write_nodes_item import PageDomWriteNodesItem +from .page_metadata_write_open_graph import PageMetadataWriteOpenGraph +from .page_metadata_write_seo import PageMetadataWriteSeo from .update_static_content_response import UpdateStaticContentResponse -__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse"] +__all__ = ["PageDomWriteNodesItem", "PageMetadataWriteOpenGraph", "PageMetadataWriteSeo", "UpdateStaticContentResponse"] diff --git a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py index 05d1f3f..15615be 100644 --- a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py +++ b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py @@ -1,7 +1,11 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ....types.text_node_write import TextNodeWrite -from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.text_node import TextNode +from ....types.component_instance import ComponentInstance +from ....types.select import Select +from ....types.text_input import TextInput +from ....types.submit_button import SubmitButton +from ....types.search_button import SearchButton -PageDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] +PageDomWriteNodesItem = typing.Union[TextNode, ComponentInstance, Select, TextInput, SubmitButton, SearchButton] diff --git a/src/webflow/resources/pages/types/page_metadata_write_open_graph.py b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py new file mode 100644 index 0000000..7b6a099 --- /dev/null +++ b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataWriteOpenGraph(UniversalBaseModel): + """ + Open Graph fields for the Page + """ + + title: typing.Optional[str] = pydantic.Field(default=None) + """ + The title supplied to Open Graph annotations + """ + + title_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="titleCopied")] = ( + pydantic.Field(default=None) + ) + """ + Indicates the Open Graph title was copied from the SEO title + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + The description supplied to Open Graph annotations + """ + + description_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="descriptionCopied")] = ( + pydantic.Field(default=None) + ) + """ + Indicates the Open Graph description was copied from the SEO description + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/pages/types/page_metadata_write_seo.py b/src/webflow/resources/pages/types/page_metadata_write_seo.py new file mode 100644 index 0000000..1b339a0 --- /dev/null +++ b/src/webflow/resources/pages/types/page_metadata_write_seo.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataWriteSeo(UniversalBaseModel): + """ + SEO-related fields for the Page + """ + + title: typing.Optional[str] = pydantic.Field(default=None) + """ + The Page title shown in search engine results + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + The Page description shown in search engine results + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/__init__.py b/src/webflow/resources/products/__init__.py index 9fced2c..adf933b 100644 --- a/src/webflow/resources/products/__init__.py +++ b/src/webflow/resources/products/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ProductsCreateSkuResponse +from .types import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse -__all__ = ["ProductsCreateSkuResponse"] +__all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/client.py b/src/webflow/resources/products/client.py index c856fef..ab262b5 100644 --- a/src/webflow/resources/products/client.py +++ b/src/webflow/resources/products/client.py @@ -16,11 +16,13 @@ from ...errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from ...core.api_error import ApiError +from .types.product_sku_create_product import ProductSkuCreateProduct +from .types.product_sku_create_sku import ProductSkuCreateSku from ...types.publish_status import PublishStatus -from ...types.product import Product -from ...types.sku import Sku from ...types.product_and_sk_us import ProductAndSkUs from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.product import Product +from ...types.sku import Sku from .types.products_create_sku_response import ProductsCreateSkuResponse from ...core.client_wrapper import AsyncClientWrapper @@ -80,6 +82,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -175,22 +178,18 @@ def create( self, site_id: str, *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[Product] = OMIT, - sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Create a new product and SKU. - - When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. - To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. @@ -201,11 +200,11 @@ def create( site_id : str Unique identifier for a Site - publish_status : typing.Optional[PublishStatus] + product : ProductSkuCreateProduct - product : typing.Optional[Product] + sku : ProductSkuCreateSku - sku : typing.Optional[Sku] + publish_status : typing.Optional[PublishStatus] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -217,24 +216,102 @@ def create( Examples -------- - from webflow import Webflow + from webflow import ( + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + Webflow, + ) + from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.create( site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), }, headers={ "content-type": "application/json", @@ -365,6 +442,7 @@ def get( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -505,6 +583,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -642,7 +721,9 @@ def create_sku( Examples -------- - from webflow import Sku, Webflow + import datetime + + from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -650,11 +731,35 @@ def create_sku( client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, @@ -794,7 +899,9 @@ def update_sku( Examples -------- - from webflow import Sku, Webflow + import datetime + + from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -803,11 +910,33 @@ def update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -964,6 +1093,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -1059,22 +1189,18 @@ async def create( self, site_id: str, *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[Product] = OMIT, - sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Create a new product and SKU. + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. - When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - - To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. @@ -1085,11 +1211,11 @@ async def create( site_id : str Unique identifier for a Site - publish_status : typing.Optional[PublishStatus] + product : ProductSkuCreateProduct - product : typing.Optional[Product] + sku : ProductSkuCreateSku - sku : typing.Optional[Sku] + publish_status : typing.Optional[PublishStatus] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1103,7 +1229,18 @@ async def create( -------- import asyncio - from webflow import AsyncWebflow + from webflow import ( + AsyncWebflow, + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + ) + from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1113,6 +1250,70 @@ async def create( async def main() -> None: await client.products.create( site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) @@ -1120,13 +1321,16 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), }, headers={ "content-type": "application/json", @@ -1265,6 +1469,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1413,6 +1618,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -1551,8 +1757,9 @@ async def create_sku( Examples -------- import asyncio + import datetime - from webflow import AsyncWebflow, Sku + from webflow import AsyncWebflow, Sku, SkuFieldData, SkuFieldDataPrice client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1563,7 +1770,30 @@ async def main() -> None: await client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) @@ -1571,6 +1801,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, @@ -1711,8 +1942,9 @@ async def update_sku( Examples -------- import asyncio + import datetime - from webflow import AsyncWebflow, Sku + from webflow import AsyncWebflow, Sku, SkuFieldData, SkuFieldDataPrice client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1724,7 +1956,28 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) @@ -1732,6 +1985,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, diff --git a/src/webflow/resources/products/types/__init__.py b/src/webflow/resources/products/types/__init__.py index b078afe..5b6d9b4 100644 --- a/src/webflow/resources/products/types/__init__.py +++ b/src/webflow/resources/products/types/__init__.py @@ -1,5 +1,7 @@ # This file was auto-generated by Fern from our API Definition. +from .product_sku_create_product import ProductSkuCreateProduct +from .product_sku_create_sku import ProductSkuCreateSku from .products_create_sku_response import ProductsCreateSkuResponse -__all__ = ["ProductsCreateSkuResponse"] +__all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/types/product_sku_create_product.py b/src/webflow/resources/products/types/product_sku_create_product.py new file mode 100644 index 0000000..750e5f4 --- /dev/null +++ b/src/webflow/resources/products/types/product_sku_create_product.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....types.product_field_data import ProductFieldData +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProductSkuCreateProduct(UniversalBaseModel): + field_data: typing_extensions.Annotated[typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/types/product_sku_create_sku.py b/src/webflow/resources/products/types/product_sku_create_sku.py new file mode 100644 index 0000000..2762a9a --- /dev/null +++ b/src/webflow/resources/products/types/product_sku_create_sku.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....types.sku_field_data import SkuFieldData +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProductSkuCreateSku(UniversalBaseModel): + field_data: typing_extensions.Annotated[typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/types/products_create_sku_response.py b/src/webflow/resources/products/types/products_create_sku_response.py index e694930..cd68c3d 100644 --- a/src/webflow/resources/products/types/products_create_sku_response.py +++ b/src/webflow/resources/products/types/products_create_sku_response.py @@ -8,7 +8,7 @@ class ProductsCreateSkuResponse(UniversalBaseModel): - skus: typing.Optional[typing.List[Sku]] = None + skus: typing.List[Sku] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/scripts/client.py b/src/webflow/resources/scripts/client.py index e9112fb..80026d9 100644 --- a/src/webflow/resources/scripts/client.py +++ b/src/webflow/resources/scripts/client.py @@ -28,14 +28,11 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> RegisteredScriptList: """ - List of scripts registered to a Site. + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -65,6 +62,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -144,14 +142,11 @@ def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. + Register a hosted script to a site. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -200,6 +195,7 @@ def register_hosted( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "hostedLocation": hosted_location, @@ -290,13 +286,11 @@ def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + Register an inline script to a site. Inline scripts are limited to 2000 characters. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -344,6 +338,7 @@ def register_inline( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sourceCode": source_code, @@ -431,14 +426,11 @@ async def list( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> RegisteredScriptList: """ - List of scripts registered to a Site. + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -476,6 +468,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -555,14 +548,11 @@ async def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. + Register a hosted script to a site. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -619,6 +609,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "hostedLocation": hosted_location, @@ -709,13 +700,11 @@ async def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + Register an inline script to a site. Inline scripts are limited to 2000 characters. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -771,6 +760,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sourceCode": source_code, diff --git a/src/webflow/resources/sites/__init__.py b/src/webflow/resources/sites/__init__.py index 3ec19db..8a61137 100644 --- a/src/webflow/resources/sites/__init__.py +++ b/src/webflow/resources/sites/__init__.py @@ -1,6 +1,37 @@ # This file was auto-generated by Fern from our API Definition. from .types import SitesPublishResponse -from .resources import activity_logs, plans, redirects, scripts +from .resources import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, + WellKnownFileContentType, + activity_logs, + comments, + plans, + redirects, + robots_txt, + scripts, + well_known, +) -__all__ = ["SitesPublishResponse", "activity_logs", "plans", "redirects", "scripts"] +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", + "SitesPublishResponse", + "WellKnownFileContentType", + "activity_logs", + "comments", + "plans", + "redirects", + "robots_txt", + "scripts", + "well_known", +] diff --git a/src/webflow/resources/sites/client.py b/src/webflow/resources/sites/client.py index c2a4468..26ef50b 100644 --- a/src/webflow/resources/sites/client.py +++ b/src/webflow/resources/sites/client.py @@ -4,7 +4,10 @@ from ...core.client_wrapper import SyncClientWrapper from .resources.redirects.client import RedirectsClient from .resources.plans.client import PlansClient +from .resources.robots_txt.client import RobotsTxtClient +from .resources.well_known.client import WellKnownClient from .resources.activity_logs.client import ActivityLogsClient +from .resources.comments.client import CommentsClient from .resources.scripts.client import ScriptsClient from ...core.request_options import RequestOptions from ...types.site import Site @@ -25,7 +28,10 @@ from ...core.client_wrapper import AsyncClientWrapper from .resources.redirects.client import AsyncRedirectsClient from .resources.plans.client import AsyncPlansClient +from .resources.robots_txt.client import AsyncRobotsTxtClient +from .resources.well_known.client import AsyncWellKnownClient from .resources.activity_logs.client import AsyncActivityLogsClient +from .resources.comments.client import AsyncCommentsClient from .resources.scripts.client import AsyncScriptsClient # this is used as the default value for optional parameters @@ -37,7 +43,10 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper self.redirects = RedirectsClient(client_wrapper=self._client_wrapper) self.plans = PlansClient(client_wrapper=self._client_wrapper) + self.robots_txt = RobotsTxtClient(client_wrapper=self._client_wrapper) + self.well_known = WellKnownClient(client_wrapper=self._client_wrapper) self.activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) + self.comments = CommentsClient(client_wrapper=self._client_wrapper) self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) def create( @@ -50,7 +59,9 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Create a site. This endpoint requires an Enterprise workspace. + Create a site. + + This endpoint requires an Enterprise workspace. Required scope | `workspace:write` @@ -90,6 +101,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "name": name, @@ -203,6 +215,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si """ _response = self._client_wrapper.httpx_client.request( "sites", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -282,6 +295,7 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -351,7 +365,9 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a site. This endpoint requires an Enterprise workspace. + Delete a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -380,6 +396,7 @@ def delete(self, site_id: str, *, request_options: typing.Optional[RequestOption """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -460,7 +477,9 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Update a site. This endpoint requires an Enterprise workspace. + Update a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -496,6 +515,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "name": name, @@ -613,6 +633,7 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -691,7 +712,9 @@ def publish( """ Publishes a site to one or more more domains. - This endpoint has a limit of one successful publish queue per minute. + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write` @@ -723,10 +746,13 @@ def publish( ) client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "customDomains": custom_domains, @@ -808,7 +834,10 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper self.redirects = AsyncRedirectsClient(client_wrapper=self._client_wrapper) self.plans = AsyncPlansClient(client_wrapper=self._client_wrapper) + self.robots_txt = AsyncRobotsTxtClient(client_wrapper=self._client_wrapper) + self.well_known = AsyncWellKnownClient(client_wrapper=self._client_wrapper) self.activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) + self.comments = AsyncCommentsClient(client_wrapper=self._client_wrapper) self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) async def create( @@ -821,7 +850,9 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Create a site. This endpoint requires an Enterprise workspace. + Create a site. + + This endpoint requires an Enterprise workspace. Required scope | `workspace:write` @@ -869,6 +900,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "name": name, @@ -990,6 +1022,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "sites", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1077,6 +1110,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1146,7 +1180,9 @@ async def main() -> None: async def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a site. This endpoint requires an Enterprise workspace. + Delete a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -1183,6 +1219,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -1263,7 +1300,9 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Update a site. This endpoint requires an Enterprise workspace. + Update a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -1307,6 +1346,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "name": name, @@ -1434,6 +1474,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1512,7 +1553,9 @@ async def publish( """ Publishes a site to one or more more domains. - This endpoint has a limit of one successful publish queue per minute. + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write` @@ -1549,6 +1592,8 @@ async def publish( async def main() -> None: await client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) @@ -1556,6 +1601,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "customDomains": custom_domains, diff --git a/src/webflow/resources/sites/resources/__init__.py b/src/webflow/resources/sites/resources/__init__.py index 1197a83..2de1e0b 100644 --- a/src/webflow/resources/sites/resources/__init__.py +++ b/src/webflow/resources/sites/resources/__init__.py @@ -1,5 +1,29 @@ # This file was auto-generated by Fern from our API Definition. -from . import activity_logs, plans, redirects, scripts +from . import activity_logs, comments, plans, redirects, robots_txt, scripts, well_known +from .comments import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, +) +from .well_known import WellKnownFileContentType -__all__ = ["activity_logs", "plans", "redirects", "scripts"] +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", + "WellKnownFileContentType", + "activity_logs", + "comments", + "plans", + "redirects", + "robots_txt", + "scripts", + "well_known", +] diff --git a/src/webflow/resources/sites/resources/activity_logs/client.py b/src/webflow/resources/sites/resources/activity_logs/client.py index cf4e1b3..1a1eb8e 100644 --- a/src/webflow/resources/sites/resources/activity_logs/client.py +++ b/src/webflow/resources/sites/resources/activity_logs/client.py @@ -29,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 ---------- @@ -63,6 +67,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -138,7 +143,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 ---------- @@ -180,6 +189,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, diff --git a/src/webflow/resources/sites/resources/comments/__init__.py b/src/webflow/resources/sites/resources/comments/__init__.py new file mode 100644 index 0000000..1bf96a0 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/__init__.py @@ -0,0 +1,19 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, +) + +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", +] diff --git a/src/webflow/resources/sites/resources/comments/client.py b/src/webflow/resources/sites/resources/comments/client.py new file mode 100644 index 0000000..564e8da --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/client.py @@ -0,0 +1,901 @@ +# This file was auto-generated by Fern from our API Definition. + +from .....core.client_wrapper import SyncClientWrapper +import typing +from .types.comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .types.comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder +from .....core.request_options import RequestOptions +from .....types.comment_thread_list import CommentThreadList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .types.comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy +from .types.comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder +from .....types.comment_thread import CommentThread +from .types.comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy +from .types.comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder +from .....types.comment_reply_list import CommentReplyList +from .....core.client_wrapper import AsyncClientWrapper + + +class CommentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThreadList: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThreadList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThread: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThread + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentReplyList: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentReplyList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncCommentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThreadList: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThreadList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThread: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThread + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentReplyList: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentReplyList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/comments/types/__init__.py b/src/webflow/resources/sites/resources/comments/types/__init__.py new file mode 100644 index 0000000..380d194 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/__init__.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +from .comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy +from .comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder +from .comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy +from .comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder +from .comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder + +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", +] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py new file mode 100644 index 0000000..14daabb --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsGetCommentThreadRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py new file mode 100644 index 0000000..3da3ffc --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsGetCommentThreadRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py new file mode 100644 index 0000000..67fcb98 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentRepliesRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py new file mode 100644 index 0000000..03c42c3 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentRepliesRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py new file mode 100644 index 0000000..1d541ce --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentThreadsRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py new file mode 100644 index 0000000..d2c2606 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentThreadsRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/sites/resources/plans/client.py b/src/webflow/resources/sites/resources/plans/client.py index 291231a..a3309bb 100644 --- a/src/webflow/resources/sites/resources/plans/client.py +++ b/src/webflow/resources/sites/resources/plans/client.py @@ -25,6 +25,8 @@ def get_site_plan(self, site_id: str, *, request_options: typing.Optional[Reques """ Get site plan details for the specified Site. + This endpoint requires an Enterprise workspace. + Required scope | `sites:read` Parameters @@ -53,6 +55,7 @@ def get_site_plan(self, site_id: str, *, request_options: typing.Optional[Reques """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -129,6 +132,8 @@ async def get_site_plan(self, site_id: str, *, request_options: typing.Optional[ """ Get site plan details for the specified Site. + This endpoint requires an Enterprise workspace. + Required scope | `sites:read` Parameters @@ -165,6 +170,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/sites/resources/redirects/client.py b/src/webflow/resources/sites/resources/redirects/client.py index 4bc0e7b..1ac17b4 100644 --- a/src/webflow/resources/sites/resources/redirects/client.py +++ b/src/webflow/resources/sites/resources/redirects/client.py @@ -27,10 +27,11 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise workspace. Required scope: `sites:read` @@ -60,6 +61,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -137,10 +139,12 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -181,6 +185,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -258,8 +263,12 @@ def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Redirects: """ - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -292,6 +301,7 @@ def delete( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -370,7 +380,10 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Update a URL redirection rule from a site. + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -415,6 +428,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "id": id, @@ -495,10 +509,11 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise workspace. Required scope: `sites:read` @@ -536,6 +551,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -613,10 +629,12 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -665,6 +683,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -742,8 +761,12 @@ async def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Redirects: """ - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -784,6 +807,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -862,7 +886,10 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Update a URL redirection rule from a site. + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -915,6 +942,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "id": id, diff --git a/src/webflow/resources/sites/resources/robots_txt/__init__.py b/src/webflow/resources/sites/resources/robots_txt/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/src/webflow/resources/sites/resources/robots_txt/__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/robots_txt/client.py b/src/webflow/resources/sites/resources/robots_txt/client.py new file mode 100644 index 0000000..a0bc59b --- /dev/null +++ b/src/webflow/resources/sites/resources/robots_txt/client.py @@ -0,0 +1,1050 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .....core.client_wrapper import SyncClientWrapper +from .....core.request_options import RequestOptions +from .....types.robots import Robots +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....types.robots_rules_item import RobotsRulesItem +from .....core.serialization import convert_and_respect_annotation_metadata +from .....core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RobotsTxtClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRobotsTxtClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/scripts/client.py b/src/webflow/resources/sites/resources/scripts/client.py index 1954842..9ed3691 100644 --- a/src/webflow/resources/sites/resources/scripts/client.py +++ b/src/webflow/resources/sites/resources/scripts/client.py @@ -31,9 +31,11 @@ def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site. + Get all scripts applied to a site by the App. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -63,6 +65,7 @@ def get_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -140,13 +143,11 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site. + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -198,6 +199,7 @@ def upsert_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -275,9 +277,11 @@ def upsert_custom_code( def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -306,6 +310,7 @@ def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -376,9 +381,13 @@ def list_custom_code_blocks( request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages. + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -414,6 +423,7 @@ def list_custom_code_blocks( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -494,9 +504,11 @@ async def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site. + Get all scripts applied to a site by the App. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -534,6 +546,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -611,13 +624,11 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site. + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -677,6 +688,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -756,9 +768,11 @@ async def delete_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -795,6 +809,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -865,9 +880,13 @@ 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. + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -911,6 +930,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, diff --git a/src/webflow/resources/sites/resources/well_known/__init__.py b/src/webflow/resources/sites/resources/well_known/__init__.py new file mode 100644 index 0000000..323b6bd --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import WellKnownFileContentType + +__all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/resources/well_known/client.py b/src/webflow/resources/sites/resources/well_known/client.py new file mode 100644 index 0000000..3d846b2 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/client.py @@ -0,0 +1,532 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .....core.client_wrapper import SyncClientWrapper +from .types.well_known_file_content_type import WellKnownFileContentType +from .....core.request_options import RequestOptions +from .....core.jsonable_encoder import jsonable_encoder +from .....errors.bad_request_error import BadRequestError +from .....core.pydantic_utilities import parse_obj_as +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class WellKnownClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="fileName", + file_data="fileData", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncWellKnownClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="fileName", + file_data="fileData", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/well_known/types/__init__.py b/src/webflow/resources/sites/resources/well_known/types/__init__.py new file mode 100644 index 0000000..4fc9c09 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/types/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .well_known_file_content_type import WellKnownFileContentType + +__all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py b/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py new file mode 100644 index 0000000..be135b4 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WellKnownFileContentType = typing.Union[typing.Literal["application/json", "text/plain"], typing.Any] diff --git a/src/webflow/resources/token/client.py b/src/webflow/resources/token/client.py index 628ce3a..d8cfd16 100644 --- a/src/webflow/resources/token/client.py +++ b/src/webflow/resources/token/client.py @@ -45,6 +45,7 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No """ _response = self._client_wrapper.httpx_client.request( "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -109,6 +110,7 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) """ _response = self._client_wrapper.httpx_client.request( "token/introspect", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -176,6 +178,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -248,6 +251,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "token/introspect", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/users/__init__.py b/src/webflow/resources/users/__init__.py index 88e72a2..b191e61 100644 --- a/src/webflow/resources/users/__init__.py +++ b/src/webflow/resources/users/__init__.py @@ -1,5 +1,27 @@ # This file was auto-generated by Fern from our API Definition. -from .types import UsersListRequestSort, UsersUpdateRequestData +from .types import ( + UserAccountAddedPayload, + UserAccountAddedPayloadPayload, + UserAccountAddedPayloadPayloadData, + UserAccountDeletedPayload, + UserAccountDeletedPayloadPayload, + UserAccountDeletedPayloadPayloadData, + UserAccountUpdatedPayload, + UserAccountUpdatedPayloadPayload, + UserAccountUpdatedPayloadPayloadData, + UsersListRequestSort, +) -__all__ = ["UsersListRequestSort", "UsersUpdateRequestData"] +__all__ = [ + "UserAccountAddedPayload", + "UserAccountAddedPayloadPayload", + "UserAccountAddedPayloadPayloadData", + "UserAccountDeletedPayload", + "UserAccountDeletedPayloadPayload", + "UserAccountDeletedPayloadPayloadData", + "UserAccountUpdatedPayload", + "UserAccountUpdatedPayloadPayload", + "UserAccountUpdatedPayloadPayloadData", + "UsersListRequestSort", +] diff --git a/src/webflow/resources/users/client.py b/src/webflow/resources/users/client.py index d690c0f..79c9fc1 100644 --- a/src/webflow/resources/users/client.py +++ b/src/webflow/resources/users/client.py @@ -17,7 +17,10 @@ from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...types.user import User -from .types.users_update_request_data import UsersUpdateRequestData +import datetime as dt +from ...types.user_status import UserStatus +from ...types.user_access_groups_item import UserAccessGroupsItem +from ...types.user_data import UserData from ...core.serialization import convert_and_respect_annotation_metadata from ...errors.conflict_error import ConflictError from ...core.client_wrapper import AsyncClientWrapper @@ -83,6 +86,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -201,6 +205,7 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -313,6 +318,7 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -389,8 +395,15 @@ def update( site_id: str, user_id: str, *, - data: typing.Optional[UsersUpdateRequestData] = OMIT, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, + id: typing.Optional[str] = OMIT, + is_email_verified: typing.Optional[bool] = OMIT, + last_updated: typing.Optional[dt.datetime] = OMIT, + invited_on: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + last_login: typing.Optional[dt.datetime] = OMIT, + status: typing.Optional[UserStatus] = OMIT, + access_groups: typing.Optional[typing.Sequence[UserAccessGroupsItem]] = OMIT, + data: typing.Optional[UserData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> User: """ @@ -409,11 +422,30 @@ def update( user_id : str Unique identifier for a User - data : typing.Optional[UsersUpdateRequestData] + id : typing.Optional[str] + Unique identifier for the User - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + is_email_verified : typing.Optional[bool] + Shows whether the user has verified their email address + + last_updated : typing.Optional[dt.datetime] + The timestamp the user was updated + + invited_on : typing.Optional[dt.datetime] + The timestamp the user was invited + created_on : typing.Optional[dt.datetime] + The timestamp the user was created + + last_login : typing.Optional[dt.datetime] + The timestamp the user was logged in + + status : typing.Optional[UserStatus] + + access_groups : typing.Optional[typing.Sequence[UserAccessGroupsItem]] + Access groups the user belongs to + + data : typing.Optional[UserData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -425,8 +457,9 @@ def update( Examples -------- - from webflow import Webflow - from webflow.resources.users import UsersUpdateRequestData + import datetime + + from webflow import UserAccessGroupsItem, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -434,25 +467,45 @@ def update( client.users.update( site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, + id="6287ec36a841b25637c663df", + is_email_verified=True, + last_updated=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + invited_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", ), - access_groups=["webflowers", "platinum", "free-tier"], + last_login=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + status="verified", + access_groups=[ + UserAccessGroupsItem( + slug="webflowers", + type="admin", + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ - "data": convert_and_respect_annotation_metadata( - object_=data, annotation=UsersUpdateRequestData, direction="write" + "id": id, + "isEmailVerified": is_email_verified, + "lastUpdated": last_updated, + "invitedOn": invited_on, + "createdOn": created_on, + "lastLogin": last_login, + "status": status, + "accessGroups": convert_and_respect_annotation_metadata( + object_=access_groups, annotation=typing.Sequence[UserAccessGroupsItem], direction="write" ), - "accessGroups": access_groups, - }, - headers={ - "content-type": "application/json", + "data": convert_and_respect_annotation_metadata(object_=data, annotation=UserData, direction="write"), }, request_options=request_options, omit=OMIT, @@ -557,7 +610,6 @@ def 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. - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -576,11 +628,12 @@ def invite( client.users.invite( site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", - access_groups=["webflowers"], + access_groups=["accessGroups"], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/invite", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "email": email, @@ -742,6 +795,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -868,6 +922,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -990,6 +1045,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -1066,8 +1122,15 @@ async def update( site_id: str, user_id: str, *, - data: typing.Optional[UsersUpdateRequestData] = OMIT, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, + id: typing.Optional[str] = OMIT, + is_email_verified: typing.Optional[bool] = OMIT, + last_updated: typing.Optional[dt.datetime] = OMIT, + invited_on: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + last_login: typing.Optional[dt.datetime] = OMIT, + status: typing.Optional[UserStatus] = OMIT, + access_groups: typing.Optional[typing.Sequence[UserAccessGroupsItem]] = OMIT, + data: typing.Optional[UserData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> User: """ @@ -1086,11 +1149,30 @@ async def update( user_id : str Unique identifier for a User - data : typing.Optional[UsersUpdateRequestData] + id : typing.Optional[str] + Unique identifier for the User - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + is_email_verified : typing.Optional[bool] + Shows whether the user has verified their email address + + last_updated : typing.Optional[dt.datetime] + The timestamp the user was updated + + invited_on : typing.Optional[dt.datetime] + The timestamp the user was invited + created_on : typing.Optional[dt.datetime] + The timestamp the user was created + + last_login : typing.Optional[dt.datetime] + The timestamp the user was logged in + + status : typing.Optional[UserStatus] + + access_groups : typing.Optional[typing.Sequence[UserAccessGroupsItem]] + Access groups the user belongs to + + data : typing.Optional[UserData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1103,9 +1185,9 @@ async def update( Examples -------- import asyncio + import datetime - from webflow import AsyncWebflow - from webflow.resources.users import UsersUpdateRequestData + from webflow import AsyncWebflow, UserAccessGroupsItem client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1116,12 +1198,27 @@ 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, + id="6287ec36a841b25637c663df", + is_email_verified=True, + last_updated=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", ), - access_groups=["webflowers", "platinum", "free-tier"], + invited_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + last_login=datetime.datetime.fromisoformat( + "2022-05-20 13:46:12+00:00", + ), + status="verified", + access_groups=[ + UserAccessGroupsItem( + slug="webflowers", + type="admin", + ) + ], ) @@ -1129,15 +1226,20 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ - "data": convert_and_respect_annotation_metadata( - object_=data, annotation=UsersUpdateRequestData, direction="write" + "id": id, + "isEmailVerified": is_email_verified, + "lastUpdated": last_updated, + "invitedOn": invited_on, + "createdOn": created_on, + "lastLogin": last_login, + "status": status, + "accessGroups": convert_and_respect_annotation_metadata( + object_=access_groups, annotation=typing.Sequence[UserAccessGroupsItem], direction="write" ), - "accessGroups": access_groups, - }, - headers={ - "content-type": "application/json", + "data": convert_and_respect_annotation_metadata(object_=data, annotation=UserData, direction="write"), }, request_options=request_options, omit=OMIT, @@ -1242,7 +1344,6 @@ async def 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. - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1266,7 +1367,7 @@ async def main() -> None: await client.users.invite( site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", - access_groups=["webflowers"], + access_groups=["accessGroups"], ) @@ -1274,6 +1375,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/invite", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "email": email, diff --git a/src/webflow/resources/users/types/__init__.py b/src/webflow/resources/users/types/__init__.py index cadf367..ca99b25 100644 --- a/src/webflow/resources/users/types/__init__.py +++ b/src/webflow/resources/users/types/__init__.py @@ -1,6 +1,25 @@ # This file was auto-generated by Fern from our API Definition. +from .user_account_added_payload import UserAccountAddedPayload +from .user_account_added_payload_payload import UserAccountAddedPayloadPayload +from .user_account_added_payload_payload_data import UserAccountAddedPayloadPayloadData +from .user_account_deleted_payload import UserAccountDeletedPayload +from .user_account_deleted_payload_payload import UserAccountDeletedPayloadPayload +from .user_account_deleted_payload_payload_data import UserAccountDeletedPayloadPayloadData +from .user_account_updated_payload import UserAccountUpdatedPayload +from .user_account_updated_payload_payload import UserAccountUpdatedPayloadPayload +from .user_account_updated_payload_payload_data import UserAccountUpdatedPayloadPayloadData from .users_list_request_sort import UsersListRequestSort -from .users_update_request_data import UsersUpdateRequestData -__all__ = ["UsersListRequestSort", "UsersUpdateRequestData"] +__all__ = [ + "UserAccountAddedPayload", + "UserAccountAddedPayloadPayload", + "UserAccountAddedPayloadPayloadData", + "UserAccountDeletedPayload", + "UserAccountDeletedPayloadPayload", + "UserAccountDeletedPayloadPayloadData", + "UserAccountUpdatedPayload", + "UserAccountUpdatedPayloadPayload", + "UserAccountUpdatedPayloadPayloadData", + "UsersListRequestSort", +] diff --git a/src/webflow/resources/users/types/user_account_added_payload.py b/src/webflow/resources/users/types/user_account_added_payload.py new file mode 100644 index 0000000..40e4e20 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_added_payload.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from .user_account_added_payload_payload import UserAccountAddedPayloadPayload +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccountAddedPayload(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["user_account_added"]], FieldMetadata(alias="triggerType") + ] = None + payload: typing.Optional[UserAccountAddedPayloadPayload] = 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/users/types/user_account_added_payload_payload.py b/src/webflow/resources/users/types/user_account_added_payload_payload.py new file mode 100644 index 0000000..318b7d3 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_added_payload_payload.py @@ -0,0 +1,76 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +from .user_account_added_payload_payload_data import UserAccountAddedPayloadPayloadData +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +import datetime as dt +from ....types.user_status import UserStatus +from ....types.user_access_groups_item import UserAccessGroupsItem +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UserAccountAddedPayloadPayload(UniversalBaseModel): + data: typing.Optional[UserAccountAddedPayloadPayloadData] = pydantic.Field(default=None) + """ + The data about the user account that was added + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the User + """ + + is_email_verified: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEmailVerified")] = ( + pydantic.Field(default=None) + ) + """ + Shows whether the user has verified their email address + """ + + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was updated + """ + + invited_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="invitedOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was invited + """ + + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was created + """ + + last_login: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastLogin")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was logged in + """ + + status: typing.Optional[UserStatus] = None + access_groups: typing_extensions.Annotated[ + typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") + ] = pydantic.Field(default=None) + """ + Access groups the user belongs to + """ + + if IS_PYDANTIC_V2: + model_config: 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/users/types/users_update_request_data.py b/src/webflow/resources/users/types/user_account_added_payload_payload_data.py similarity index 59% rename from src/webflow/resources/users/types/users_update_request_data.py rename to src/webflow/resources/users/types/user_account_added_payload_payload_data.py index 919406c..c5a668a 100644 --- a/src/webflow/resources/users/types/users_update_request_data.py +++ b/src/webflow/resources/users/types/user_account_added_payload_payload_data.py @@ -1,32 +1,26 @@ # This file was auto-generated by Fern from our API Definition. from ....core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic import typing_extensions +import typing from ....core.serialization import FieldMetadata from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class UsersUpdateRequestData(UniversalBaseModel): - name: typing.Optional[str] = pydantic.Field(default=None) +class UserAccountAddedPayloadPayloadData(UniversalBaseModel): """ - The name of the user - """ - - accept_privacy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="accept-privacy")] = ( - pydantic.Field(default=None) - ) - """ - Boolean indicating if the user has accepted the privacy policy + The data about the user account that was added """ + accept_privacy_policy: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-privacy-policy") + ] = 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 - """ + ] = None + email: typing.Optional[str] = None + name: typing.Optional[str] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/users/types/user_account_deleted_payload.py b/src/webflow/resources/users/types/user_account_deleted_payload.py new file mode 100644 index 0000000..2d2aef8 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_deleted_payload.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from .user_account_deleted_payload_payload import UserAccountDeletedPayloadPayload +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccountDeletedPayload(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["user_account_deleted"]], FieldMetadata(alias="triggerType") + ] = None + payload: typing.Optional[UserAccountDeletedPayloadPayload] = 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/users/types/user_account_deleted_payload_payload.py b/src/webflow/resources/users/types/user_account_deleted_payload_payload.py new file mode 100644 index 0000000..a839489 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_deleted_payload_payload.py @@ -0,0 +1,76 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +from .user_account_deleted_payload_payload_data import UserAccountDeletedPayloadPayloadData +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +import datetime as dt +from ....types.user_status import UserStatus +from ....types.user_access_groups_item import UserAccessGroupsItem +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UserAccountDeletedPayloadPayload(UniversalBaseModel): + data: typing.Optional[UserAccountDeletedPayloadPayloadData] = pydantic.Field(default=None) + """ + The data about the user account that was added + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the User + """ + + is_email_verified: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEmailVerified")] = ( + pydantic.Field(default=None) + ) + """ + Shows whether the user has verified their email address + """ + + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was updated + """ + + invited_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="invitedOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was invited + """ + + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was created + """ + + last_login: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastLogin")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was logged in + """ + + status: typing.Optional[UserStatus] = None + access_groups: typing_extensions.Annotated[ + typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") + ] = pydantic.Field(default=None) + """ + Access groups the user belongs to + """ + + if IS_PYDANTIC_V2: + model_config: 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/users/types/user_account_deleted_payload_payload_data.py b/src/webflow/resources/users/types/user_account_deleted_payload_payload_data.py new file mode 100644 index 0000000..2d65fd3 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_deleted_payload_payload_data.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccountDeletedPayloadPayloadData(UniversalBaseModel): + """ + The data about the user account that was added + """ + + accept_privacy_policy: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-privacy-policy") + ] = None + accept_communications: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-communications") + ] = None + email: typing.Optional[str] = None + name: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/users/types/user_account_updated_payload.py b/src/webflow/resources/users/types/user_account_updated_payload.py new file mode 100644 index 0000000..6c733c1 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_updated_payload.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from .user_account_updated_payload_payload import UserAccountUpdatedPayloadPayload +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccountUpdatedPayload(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["user_account_updated"]], FieldMetadata(alias="triggerType") + ] = None + payload: typing.Optional[UserAccountUpdatedPayloadPayload] = 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/users/types/user_account_updated_payload_payload.py b/src/webflow/resources/users/types/user_account_updated_payload_payload.py new file mode 100644 index 0000000..fc3a2d2 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_updated_payload_payload.py @@ -0,0 +1,76 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +from .user_account_updated_payload_payload_data import UserAccountUpdatedPayloadPayloadData +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +import datetime as dt +from ....types.user_status import UserStatus +from ....types.user_access_groups_item import UserAccessGroupsItem +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UserAccountUpdatedPayloadPayload(UniversalBaseModel): + data: typing.Optional[UserAccountUpdatedPayloadPayloadData] = pydantic.Field(default=None) + """ + The data about the user account that was added + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the User + """ + + is_email_verified: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEmailVerified")] = ( + pydantic.Field(default=None) + ) + """ + Shows whether the user has verified their email address + """ + + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was updated + """ + + invited_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="invitedOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was invited + """ + + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was created + """ + + last_login: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastLogin")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the user was logged in + """ + + status: typing.Optional[UserStatus] = None + access_groups: typing_extensions.Annotated[ + typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") + ] = pydantic.Field(default=None) + """ + Access groups the user belongs to + """ + + if IS_PYDANTIC_V2: + model_config: 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/users/types/user_account_updated_payload_payload_data.py b/src/webflow/resources/users/types/user_account_updated_payload_payload_data.py new file mode 100644 index 0000000..1a572a3 --- /dev/null +++ b/src/webflow/resources/users/types/user_account_updated_payload_payload_data.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccountUpdatedPayloadPayloadData(UniversalBaseModel): + """ + The data about the user account that was added + """ + + accept_privacy_policy: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-privacy-policy") + ] = None + accept_communications: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-communications") + ] = None + email: typing.Optional[str] = None + name: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/webhooks/client.py b/src/webflow/resources/webhooks/client.py index ded9a2f..c6821a9 100644 --- a/src/webflow/resources/webhooks/client.py +++ b/src/webflow/resources/webhooks/client.py @@ -61,6 +61,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -212,6 +213,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -324,6 +326,7 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption """ _response = self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -422,6 +425,7 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt """ _response = self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -528,6 +532,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -686,6 +691,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -806,6 +812,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -912,6 +919,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/workspaces/__init__.py b/src/webflow/resources/workspaces/__init__.py new file mode 100644 index 0000000..d6cc054 --- /dev/null +++ b/src/webflow/resources/workspaces/__init__.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from .resources import ( + AuditLogsGetWorkspaceAuditLogsRequestEventType, + AuditLogsGetWorkspaceAuditLogsRequestSortOrder, + audit_logs, +) + +__all__ = [ + "AuditLogsGetWorkspaceAuditLogsRequestEventType", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder", + "audit_logs", +] diff --git a/src/webflow/resources/workspaces/client.py b/src/webflow/resources/workspaces/client.py new file mode 100644 index 0000000..de70ca5 --- /dev/null +++ b/src/webflow/resources/workspaces/client.py @@ -0,0 +1,18 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.client_wrapper import SyncClientWrapper +from .resources.audit_logs.client import AuditLogsClient +from ...core.client_wrapper import AsyncClientWrapper +from .resources.audit_logs.client import AsyncAuditLogsClient + + +class WorkspacesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + self.audit_logs = AuditLogsClient(client_wrapper=self._client_wrapper) + + +class AsyncWorkspacesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + self.audit_logs = AsyncAuditLogsClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/resources/workspaces/resources/__init__.py b/src/webflow/resources/workspaces/resources/__init__.py new file mode 100644 index 0000000..0e96a0e --- /dev/null +++ b/src/webflow/resources/workspaces/resources/__init__.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +from . import audit_logs +from .audit_logs import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = [ + "AuditLogsGetWorkspaceAuditLogsRequestEventType", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder", + "audit_logs", +] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py new file mode 100644 index 0000000..dab3df1 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/client.py b/src/webflow/resources/workspaces/resources/audit_logs/client.py new file mode 100644 index 0000000..ea6ebd8 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/client.py @@ -0,0 +1,332 @@ +# This file was auto-generated by Fern from our API Definition. + +from .....core.client_wrapper import SyncClientWrapper +import typing +from .types.audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder +from .types.audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +import datetime as dt +from .....core.request_options import RequestOptions +from .....types.workspace_audit_log_response import WorkspaceAuditLogResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.datetime_utils import serialize_datetime +from .....core.pydantic_utilities import parse_obj_as +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.forbidden_error import ForbiddenError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper + + +class AuditLogsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_workspace_audit_logs( + self, + workspace_id_or_slug: str, + *, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkspaceAuditLogResponse: + """ + Get audit logs for a workspace. + + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` + + Parameters + ---------- + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[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 + + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc + + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by + + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkspaceAuditLogResponse + A list of workspace audit logs + + Examples + -------- + import datetime + + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + from_=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + WorkspaceAuditLogResponse, + parse_obj_as( + type_=WorkspaceAuditLogResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncAuditLogsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_workspace_audit_logs( + self, + workspace_id_or_slug: str, + *, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkspaceAuditLogResponse: + """ + Get audit logs for a workspace. + + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` + + Parameters + ---------- + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[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 + + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc + + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by + + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkspaceAuditLogResponse + A list of workspace audit logs + + Examples + -------- + import asyncio + import datetime + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + from_=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2024-04-22 16:00:31+00:00", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + WorkspaceAuditLogResponse, + parse_obj_as( + type_=WorkspaceAuditLogResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py new file mode 100644 index 0000000..3decf29 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py @@ -0,0 +1,6 @@ +# This file was auto-generated by Fern from our API Definition. + +from .audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +from .audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py new file mode 100644 index 0000000..950e45b --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AuditLogsGetWorkspaceAuditLogsRequestEventType = typing.Union[ + typing.Literal["user_access", "custom_role", "workspace_membership", "site_membership", "workspace_invitation"], + typing.Any, +] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py new file mode 100644 index 0000000..dd90d5f --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AuditLogsGetWorkspaceAuditLogsRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/types/__init__.py b/src/webflow/types/__init__.py index 5b2d8c6..9f662bd 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -19,6 +19,8 @@ from .bulk_collection_item_field_data import BulkCollectionItemFieldData from .collection import Collection from .collection_item import CollectionItem +from .collection_item_changed import CollectionItemChanged +from .collection_item_created import CollectionItemCreated from .collection_item_field_data import CollectionItemFieldData from .collection_item_list import CollectionItemList from .collection_item_list_no_pagination import CollectionItemListNoPagination @@ -27,26 +29,51 @@ from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData from .collection_item_post_single import CollectionItemPostSingle from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData +from .collection_item_published import CollectionItemPublished +from .collection_item_removed import CollectionItemRemoved +from .collection_item_removed_payload import CollectionItemRemovedPayload +from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData +from .collection_item_unpublished import CollectionItemUnpublished +from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload +from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData from .collection_item_with_id_input import CollectionItemWithIdInput from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData from .collection_list import CollectionList from .collection_list_array_item import CollectionListArrayItem +from .comment import Comment +from .comment_payload import CommentPayload +from .comment_payload_author import CommentPayloadAuthor +from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem +from .comment_reply import CommentReply +from .comment_reply_author import CommentReplyAuthor +from .comment_reply_list import CommentReplyList +from .comment_reply_list_pagination import CommentReplyListPagination +from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem +from .comment_thread import CommentThread +from .comment_thread_author import CommentThreadAuthor +from .comment_thread_list import CommentThreadList +from .comment_thread_list_pagination import CommentThreadListPagination +from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem from .component import Component from .component_dom import ComponentDom -from .component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from .component_instance import ComponentInstance from .component_instance_node_property_overrides_write_property_overrides_item import ( ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, ) from .component_list import ComponentList -from .component_node import ComponentNode +from .component_node_dom import ComponentNodeDom 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 from .custom_code_hosted_response import CustomCodeHostedResponse from .custom_code_inline_response import CustomCodeInlineResponse +from .custom_role import CustomRole +from .custom_role_audit_log_item import CustomRoleAuditLogItem +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType from .dom import Dom from .domain import Domain from .domains import Domains @@ -55,7 +82,13 @@ from .error import Error from .error_code import ErrorCode from .field import Field +from .field_create import FieldCreate from .field_type import FieldType +from .field_validations import FieldValidations +from .field_validations_additional_properties import FieldValidationsAdditionalProperties +from .field_validations_additional_properties_additional_properties import ( + FieldValidationsAdditionalPropertiesAdditionalProperties, +) from .forbidden_error_body import ForbiddenErrorBody from .form import Form from .form_field import FormField @@ -65,23 +98,45 @@ from .form_response_settings import FormResponseSettings from .form_submission import FormSubmission from .form_submission_list import FormSubmissionList -from .image_node import ImageNode +from .form_submission_trigger import FormSubmissionTrigger +from .form_submission_trigger_payload import FormSubmissionTriggerPayload +from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem +from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType +from .image_node_dom import ImageNodeDom from .image_node_image import ImageNodeImage from .invalid_domain import InvalidDomain from .invalid_scopes import InvalidScopes from .inventory_item import InventoryItem from .inventory_item_inventory_type import InventoryItemInventoryType +from .items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished +from .items_list_items_request_last_published import ItemsListItemsRequestLastPublished from .list_custom_code_blocks import ListCustomCodeBlocks from .locale import Locale from .locales import Locales +from .metadata import Metadata +from .metadata_options_item import MetadataOptionsItem +from .new_order import NewOrder from .no_domains import NoDomains -from .node import Node, Node_ComponentInstance, Node_Image, Node_Text +from .node import ( + Node, + Node_ComponentInstance, + Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, + Node_Text, + Node_TextInput, +) from .not_enterprise_plan_site import NotEnterprisePlanSite from .not_enterprise_plan_workspace import NotEnterprisePlanWorkspace +from .option_field import OptionField from .order import Order from .order_address import OrderAddress from .order_address_japan_type import OrderAddressJapanType from .order_address_type import OrderAddressType +from .order_billing_address import OrderBillingAddress +from .order_billing_address_japan_type import OrderBillingAddressJapanType +from .order_billing_address_type import OrderBillingAddressType from .order_customer_info import OrderCustomerInfo from .order_dispute_last_status import OrderDisputeLastStatus from .order_download_files_item import OrderDownloadFilesItem @@ -92,15 +147,26 @@ from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem +from .order_shipping_address import OrderShippingAddress +from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from .order_shipping_address_type import OrderShippingAddressType from .order_status import OrderStatus from .order_totals import OrderTotals from .order_totals_extras_item import OrderTotalsExtrasItem from .order_totals_extras_item_type import OrderTotalsExtrasItemType from .page import Page +from .page_created_webhook import PageCreatedWebhook +from .page_created_webhook_payload import PageCreatedWebhookPayload +from .page_deleted_webhook import PageDeletedWebhook +from .page_deleted_webhook_payload import PageDeletedWebhookPayload from .page_list import PageList +from .page_metadata_updated_webhook import PageMetadataUpdatedWebhook +from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload from .page_open_graph import PageOpenGraph from .page_seo import PageSeo from .pagination import Pagination +from .payload import Payload +from .payload_field_data import PayloadFieldData from .paypal_details import PaypalDetails from .product import Product from .product_and_sk_us import ProductAndSkUs @@ -111,11 +177,24 @@ from .publish_status import PublishStatus from .redirect import Redirect from .redirects import Redirects +from .reference_field import ReferenceField +from .reference_field_metadata import ReferenceFieldMetadata +from .reference_field_type import ReferenceFieldType from .registered_script_list import RegisteredScriptList +from .robots import Robots +from .robots_rules_item import RobotsRulesItem from .script_apply import ScriptApply from .script_apply_list import ScriptApplyList from .script_apply_location import ScriptApplyLocation from .scripts import Scripts +from .search_button import SearchButton +from .search_button_node_dom import SearchButtonNodeDom +from .select import Select +from .select_node_choices_item import SelectNodeChoicesItem +from .select_node_dom import SelectNodeDom +from .select_node_write_choices_item import SelectNodeWriteChoicesItem +from .single_locale_created_payload import SingleLocaleCreatedPayload +from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData from .site import Site from .site_activity_log_item import SiteActivityLogItem from .site_activity_log_item_event import SiteActivityLogItemEvent @@ -123,9 +202,14 @@ from .site_activity_log_item_user import SiteActivityLogItemUser from .site_activity_log_response import SiteActivityLogResponse from .site_data_collection_type import SiteDataCollectionType +from .site_membership import SiteMembership +from .site_membership_audit_log_item import SiteMembershipAuditLogItem +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType from .site_plan import SitePlan from .site_plan_id import SitePlanId from .site_plan_name import SitePlanName +from .site_publish import SitePublish +from .site_publish_payload import SitePublishPayload from .sites import Sites from .sku import Sku from .sku_field_data import SkuFieldData @@ -139,16 +223,26 @@ from .sku_property_list import SkuPropertyList from .sku_property_list_enum_item import SkuPropertyListEnumItem from .sku_value_list import SkuValueList +from .static_field import StaticField +from .static_field_type import StaticFieldType from .stripe_card import StripeCard from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires from .stripe_details import StripeDetails +from .submit_button import SubmitButton +from .submit_button_node_dom import SubmitButtonNodeDom from .text import Text +from .text_input import TextInput +from .text_input_node_dom import TextInputNodeDom from .text_node import TextNode +from .text_node_dom import TextNodeDom from .text_node_text import TextNodeText -from .text_node_write import TextNodeWrite from .trigger_type import TriggerType +from .updated_order import UpdatedOrder from .user import User +from .user_access import UserAccess +from .user_access_audit_log_item import UserAccessAuditLogItem +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType from .user_access_groups_item import UserAccessGroupsItem from .user_access_groups_item_type import UserAccessGroupsItemType from .user_data import UserData @@ -160,6 +254,50 @@ from .webhook import Webhook from .webhook_filter import WebhookFilter from .webhook_list import WebhookList +from .workspace_audit_log_item import ( + WorkspaceAuditLogItem, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, +) +from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor +from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod +from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite +from .workspace_audit_log_item_payload_site_membership_target_user import ( + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, +) +from .workspace_audit_log_item_payload_site_membership_user_type import ( + WorkspaceAuditLogItemPayloadSiteMembershipUserType, +) +from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod +from .workspace_audit_log_item_payload_workspace_invitation_method import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, +) +from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, +) +from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +) +from .workspace_audit_log_item_payload_workspace_membership_method import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, +) +from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, +) +from .workspace_audit_log_item_payload_workspace_membership_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, +) +from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace +from .workspace_audit_log_response import WorkspaceAuditLogResponse +from .workspace_invitation import WorkspaceInvitation +from .workspace_invitation_audit_log_item import WorkspaceInvitationAuditLogItem +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .workspace_membership import WorkspaceMembership +from .workspace_membership_audit_log_item import WorkspaceMembershipAuditLogItem +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType __all__ = [ "AccessGroup", @@ -181,6 +319,8 @@ "BulkCollectionItemFieldData", "Collection", "CollectionItem", + "CollectionItemChanged", + "CollectionItemCreated", "CollectionItemFieldData", "CollectionItemList", "CollectionItemListNoPagination", @@ -189,24 +329,49 @@ "CollectionItemPatchSingleFieldData", "CollectionItemPostSingle", "CollectionItemPostSingleFieldData", + "CollectionItemPublished", + "CollectionItemRemoved", + "CollectionItemRemovedPayload", + "CollectionItemRemovedPayloadFieldData", + "CollectionItemUnpublished", + "CollectionItemUnpublishedPayload", + "CollectionItemUnpublishedPayloadFieldData", "CollectionItemWithIdInput", "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Comment", + "CommentPayload", + "CommentPayloadAuthor", + "CommentPayloadMentionedUsersItem", + "CommentReply", + "CommentReplyAuthor", + "CommentReplyList", + "CommentReplyListPagination", + "CommentReplyMentionedUsersItem", + "CommentThread", + "CommentThreadAuthor", + "CommentThreadList", + "CommentThreadListPagination", + "CommentThreadMentionedUsersItem", "Component", "ComponentDom", - "ComponentInstanceNodePropertyOverridesWrite", + "ComponentInstance", "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem", "ComponentList", - "ComponentNode", + "ComponentNodeDom", "ComponentProperties", "ComponentProperty", "ComponentPropertyType", + "Conflict", "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", "CustomCodeHostedResponse", "CustomCodeInlineResponse", + "CustomRole", + "CustomRoleAuditLogItem", + "CustomRoleAuditLogItemEventSubType", "Dom", "Domain", "Domains", @@ -215,7 +380,11 @@ "Error", "ErrorCode", "Field", + "FieldCreate", "FieldType", + "FieldValidations", + "FieldValidationsAdditionalProperties", + "FieldValidationsAdditionalPropertiesAdditionalProperties", "ForbiddenErrorBody", "Form", "FormField", @@ -225,26 +394,43 @@ "FormResponseSettings", "FormSubmission", "FormSubmissionList", - "ImageNode", + "FormSubmissionTrigger", + "FormSubmissionTriggerPayload", + "FormSubmissionTriggerPayloadSchemaItem", + "FormSubmissionTriggerPayloadSchemaItemFieldType", + "ImageNodeDom", "ImageNodeImage", "InvalidDomain", "InvalidScopes", "InventoryItem", "InventoryItemInventoryType", + "ItemsListItemsLiveRequestLastPublished", + "ItemsListItemsRequestLastPublished", "ListCustomCodeBlocks", "Locale", "Locales", + "Metadata", + "MetadataOptionsItem", + "NewOrder", "NoDomains", "Node", "Node_ComponentInstance", "Node_Image", + "Node_SearchButton", + "Node_Select", + "Node_SubmitButton", "Node_Text", + "Node_TextInput", "NotEnterprisePlanSite", "NotEnterprisePlanWorkspace", + "OptionField", "Order", "OrderAddress", "OrderAddressJapanType", "OrderAddressType", + "OrderBillingAddress", + "OrderBillingAddressJapanType", + "OrderBillingAddressType", "OrderCustomerInfo", "OrderDisputeLastStatus", "OrderDownloadFilesItem", @@ -255,15 +441,26 @@ "OrderPurchasedItemVariantImage", "OrderPurchasedItemVariantImageFile", "OrderPurchasedItemVariantImageFileVariantsItem", + "OrderShippingAddress", + "OrderShippingAddressJapanType", + "OrderShippingAddressType", "OrderStatus", "OrderTotals", "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", "Page", + "PageCreatedWebhook", + "PageCreatedWebhookPayload", + "PageDeletedWebhook", + "PageDeletedWebhookPayload", "PageList", + "PageMetadataUpdatedWebhook", + "PageMetadataUpdatedWebhookPayload", "PageOpenGraph", "PageSeo", "Pagination", + "Payload", + "PayloadFieldData", "PaypalDetails", "Product", "ProductAndSkUs", @@ -274,11 +471,24 @@ "PublishStatus", "Redirect", "Redirects", + "ReferenceField", + "ReferenceFieldMetadata", + "ReferenceFieldType", "RegisteredScriptList", + "Robots", + "RobotsRulesItem", "ScriptApply", "ScriptApplyList", "ScriptApplyLocation", "Scripts", + "SearchButton", + "SearchButtonNodeDom", + "Select", + "SelectNodeChoicesItem", + "SelectNodeDom", + "SelectNodeWriteChoicesItem", + "SingleLocaleCreatedPayload", + "SingleLocaleCreatedPayloadFieldData", "Site", "SiteActivityLogItem", "SiteActivityLogItemEvent", @@ -286,9 +496,14 @@ "SiteActivityLogItemUser", "SiteActivityLogResponse", "SiteDataCollectionType", + "SiteMembership", + "SiteMembershipAuditLogItem", + "SiteMembershipAuditLogItemEventSubType", "SitePlan", "SitePlanId", "SitePlanName", + "SitePublish", + "SitePublishPayload", "Sites", "Sku", "SkuFieldData", @@ -302,16 +517,26 @@ "SkuPropertyList", "SkuPropertyListEnumItem", "SkuValueList", + "StaticField", + "StaticFieldType", "StripeCard", "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "SubmitButton", + "SubmitButtonNodeDom", "Text", + "TextInput", + "TextInputNodeDom", "TextNode", + "TextNodeDom", "TextNodeText", - "TextNodeWrite", "TriggerType", + "UpdatedOrder", "User", + "UserAccess", + "UserAccessAuditLogItem", + "UserAccessAuditLogItemEventSubType", "UserAccessGroupsItem", "UserAccessGroupsItemType", "UserData", @@ -323,4 +548,30 @@ "Webhook", "WebhookFilter", "WebhookList", + "WorkspaceAuditLogItem", + "WorkspaceAuditLogItemActor", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipSite", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType", + "WorkspaceAuditLogItemPayloadUserAccessMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType", + "WorkspaceAuditLogItemWorkspace", + "WorkspaceAuditLogItem_CustomRole", + "WorkspaceAuditLogItem_SiteMembership", + "WorkspaceAuditLogItem_UserAccess", + "WorkspaceAuditLogItem_WorkspaceInvitation", + "WorkspaceAuditLogItem_WorkspaceMembership", + "WorkspaceAuditLogResponse", + "WorkspaceInvitation", + "WorkspaceInvitationAuditLogItem", + "WorkspaceInvitationAuditLogItemEventSubType", + "WorkspaceMembership", + "WorkspaceMembershipAuditLogItem", + "WorkspaceMembershipAuditLogItemEventSubType", ] diff --git a/src/webflow/types/application.py b/src/webflow/types/application.py index ac819f0..b11f910 100644 --- a/src/webflow/types/application.py +++ b/src/webflow/types/application.py @@ -1,5 +1,41 @@ # This file was auto-generated by Fern from our API Definition. +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -Application = typing.Optional[typing.Any] + +class Application(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the Application + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + Application description provided by the developer + """ + + homepage: typing.Optional[str] = pydantic.Field(default=None) + """ + Application homepage URL provided by the developer + """ + + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) + """ + Application name provided by the developer + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset.py b/src/webflow/types/asset.py index b67cefa..8ebad3b 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -11,6 +11,10 @@ class Asset(UniversalBaseModel): + """ + Asset details + """ + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for this asset @@ -49,9 +53,7 @@ class Asset(UniversalBaseModel): Original file name at the time of upload """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Display name of the asset """ @@ -70,7 +72,11 @@ class Asset(UniversalBaseModel): Date the asset metadata was created """ - variants: typing.Optional[typing.List[AssetVariant]] = None + variants: typing.List[AssetVariant] = pydantic.Field() + """ + A list of [asset variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) created by Webflow to serve your site responsively. + """ + alt_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="altText")] = pydantic.Field( default=None ) diff --git a/src/webflow/types/asset_variant.py b/src/webflow/types/asset_variant.py index 5278667..0ad16f1 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.py @@ -2,40 +2,38 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing_extensions -import typing from ..core.serialization import FieldMetadata import pydantic +import typing from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AssetVariant(UniversalBaseModel): - hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( - default=None - ) + """ + Asset variant details + """ + + hosted_url: typing_extensions.Annotated[str, FieldMetadata(alias="hostedUrl")] = pydantic.Field() """ URL of where the asset variant is hosted """ - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - pydantic.Field(default=None) - ) + original_file_name: typing_extensions.Annotated[str, FieldMetadata(alias="originalFileName")] = pydantic.Field() """ Original file name of the variant """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Display name of the variant """ - format: typing.Optional[str] = pydantic.Field(default=None) + format: str = pydantic.Field() """ format of the variant """ - width: typing.Optional[int] = pydantic.Field(default=None) + width: int = pydantic.Field() """ Width in pixels """ @@ -45,7 +43,7 @@ class AssetVariant(UniversalBaseModel): Height in pixels """ - quality: typing.Optional[int] = pydantic.Field(default=None) + quality: int = pydantic.Field() """ Value between 0 and 100 representing the image quality """ diff --git a/src/webflow/types/assets.py b/src/webflow/types/assets.py index 380b0de..bd5f8ea 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -3,6 +3,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing from .asset import Asset +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -13,6 +14,7 @@ class Assets(UniversalBaseModel): """ assets: typing.Optional[typing.List[Asset]] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/bulk_collection_item.py b/src/webflow/types/bulk_collection_item.py index 4d17d13..de8e770 100644 --- a/src/webflow/types/bulk_collection_item.py +++ b/src/webflow/types/bulk_collection_item.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel +import typing import pydantic import typing_extensions -import typing from ..core.serialization import FieldMetadata from .bulk_collection_item_field_data import BulkCollectionItemFieldData from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -14,7 +14,7 @@ class BulkCollectionItem(UniversalBaseModel): The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items """ - id: str = pydantic.Field() + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Item """ diff --git a/src/webflow/types/collection.py b/src/webflow/types/collection.py index 81e0f90..561a535 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -3,8 +3,8 @@ from ..core.pydantic_utilities import UniversalBaseModel import pydantic import typing_extensions -import typing from ..core.serialization import FieldMetadata +import typing import datetime as dt from .field import Field from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -20,16 +20,12 @@ class Collection(UniversalBaseModel): Unique identifier for a Collection """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Name given to the Collection """ - singular_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="singularName")] = ( - pydantic.Field(default=None) - ) + singular_name: typing_extensions.Annotated[str, FieldMetadata(alias="singularName")] = pydantic.Field() """ The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) """ diff --git a/src/webflow/types/collection_item_changed.py b/src/webflow/types/collection_item_changed.py new file mode 100644 index 0000000..4484722 --- /dev/null +++ b/src/webflow/types/collection_item_changed.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .single_locale_created_payload import SingleLocaleCreatedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemChanged(UniversalBaseModel): + """ + The Webhook payload for when a Collection Item is changed + """ + + trigger_type: typing_extensions.Annotated[ + typing.Literal["collection_item_changed"], FieldMetadata(alias="triggerType") + ] = pydantic.Field(default="collection_item_changed") + """ + The type of event that triggered the request + """ + + payload: SingleLocaleCreatedPayload + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_created.py b/src/webflow/types/collection_item_created.py new file mode 100644 index 0000000..bc6233c --- /dev/null +++ b/src/webflow/types/collection_item_created.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .single_locale_created_payload import SingleLocaleCreatedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemCreated(UniversalBaseModel): + """ + The Webhook payload for when a Collection Item is created + """ + + trigger_type: typing_extensions.Annotated[ + typing.Literal["collection_item_created"], FieldMetadata(alias="triggerType") + ] = pydantic.Field(default="collection_item_created") + """ + The type of event that triggered the request + """ + + payload: SingleLocaleCreatedPayload + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_published.py b/src/webflow/types/collection_item_published.py new file mode 100644 index 0000000..c315f37 --- /dev/null +++ b/src/webflow/types/collection_item_published.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .payload import Payload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemPublished(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Payload] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_removed.py b/src/webflow/types/collection_item_removed.py new file mode 100644 index 0000000..fb09cd7 --- /dev/null +++ b/src/webflow/types/collection_item_removed.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .collection_item_removed_payload import CollectionItemRemovedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemRemoved(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CollectionItemRemovedPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_removed_payload.py b/src/webflow/types/collection_item_removed_payload.py new file mode 100644 index 0000000..745cf3c --- /dev/null +++ b/src/webflow/types/collection_item_removed_payload.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemRemovedPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was deleted + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemRemovedPayloadFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_removed_payload_field_data.py b/src/webflow/types/collection_item_removed_payload_field_data.py new file mode 100644 index 0000000..bca5629 --- /dev/null +++ b/src/webflow/types/collection_item_removed_payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class CollectionItemRemovedPayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_unpublished.py b/src/webflow/types/collection_item_unpublished.py new file mode 100644 index 0000000..ce23d7f --- /dev/null +++ b/src/webflow/types/collection_item_unpublished.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemUnpublished(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CollectionItemUnpublishedPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_unpublished_payload.py b/src/webflow/types/collection_item_unpublished_payload.py new file mode 100644 index 0000000..7250b24 --- /dev/null +++ b/src/webflow/types/collection_item_unpublished_payload.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemUnpublishedPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was unpublished + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemUnpublishedPayloadFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_unpublished_payload_field_data.py b/src/webflow/types/collection_item_unpublished_payload_field_data.py new file mode 100644 index 0000000..8ae8719 --- /dev/null +++ b/src/webflow/types/collection_item_unpublished_payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class CollectionItemUnpublishedPayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment.py b/src/webflow/types/comment.py new file mode 100644 index 0000000..b5df7e7 --- /dev/null +++ b/src/webflow/types/comment.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .comment_payload import CommentPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Comment(UniversalBaseModel): + """ + The Webhook payload for when a comment thread or reply is made on a Site + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CommentPayload] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_payload.py b/src/webflow/types/comment_payload.py new file mode 100644 index 0000000..c6b6a38 --- /dev/null +++ b/src/webflow/types/comment_payload.py @@ -0,0 +1,114 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .comment_payload_author import CommentPayloadAuthor +from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentPayload(UniversalBaseModel): + """ + The comment webhook payload contains data for the thread and for replies. Check the type to determine if the payload is for a thread or a reply. The webhook payload may be delayed by up to 5 minutes. + """ + + thread_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="threadId")] = pydantic.Field( + default=None + ) + """ + Unique identifier for the comment thread + """ + + comment_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="commentId")] = pydantic.Field( + default=None + ) + """ + Unique identifier for the comment reply + """ + + type: typing.Optional[str] = pydantic.Field(default=None) + """ + The type of comment payload + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( + default=None + ) + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( + default=None + ) + """ + The item unique identifier + """ + + breakpoint: typing.Optional[str] = pydantic.Field(default=None) + """ + The breakpoint the comment was left on + """ + + url: typing.Optional[str] = pydantic.Field(default=None) + """ + The URL of the page the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentPayloadAuthor + mentioned_users: typing_extensions.Annotated[ + typing.List[CommentPayloadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field() + """ + List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_payload_author.py b/src/webflow/types/comment_payload_author.py new file mode 100644 index 0000000..04c9ba8 --- /dev/null +++ b/src/webflow/types/comment_payload_author.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentPayloadAuthor(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the author + """ + + email: str = pydantic.Field() + """ + Email of the author + """ + + name: str = pydantic.Field() + """ + Name of the author + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_payload_mentioned_users_item.py b/src/webflow/types/comment_payload_mentioned_users_item.py new file mode 100644 index 0000000..7a63d83 --- /dev/null +++ b/src/webflow/types/comment_payload_mentioned_users_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentPayloadMentionedUsersItem(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply.py b/src/webflow/types/comment_reply.py new file mode 100644 index 0000000..1017249 --- /dev/null +++ b/src/webflow/types/comment_reply.py @@ -0,0 +1,89 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from .comment_reply_author import CommentReplyAuthor +from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentReply(UniversalBaseModel): + """ + A comment thread represents a conversation between users on a specific page. Each comment thread has a unique identifier and can contain multiple comments. + """ + + id: str = pydantic.Field() + """ + Unique identifier for the comment thread + """ + + comment_id: typing_extensions.Annotated[str, FieldMetadata(alias="commentId")] = pydantic.Field() + """ + The comment reply unique identifier + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + breakpoint: str = pydantic.Field() + """ + The breakpoint the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentReplyAuthor + mentioned_users: typing_extensions.Annotated[ + typing.Optional[typing.List[CommentReplyMentionedUsersItem]], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field(default=None) + """ + List of mentioned users is an empty array until email notifications are sent. + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_author.py b/src/webflow/types/comment_reply_author.py new file mode 100644 index 0000000..7509b7e --- /dev/null +++ b/src/webflow/types/comment_reply_author.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyAuthor(UniversalBaseModel): + id: str = pydantic.Field() + """ + The unique identifier of the author + """ + + email: str = pydantic.Field() + """ + Email of the author + """ + + name: str = pydantic.Field() + """ + Name of the author + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_list.py b/src/webflow/types/comment_reply_list.py new file mode 100644 index 0000000..c382932 --- /dev/null +++ b/src/webflow/types/comment_reply_list.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .comment_reply import CommentReply +from .comment_reply_list_pagination import CommentReplyListPagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CommentReplyList(UniversalBaseModel): + """ + A list of comment replies. + """ + + comments: typing.List[CommentReply] + pagination: CommentReplyListPagination + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_list_pagination.py b/src/webflow/types/comment_reply_list_pagination.py new file mode 100644 index 0000000..7fa5c8e --- /dev/null +++ b/src/webflow/types/comment_reply_list_pagination.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyListPagination(UniversalBaseModel): + limit: float = pydantic.Field() + """ + The limit specified in the request (default 100) + """ + + offset: float = pydantic.Field() + """ + The offset specified for pagination + """ + + total: float = pydantic.Field() + """ + Total number of comment replies + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_mentioned_users_item.py b/src/webflow/types/comment_reply_mentioned_users_item.py new file mode 100644 index 0000000..12324d9 --- /dev/null +++ b/src/webflow/types/comment_reply_mentioned_users_item.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyMentionedUsersItem(UniversalBaseModel): + id: str = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread.py b/src/webflow/types/comment_thread.py new file mode 100644 index 0000000..0694916 --- /dev/null +++ b/src/webflow/types/comment_thread.py @@ -0,0 +1,92 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from .comment_thread_author import CommentThreadAuthor +from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentThread(UniversalBaseModel): + """ + A comment thread represents a conversation between users on a specific page. Each comment thread has a unique identifier and can contain multiple comments. Retrieve comment replies using the replies API endpoint. + """ + + id: str = pydantic.Field() + """ + Unique identifier for the comment thread + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( + default=None + ) + """ + The item unique identifier + """ + + breakpoint: str = pydantic.Field() + """ + The breakpoint the comment was left on + """ + + url: str = pydantic.Field() + """ + The URL of the page the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentThreadAuthor + mentioned_users: typing_extensions.Annotated[ + typing.List[CommentThreadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field() + """ + List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. + """ + + created_on: typing_extensions.Annotated[str, FieldMetadata(alias="createdOn")] = pydantic.Field() + """ + The date the item was created + """ + + last_updated: typing_extensions.Annotated[str, FieldMetadata(alias="lastUpdated")] = pydantic.Field() + """ + The date the item was last updated + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_author.py b/src/webflow/types/comment_thread_author.py new file mode 100644 index 0000000..c2f1b1e --- /dev/null +++ b/src/webflow/types/comment_thread_author.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadAuthor(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the author + """ + + email: str = pydantic.Field() + """ + Email of the author + """ + + name: str = pydantic.Field() + """ + Name of the author + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_list.py b/src/webflow/types/comment_thread_list.py new file mode 100644 index 0000000..f46e6bd --- /dev/null +++ b/src/webflow/types/comment_thread_list.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .comment_thread import CommentThread +from .comment_thread_list_pagination import CommentThreadListPagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CommentThreadList(UniversalBaseModel): + """ + A list of comment threads on the site. Contains the content of the first reply. + """ + + comments: typing.List[CommentThread] + pagination: CommentThreadListPagination + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_list_pagination.py b/src/webflow/types/comment_thread_list_pagination.py new file mode 100644 index 0000000..e5d55bb --- /dev/null +++ b/src/webflow/types/comment_thread_list_pagination.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadListPagination(UniversalBaseModel): + limit: float = pydantic.Field() + """ + The limit specified in the request (default 100) + """ + + offset: float = pydantic.Field() + """ + The offset specified for pagination + """ + + total: float = pydantic.Field() + """ + Total number of comment threads + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_mentioned_users_item.py b/src/webflow/types/comment_thread_mentioned_users_item.py new file mode 100644 index 0000000..f9a20df --- /dev/null +++ b/src/webflow/types/comment_thread_mentioned_users_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadMentionedUsersItem(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_dom.py b/src/webflow/types/component_dom.py index 3f76c81..2f70fc4 100644 --- a/src/webflow/types/component_dom.py +++ b/src/webflow/types/component_dom.py @@ -12,7 +12,7 @@ class ComponentDom(UniversalBaseModel): """ - The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, or nested component instances. + The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, select or text inputs, submit buttons, or nested component instances. """ component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( diff --git a/src/webflow/types/component_instance_node_property_overrides_write.py b/src/webflow/types/component_instance.py similarity index 94% rename from src/webflow/types/component_instance_node_property_overrides_write.py rename to src/webflow/types/component_instance.py index 6c7d69c..301324f 100644 --- a/src/webflow/types/component_instance_node_property_overrides_write.py +++ b/src/webflow/types/component_instance.py @@ -11,7 +11,7 @@ from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ComponentInstanceNodePropertyOverridesWrite(UniversalBaseModel): +class ComponentInstance(UniversalBaseModel): """ Update text property overrides of a component instance """ diff --git a/src/webflow/types/component_node.py b/src/webflow/types/component_node_dom.py similarity index 69% rename from src/webflow/types/component_node.py rename to src/webflow/types/component_node_dom.py index fa5f69d..9e9d74b 100644 --- a/src/webflow/types/component_node.py +++ b/src/webflow/types/component_node_dom.py @@ -1,34 +1,32 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing import pydantic import typing_extensions from ..core.serialization import FieldMetadata +import typing from .component_property import ComponentProperty from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ComponentNode(UniversalBaseModel): +class ComponentNodeDom(UniversalBaseModel): """ Represents a component instance within the DOM. It contains details about the component instance, such as its type and properties. """ - id: typing.Optional[str] = pydantic.Field(default=None) + id: str = pydantic.Field() """ - Node UUID + The unique identifier of the component instance node """ - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( - pydantic.Field(default=None) - ) + component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] = pydantic.Field() """ - Component ID + The unique identifier of the component """ property_overrides: typing_extensions.Annotated[ - typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") - ] = pydantic.Field(default=None) + typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + ] = pydantic.Field() """ List of component properties with overrides for a component instance. """ diff --git a/src/webflow/types/conflict.py b/src/webflow/types/conflict.py new file mode 100644 index 0000000..30b9809 --- /dev/null +++ b/src/webflow/types/conflict.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +Conflict = typing.Optional[typing.Any] diff --git a/src/webflow/types/custom_role.py b/src/webflow/types/custom_role.py new file mode 100644 index 0000000..f8c9440 --- /dev/null +++ b/src/webflow/types/custom_role.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CustomRole(UniversalBaseModel): + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the custom role + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous name of the custom role + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_role_audit_log_item.py b/src/webflow/types/custom_role_audit_log_item.py new file mode 100644 index 0000000..336aa26 --- /dev/null +++ b/src/webflow/types/custom_role_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .custom_role import CustomRole +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CustomRoleAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[CustomRole] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_role_audit_log_item_event_sub_type.py b/src/webflow/types/custom_role_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..38d177b --- /dev/null +++ b/src/webflow/types/custom_role_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CustomRoleAuditLogItemEventSubType = typing.Union[ + typing.Literal["role_created", "role_updated", "role_deleted"], typing.Any +] diff --git a/src/webflow/types/dom.py b/src/webflow/types/dom.py index ce15a6a..431e3d8 100644 --- a/src/webflow/types/dom.py +++ b/src/webflow/types/dom.py @@ -7,6 +7,7 @@ import pydantic from .node import Node from .pagination import Pagination +import datetime as dt from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -22,8 +23,21 @@ class Dom(UniversalBaseModel): Page ID """ + branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( + default=None + ) + """ + If the page is a branch, this is the ID of the branch + """ + nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the page dom was most recently updated + """ if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/field.py b/src/webflow/types/field.py index 40233a9..9543092 100644 --- a/src/webflow/types/field.py +++ b/src/webflow/types/field.py @@ -6,6 +6,7 @@ from ..core.serialization import FieldMetadata import typing from .field_type import FieldType +from .field_validations import FieldValidations from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -53,6 +54,11 @@ class Field(UniversalBaseModel): Additional text to help anyone filling out this field """ + validations: typing.Optional[FieldValidations] = pydantic.Field(default=None) + """ + The validations for the field + """ + if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 else: diff --git a/src/webflow/types/field_create.py b/src/webflow/types/field_create.py new file mode 100644 index 0000000..1c9cf61 --- /dev/null +++ b/src/webflow/types/field_create.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .static_field import StaticField +from .option_field import OptionField +from .reference_field import ReferenceField + +FieldCreate = typing.Union[StaticField, OptionField, ReferenceField] diff --git a/src/webflow/types/field_type.py b/src/webflow/types/field_type.py index 6318a3d..e3495ce 100644 --- a/src/webflow/types/field_type.py +++ b/src/webflow/types/field_type.py @@ -8,15 +8,19 @@ "DateTime", "Email", "ExtFileRef", + "File", "Image", "Link", "MultiImage", + "MultiReference", "Number", + "Option", "Phone", "PlainText", + "Reference", "RichText", "Switch", - "Video", + "VideoLink", ], typing.Any, ] diff --git a/src/webflow/types/field_validations.py b/src/webflow/types/field_validations.py new file mode 100644 index 0000000..ca58a0b --- /dev/null +++ b/src/webflow/types/field_validations.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .field_validations_additional_properties import FieldValidationsAdditionalProperties +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class FieldValidations(UniversalBaseModel): + """ + The validations for the field + """ + + additional_properties: typing_extensions.Annotated[ + typing.Optional[FieldValidationsAdditionalProperties], FieldMetadata(alias="additionalProperties") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/field_validations_additional_properties.py b/src/webflow/types/field_validations_additional_properties.py new file mode 100644 index 0000000..ba31807 --- /dev/null +++ b/src/webflow/types/field_validations_additional_properties.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .field_validations_additional_properties_additional_properties import ( + FieldValidationsAdditionalPropertiesAdditionalProperties, +) + +FieldValidationsAdditionalProperties = typing.Union[ + str, float, bool, int, FieldValidationsAdditionalPropertiesAdditionalProperties +] diff --git a/src/webflow/types/field_validations_additional_properties_additional_properties.py b/src/webflow/types/field_validations_additional_properties_additional_properties.py new file mode 100644 index 0000000..da6a9ee --- /dev/null +++ b/src/webflow/types/field_validations_additional_properties_additional_properties.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class FieldValidationsAdditionalPropertiesAdditionalProperties(UniversalBaseModel): + additional_properties: typing_extensions.Annotated[ + typing.Optional[typing.Optional[typing.Any]], FieldMetadata(alias="additionalProperties") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger.py b/src/webflow/types/form_submission_trigger.py new file mode 100644 index 0000000..82f1eaf --- /dev/null +++ b/src/webflow/types/form_submission_trigger.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .form_submission_trigger_payload import FormSubmissionTriggerPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTrigger(UniversalBaseModel): + """ + The Webhook payload for when a form is submitted + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[FormSubmissionTriggerPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload.py b/src/webflow/types/form_submission_trigger_payload.py new file mode 100644 index 0000000..f192a9f --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTriggerPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + The name of the form + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site that the form was submitted from + """ + + data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + The data submitted in the form + """ + + schema_: typing_extensions.Annotated[ + typing.Optional[typing.List[FormSubmissionTriggerPayloadSchemaItem]], FieldMetadata(alias="schema") + ] = pydantic.Field(default=None) + """ + A list of fields from the submitted form + """ + + submitted_at: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="submittedAt")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the form was submitted + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + the ID of the event + """ + + form_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formId")] = pydantic.Field( + default=None + ) + """ + The ID of the form submission + """ + + form_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formElementId")] = ( + pydantic.Field(default=None) + ) + """ + The uniqueID of the Form element + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload_schema_item.py b/src/webflow/types/form_submission_trigger_payload_schema_item.py new file mode 100644 index 0000000..014322f --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload_schema_item.py @@ -0,0 +1,41 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTriggerPayloadSchemaItem(UniversalBaseModel): + field_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldName")] = pydantic.Field( + default=None + ) + """ + Form field name + """ + + field_type: typing_extensions.Annotated[ + typing.Optional[FormSubmissionTriggerPayloadSchemaItemFieldType], FieldMetadata(alias="fieldType") + ] = pydantic.Field(default=None) + """ + Form field type + """ + + field_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldElementId")] = ( + pydantic.Field(default=None) + ) + """ + Element ID of the Form Field + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py b/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py new file mode 100644 index 0000000..0ab97d1 --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +FormSubmissionTriggerPayloadSchemaItemFieldType = typing.Union[ + typing.Literal["FormTextInput", "FormTextarea", "FormCheckboxInput", "FormRadioInput", "FormFileUploadInput"], + typing.Any, +] diff --git a/src/webflow/types/image_node.py b/src/webflow/types/image_node_dom.py similarity index 85% rename from src/webflow/types/image_node.py rename to src/webflow/types/image_node_dom.py index 2351cea..d6bcec1 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node_dom.py @@ -1,23 +1,27 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing import pydantic from .image_node_image import ImageNodeImage +import typing from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ImageNode(UniversalBaseModel): +class ImageNodeDom(UniversalBaseModel): """ Represents an image within the DOM. It contains details about the image, such as its alternative text (alt) for accessibility and an asset identifier for fetching the actual image resource. Additional attributes can be associated with the image for styling or other purposes. """ - id: typing.Optional[str] = pydantic.Field(default=None) + id: str = pydantic.Field() """ Node UUID """ - image: typing.Optional[ImageNodeImage] = None + image: ImageNodeImage = pydantic.Field() + """ + The image details of the node + """ + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) """ The custom attributes of the node diff --git a/src/webflow/types/image_node_image.py b/src/webflow/types/image_node_image.py index 2ef819f..f8d9379 100644 --- a/src/webflow/types/image_node_image.py +++ b/src/webflow/types/image_node_image.py @@ -9,6 +9,10 @@ class ImageNodeImage(UniversalBaseModel): + """ + The image details of the node + """ + alt: typing.Optional[str] = None asset_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetId")] = None diff --git a/src/webflow/types/items_list_items_live_request_last_published.py b/src/webflow/types/items_list_items_live_request_last_published.py new file mode 100644 index 0000000..31aab15 --- /dev/null +++ b/src/webflow/types/items_list_items_live_request_last_published.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsListItemsLiveRequestLastPublished(UniversalBaseModel): + lte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published before this date + """ + + gte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published after this date + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/items_list_items_request_last_published.py b/src/webflow/types/items_list_items_request_last_published.py new file mode 100644 index 0000000..bf4505d --- /dev/null +++ b/src/webflow/types/items_list_items_request_last_published.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsListItemsRequestLastPublished(UniversalBaseModel): + lte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published before this date + """ + + gte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published after this date + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/metadata.py b/src/webflow/types/metadata.py new file mode 100644 index 0000000..1c9caa7 --- /dev/null +++ b/src/webflow/types/metadata.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .metadata_options_item import MetadataOptionsItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Metadata(UniversalBaseModel): + """ + The metadata for the Option field. + """ + + options: typing.List[MetadataOptionsItem] = pydantic.Field() + """ + The option values for the Option field. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/metadata_options_item.py b/src/webflow/types/metadata_options_item.py new file mode 100644 index 0000000..91eb360 --- /dev/null +++ b/src/webflow/types/metadata_options_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class MetadataOptionsItem(UniversalBaseModel): + """ + A single option value for the Option field. + """ + + name: str = pydantic.Field() + """ + The name of the option + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The unique identifier of the option + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/new_order.py b/src/webflow/types/new_order.py new file mode 100644 index 0000000..c156c65 --- /dev/null +++ b/src/webflow/types/new_order.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .order import Order +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class NewOrder(UniversalBaseModel): + """ + The Webhook payload for when a new order is created + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Order] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/node.py b/src/webflow/types/node.py index cd0942f..6ec64b9 100644 --- a/src/webflow/types/node.py +++ b/src/webflow/types/node.py @@ -10,6 +10,7 @@ import typing_extensions from ..core.serialization import FieldMetadata from .component_property import ComponentProperty +from .select_node_choices_item import SelectNodeChoicesItem class Node_Text(UniversalBaseModel): @@ -18,8 +19,8 @@ class Node_Text(UniversalBaseModel): """ type: typing.Literal["text"] = "text" - id: typing.Optional[str] = None - text: typing.Optional[TextNodeText] = None + id: str + text: TextNodeText attributes: typing.Optional[typing.Dict[str, str]] = None if IS_PYDANTIC_V2: @@ -38,8 +39,8 @@ class Node_Image(UniversalBaseModel): """ type: typing.Literal["image"] = "image" - id: typing.Optional[str] = None - image: typing.Optional[ImageNodeImage] = None + id: str + image: ImageNodeImage attributes: typing.Optional[typing.Dict[str, str]] = None if IS_PYDANTIC_V2: @@ -58,11 +59,11 @@ class Node_ComponentInstance(UniversalBaseModel): """ type: typing.Literal["component-instance"] = "component-instance" - id: typing.Optional[str] = None - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = None + id: str + component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] property_overrides: typing_extensions.Annotated[ - typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") - ] = None + typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 @@ -74,4 +75,87 @@ class Config: extra = pydantic.Extra.allow -Node = typing.Union[Node_Text, Node_Image, Node_ComponentInstance] +class Node_TextInput(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["text-input"] = "text-input" + id: str + placeholder: str + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_Select(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["select"] = "select" + id: str + choices: typing.List[SelectNodeChoicesItem] + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_SubmitButton(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["submit-button"] = "submit-button" + id: str + value: str + waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_SearchButton(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["search-button"] = "search-button" + id: str + value: str + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +Node = typing.Union[ + Node_Text, Node_Image, Node_ComponentInstance, Node_TextInput, Node_Select, Node_SubmitButton, Node_SearchButton +] diff --git a/src/webflow/types/option_field.py b/src/webflow/types/option_field.py new file mode 100644 index 0000000..7f7c6d5 --- /dev/null +++ b/src/webflow/types/option_field.py @@ -0,0 +1,58 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .metadata import Metadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OptionField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: typing.Literal["Option"] = pydantic.Field(default="Option") + """ + The [Option field type](/data/reference/field-types-item-values#option) + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + metadata: Metadata + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order.py b/src/webflow/types/order.py index d45b1de..2b2844c 100644 --- a/src/webflow/types/order.py +++ b/src/webflow/types/order.py @@ -10,6 +10,8 @@ from .order_dispute_last_status import OrderDisputeLastStatus from .order_price import OrderPrice from .order_address import OrderAddress +from .order_shipping_address import OrderShippingAddress +from .order_billing_address import OrderBillingAddress from .order_customer_info import OrderCustomerInfo from .order_purchased_item import OrderPurchasedItem from .stripe_details import StripeDetails @@ -119,14 +121,14 @@ class Order(UniversalBaseModel): """ shipping_address: typing_extensions.Annotated[ - typing.Optional[OrderAddress], FieldMetadata(alias="shippingAddress") + typing.Optional[OrderShippingAddress], FieldMetadata(alias="shippingAddress") ] = pydantic.Field(default=None) """ The shipping address """ billing_address: typing_extensions.Annotated[ - typing.Optional[OrderAddress], FieldMetadata(alias="billingAddress") + typing.Optional[OrderBillingAddress], FieldMetadata(alias="billingAddress") ] = pydantic.Field(default=None) """ The billing address diff --git a/src/webflow/types/order_billing_address.py b/src/webflow/types/order_billing_address.py new file mode 100644 index 0000000..75e87c6 --- /dev/null +++ b/src/webflow/types/order_billing_address.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .order_billing_address_type import OrderBillingAddressType +import pydantic +import typing_extensions +from .order_billing_address_japan_type import OrderBillingAddressJapanType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrderBillingAddress(UniversalBaseModel): + """ + The billing address + """ + + type: typing.Optional[OrderBillingAddressType] = pydantic.Field(default=None) + """ + The type of the order address (billing or shipping) + """ + + japan_type: typing_extensions.Annotated[ + typing.Optional[OrderBillingAddressJapanType], FieldMetadata(alias="japanType") + ] = pydantic.Field(default=None) + """ + Represents a Japan-only address format. This field will only appear on orders placed from Japan. + """ + + addressee: typing.Optional[str] = pydantic.Field(default=None) + """ + Display name on the address + """ + + line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( + default=None + ) + """ + The first line of the address + """ + + line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( + default=None + ) + """ + The second line of the address + """ + + city: typing.Optional[str] = pydantic.Field(default=None) + """ + The city of the address. + """ + + state: typing.Optional[str] = pydantic.Field(default=None) + """ + The state or province of the address + """ + + country: typing.Optional[str] = pydantic.Field(default=None) + """ + The country of the address + """ + + postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( + default=None + ) + """ + The postal code of the address + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_billing_address_japan_type.py b/src/webflow/types/order_billing_address_japan_type.py new file mode 100644 index 0000000..8c983bb --- /dev/null +++ b/src/webflow/types/order_billing_address_japan_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderBillingAddressJapanType = typing.Union[typing.Literal["kana", "kanji"], typing.Any] diff --git a/src/webflow/types/order_billing_address_type.py b/src/webflow/types/order_billing_address_type.py new file mode 100644 index 0000000..6b03d6e --- /dev/null +++ b/src/webflow/types/order_billing_address_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderBillingAddressType = typing.Union[typing.Literal["shipping", "billing"], typing.Any] diff --git a/src/webflow/types/order_shipping_address.py b/src/webflow/types/order_shipping_address.py new file mode 100644 index 0000000..5c62f00 --- /dev/null +++ b/src/webflow/types/order_shipping_address.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .order_shipping_address_type import OrderShippingAddressType +import pydantic +import typing_extensions +from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrderShippingAddress(UniversalBaseModel): + """ + The shipping address + """ + + type: typing.Optional[OrderShippingAddressType] = pydantic.Field(default=None) + """ + The type of the order address (billing or shipping) + """ + + japan_type: typing_extensions.Annotated[ + typing.Optional[OrderShippingAddressJapanType], FieldMetadata(alias="japanType") + ] = pydantic.Field(default=None) + """ + Represents a Japan-only address format. This field will only appear on orders placed from Japan. + """ + + addressee: typing.Optional[str] = pydantic.Field(default=None) + """ + Display name on the address + """ + + line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( + default=None + ) + """ + The first line of the address + """ + + line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( + default=None + ) + """ + The second line of the address + """ + + city: typing.Optional[str] = pydantic.Field(default=None) + """ + The city of the address. + """ + + state: typing.Optional[str] = pydantic.Field(default=None) + """ + The state or province of the address + """ + + country: typing.Optional[str] = pydantic.Field(default=None) + """ + The country of the address + """ + + postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( + default=None + ) + """ + The postal code of the address + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_shipping_address_japan_type.py b/src/webflow/types/order_shipping_address_japan_type.py new file mode 100644 index 0000000..b5b548e --- /dev/null +++ b/src/webflow/types/order_shipping_address_japan_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderShippingAddressJapanType = typing.Union[typing.Literal["kana", "kanji"], typing.Any] diff --git a/src/webflow/types/order_shipping_address_type.py b/src/webflow/types/order_shipping_address_type.py new file mode 100644 index 0000000..467ccbd --- /dev/null +++ b/src/webflow/types/order_shipping_address_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderShippingAddressType = typing.Union[typing.Literal["shipping", "billing"], typing.Any] diff --git a/src/webflow/types/page.py b/src/webflow/types/page.py index 56b32d3..51346a0 100644 --- a/src/webflow/types/page.py +++ b/src/webflow/types/page.py @@ -80,7 +80,7 @@ class Page(UniversalBaseModel): default=None ) """ - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching). Pages that are already branches cannot be branched again. """ is_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBranch")] = pydantic.Field( @@ -90,11 +90,11 @@ class Page(UniversalBaseModel): Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) """ - is_members_only: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isMembersOnly")] = ( - pydantic.Field(default=None) + branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( + default=None ) """ - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + If the Page is a Branch of another Page, this is the ID of the Branch """ seo: typing.Optional[PageSeo] = pydantic.Field(default=None) diff --git a/src/webflow/types/page_created_webhook.py b/src/webflow/types/page_created_webhook.py new file mode 100644 index 0000000..60ef73e --- /dev/null +++ b/src/webflow/types/page_created_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_created_webhook_payload import PageCreatedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageCreatedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page is created + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageCreatedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_created_webhook_payload.py b/src/webflow/types/page_created_webhook_payload.py new file mode 100644 index 0000000..e986315 --- /dev/null +++ b/src/webflow/types/page_created_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageCreatedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_deleted_webhook.py b/src/webflow/types/page_deleted_webhook.py new file mode 100644 index 0000000..5894078 --- /dev/null +++ b/src/webflow/types/page_deleted_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_deleted_webhook_payload import PageDeletedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageDeletedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page is deleted + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageDeletedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_deleted_webhook_payload.py b/src/webflow/types/page_deleted_webhook_payload.py new file mode 100644 index 0000000..5d09458 --- /dev/null +++ b/src/webflow/types/page_deleted_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageDeletedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + deleted_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="deletedOn")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_metadata_updated_webhook.py b/src/webflow/types/page_metadata_updated_webhook.py new file mode 100644 index 0000000..1bcb1e1 --- /dev/null +++ b/src/webflow/types/page_metadata_updated_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataUpdatedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page's metadata is updated + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageMetadataUpdatedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_metadata_updated_webhook_payload.py b/src/webflow/types/page_metadata_updated_webhook_payload.py new file mode 100644 index 0000000..a75b703 --- /dev/null +++ b/src/webflow/types/page_metadata_updated_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageMetadataUpdatedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/payload.py b/src/webflow/types/payload.py new file mode 100644 index 0000000..a608741 --- /dev/null +++ b/src/webflow/types/payload.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .payload_field_data import PayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Payload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was unpublished + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[typing.Optional[PayloadFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/payload_field_data.py b/src/webflow/types/payload_field_data.py new file mode 100644 index 0000000..6fa4fc5 --- /dev/null +++ b/src/webflow/types/payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class PayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_field_data.py b/src/webflow/types/product_field_data.py index e58b83d..e907159 100644 --- a/src/webflow/types/product_field_data.py +++ b/src/webflow/types/product_field_data.py @@ -43,9 +43,9 @@ class ProductFieldData(UniversalBaseModel): Variant types to include in SKUs """ - categories: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + category: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ - The categories your product belongs to. + The category your product belongs to. """ tax_category: typing_extensions.Annotated[ diff --git a/src/webflow/types/reference_field.py b/src/webflow/types/reference_field.py new file mode 100644 index 0000000..3c75552 --- /dev/null +++ b/src/webflow/types/reference_field.py @@ -0,0 +1,62 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .reference_field_type import ReferenceFieldType +from .reference_field_metadata import ReferenceFieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ReferenceField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: ReferenceFieldType = pydantic.Field() + """ + Choose these appropriate field type for your collection data + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + metadata: ReferenceFieldMetadata = pydantic.Field() + """ + The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/reference_field_metadata.py b/src/webflow/types/reference_field_metadata.py new file mode 100644 index 0000000..164c4a6 --- /dev/null +++ b/src/webflow/types/reference_field_metadata.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class ReferenceFieldMetadata(UniversalBaseModel): + """ + The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. + """ + + collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() + """ + The unique identifier of the collection + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/reference_field_type.py b/src/webflow/types/reference_field_type.py new file mode 100644 index 0000000..b80f3e1 --- /dev/null +++ b/src/webflow/types/reference_field_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ReferenceFieldType = typing.Union[typing.Literal["MultiReference", "Reference"], typing.Any] diff --git a/src/webflow/types/registered_script_list.py b/src/webflow/types/registered_script_list.py index ddfff8d..e9d8a01 100644 --- a/src/webflow/types/registered_script_list.py +++ b/src/webflow/types/registered_script_list.py @@ -5,6 +5,7 @@ import typing from .custom_code_hosted_response import CustomCodeHostedResponse from ..core.serialization import FieldMetadata +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -17,6 +18,7 @@ class RegisteredScriptList(UniversalBaseModel): registered_scripts: typing_extensions.Annotated[ typing.Optional[typing.List[CustomCodeHostedResponse]], FieldMetadata(alias="registeredScripts") ] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/robots.py b/src/webflow/types/robots.py new file mode 100644 index 0000000..7489660 --- /dev/null +++ b/src/webflow/types/robots.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .robots_rules_item import RobotsRulesItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Robots(UniversalBaseModel): + """ + The robots.txt file for a given site + """ + + rules: typing.Optional[typing.List[RobotsRulesItem]] = pydantic.Field(default=None) + """ + List of rules for user agents. + """ + + sitemap: typing.Optional[str] = pydantic.Field(default=None) + """ + URL to the sitemap. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/robots_rules_item.py b/src/webflow/types/robots_rules_item.py new file mode 100644 index 0000000..048f239 --- /dev/null +++ b/src/webflow/types/robots_rules_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class RobotsRulesItem(UniversalBaseModel): + user_agent: typing_extensions.Annotated[str, FieldMetadata(alias="userAgent")] = pydantic.Field() + """ + The user agent the rules apply to. + """ + + allows: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + List of paths allowed for this user agent. + """ + + disallows: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + List of paths disallowed for this user agent. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node_write.py b/src/webflow/types/search_button.py similarity index 75% rename from src/webflow/types/text_node_write.py rename to src/webflow/types/search_button.py index a16c800..10e83ce 100644 --- a/src/webflow/types/text_node_write.py +++ b/src/webflow/types/search_button.py @@ -8,9 +8,9 @@ import typing -class TextNodeWrite(UniversalBaseModel): +class SearchButton(UniversalBaseModel): """ - Update a text node + Update a search button node """ node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() @@ -18,9 +18,9 @@ class TextNodeWrite(UniversalBaseModel): Node UUID """ - text: str = pydantic.Field() + value: 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. + The text content of the search button. """ if IS_PYDANTIC_V2: diff --git a/src/webflow/types/search_button_node_dom.py b/src/webflow/types/search_button_node_dom.py new file mode 100644 index 0000000..f2e002e --- /dev/null +++ b/src/webflow/types/search_button_node_dom.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SearchButtonNodeDom(UniversalBaseModel): + """ + Represents search button elements within the DOM. It contains the text of the button. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + value: str = pydantic.Field() + """ + The text content of the search button. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select.py b/src/webflow/types/select.py new file mode 100644 index 0000000..7208091 --- /dev/null +++ b/src/webflow/types/select.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from .select_node_write_choices_item import SelectNodeWriteChoicesItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Select(UniversalBaseModel): + """ + Update choices on a select node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + choices: typing.List[SelectNodeWriteChoicesItem] = pydantic.Field() + """ + The list of choices to set on the select node. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node_choices_item.py b/src/webflow/types/select_node_choices_item.py new file mode 100644 index 0000000..cd210b1 --- /dev/null +++ b/src/webflow/types/select_node_choices_item.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SelectNodeChoicesItem(UniversalBaseModel): + value: str = pydantic.Field() + """ + The value of the choice when selected. + """ + + text: str = pydantic.Field() + """ + The text to display for the choice. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node_dom.py b/src/webflow/types/select_node_dom.py new file mode 100644 index 0000000..4e8ede8 --- /dev/null +++ b/src/webflow/types/select_node_dom.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from .select_node_choices_item import SelectNodeChoicesItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SelectNodeDom(UniversalBaseModel): + """ + Represents select elements within the DOM. It contains the list of choices in the select. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + choices: typing.List[SelectNodeChoicesItem] = pydantic.Field() + """ + The list of choices in this select node. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node_write_choices_item.py b/src/webflow/types/select_node_write_choices_item.py new file mode 100644 index 0000000..4346fef --- /dev/null +++ b/src/webflow/types/select_node_write_choices_item.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SelectNodeWriteChoicesItem(UniversalBaseModel): + value: str = pydantic.Field() + """ + The value of the choice when selected. + """ + + text: str = pydantic.Field() + """ + The text to display for the choice. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/single_locale_created_payload.py b/src/webflow/types/single_locale_created_payload.py new file mode 100644 index 0000000..9293d8c --- /dev/null +++ b/src/webflow/types/single_locale_created_payload.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +import datetime as dt +from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SingleLocaleCreatedPayload(UniversalBaseModel): + id: str = pydantic.Field() + """ + Unique identifier for the Item + """ + + workspace_id: typing_extensions.Annotated[str, FieldMetadata(alias="workspaceId")] = pydantic.Field() + """ + Unique identifier of the workspace + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + Unique identifier of the site + """ + + collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() + """ + Unique identifier of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[SingleLocaleCreatedPayloadFieldData, FieldMetadata(alias="fieldData")] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/single_locale_created_payload_field_data.py b/src/webflow/types/single_locale_created_payload_field_data.py new file mode 100644 index 0000000..b412ef9 --- /dev/null +++ b/src/webflow/types/single_locale_created_payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class SingleLocaleCreatedPayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership.py b/src/webflow/types/site_membership.py new file mode 100644 index 0000000..5ad913f --- /dev/null +++ b/src/webflow/types/site_membership.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite +import typing_extensions +from .workspace_audit_log_item_payload_site_membership_target_user import ( + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod +from .workspace_audit_log_item_payload_site_membership_user_type import ( + WorkspaceAuditLogItemPayloadSiteMembershipUserType, +) +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SiteMembership(UniversalBaseModel): + site: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipSite] = None + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership_audit_log_item.py b/src/webflow/types/site_membership_audit_log_item.py new file mode 100644 index 0000000..d24ee9f --- /dev/null +++ b/src/webflow/types/site_membership_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .site_membership import SiteMembership +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SiteMembershipAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SiteMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership_audit_log_item_event_sub_type.py b/src/webflow/types/site_membership_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..b604b85 --- /dev/null +++ b/src/webflow/types/site_membership_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SiteMembershipAuditLogItemEventSubType = typing.Union[ + typing.Literal["user_added", "user_removed", "user_role_updated"], typing.Any +] diff --git a/src/webflow/types/site_publish.py b/src/webflow/types/site_publish.py new file mode 100644 index 0000000..518178e --- /dev/null +++ b/src/webflow/types/site_publish.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .site_publish_payload import SitePublishPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitePublish(UniversalBaseModel): + """ + The Webhook payload for when a Site is published + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[SitePublishPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_publish_payload.py b/src/webflow/types/site_publish_payload.py new file mode 100644 index 0000000..f44882e --- /dev/null +++ b/src/webflow/types/site_publish_payload.py @@ -0,0 +1,50 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitePublishPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site that was published + """ + + published_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="publishedOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp of the publish event + """ + + domains: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + The domains that were published + """ + + published_by: typing_extensions.Annotated[ + typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="publishedBy") + ] = pydantic.Field(default=None) + """ + The name andID of the user who published the site + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data.py b/src/webflow/types/sku_field_data.py index e20efdb..c7540d8 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -10,6 +10,7 @@ from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan +from .sku_property_list import SkuPropertyList from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -43,20 +44,35 @@ class SkuFieldData(UniversalBaseModel): ec_sku_billing_method: typing_extensions.Annotated[ typing.Optional[SkuFieldDataEcSkuBillingMethod], FieldMetadata(alias="ec-sku-billing-method") - ] = None + ] = pydantic.Field(default=None) + """ + [Billing method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for the SKU + """ + ec_sku_subscription_plan: typing_extensions.Annotated[ typing.Optional[SkuFieldDataEcSkuSubscriptionPlan], FieldMetadata(alias="ec-sku-subscription-plan") - ] = None - track_inventory: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="track-inventory")] = ( - pydantic.Field(default=None) + ] = pydantic.Field(default=None) + """ + [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU + """ + + main_image: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="main-image")] = pydantic.Field( + default=None ) """ - A boolean indicating whether inventory for this product should be tracked. + The URL for the main image of the SKU + """ + + sku: typing.Optional[str] = pydantic.Field(default=None) + """ + A unique identifier for the SKU """ - quantity: typing.Optional[float] = pydantic.Field(default=None) + sku_properties: typing_extensions.Annotated[ + typing.Optional[typing.List[SkuPropertyList]], FieldMetadata(alias="sku-properties") + ] = pydantic.Field(default=None) """ - Quantity of SKU that will be tracked as items are ordered. + The properties of the SKU """ if IS_PYDANTIC_V2: diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py index 24c85a7..ed2e484 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py @@ -9,6 +9,10 @@ class SkuFieldDataEcSkuSubscriptionPlan(UniversalBaseModel): + """ + [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU + """ + interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic.Field(default=None) """ Interval of subscription renewal diff --git a/src/webflow/types/sku_field_data_price.py b/src/webflow/types/sku_field_data_price.py index 45ff611..cb31f4a 100644 --- a/src/webflow/types/sku_field_data_price.py +++ b/src/webflow/types/sku_field_data_price.py @@ -21,6 +21,11 @@ class SkuFieldDataPrice(UniversalBaseModel): Currency of Item """ + currency: typing.Optional[str] = pydantic.Field(default=None) + """ + Currency of Item (alternative representation) + """ + if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 else: diff --git a/src/webflow/types/static_field.py b/src/webflow/types/static_field.py new file mode 100644 index 0000000..c6e6162 --- /dev/null +++ b/src/webflow/types/static_field.py @@ -0,0 +1,56 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .static_field_type import StaticFieldType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class StaticField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: StaticFieldType = pydantic.Field() + """ + Choose these appropriate field type for your collection data + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/fields/types/field_create_type.py b/src/webflow/types/static_field_type.py similarity index 82% rename from src/webflow/resources/collections/resources/fields/types/field_create_type.py rename to src/webflow/types/static_field_type.py index c8ec44b..e7cadf0 100644 --- a/src/webflow/resources/collections/resources/fields/types/field_create_type.py +++ b/src/webflow/types/static_field_type.py @@ -2,12 +2,11 @@ import typing -FieldCreateType = typing.Union[ +StaticFieldType = typing.Union[ typing.Literal[ "Color", "DateTime", "Email", - "ExtFileRef", "File", "Image", "Link", @@ -17,7 +16,7 @@ "PlainText", "RichText", "Switch", - "Video", + "VideoLink", ], typing.Any, ] diff --git a/src/webflow/types/submit_button.py b/src/webflow/types/submit_button.py new file mode 100644 index 0000000..158759b --- /dev/null +++ b/src/webflow/types/submit_button.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SubmitButton(UniversalBaseModel): + """ + Update a submit button node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + value: typing.Optional[str] = pydantic.Field(default=None) + """ + The text content of the submit button. + """ + + waiting_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="waitingText")] = ( + pydantic.Field(default=None) + ) + """ + The text to show while the form is submitting. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/submit_button_node_dom.py b/src/webflow/types/submit_button_node_dom.py new file mode 100644 index 0000000..8cf770f --- /dev/null +++ b/src/webflow/types/submit_button_node_dom.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SubmitButtonNodeDom(UniversalBaseModel): + """ + Represents submit button elements within the DOM. It contains the text and waiting text of the button. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + value: str = pydantic.Field() + """ + The text content of the submit button. + """ + + waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] = pydantic.Field() + """ + The text to show while the form is submitting. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text.py b/src/webflow/types/text.py index 18f8501..913d5d1 100644 --- a/src/webflow/types/text.py +++ b/src/webflow/types/text.py @@ -7,6 +7,10 @@ class Text(UniversalBaseModel): + """ + The text content of the node + """ + html: typing.Optional[str] = pydantic.Field(default=None) """ The HTML content of the text node. diff --git a/src/webflow/types/text_input.py b/src/webflow/types/text_input.py new file mode 100644 index 0000000..80e4037 --- /dev/null +++ b/src/webflow/types/text_input.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 TextInput(UniversalBaseModel): + """ + Update placeholder text on a text input node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + placeholder: str = pydantic.Field() + """ + The placeholder text of the input node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_input_node_dom.py b/src/webflow/types/text_input_node_dom.py new file mode 100644 index 0000000..ce85da6 --- /dev/null +++ b/src/webflow/types/text_input_node_dom.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class TextInputNodeDom(UniversalBaseModel): + """ + Represents text input and textarea elements within the DOM. It contains the placeholder text in the input. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + placeholder: str = pydantic.Field() + """ + The placeholder text of the input node + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node.py b/src/webflow/types/text_node.py index 1e16717..64774c9 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -1,26 +1,26 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing +import typing_extensions +from ..core.serialization import FieldMetadata import pydantic -from .text_node_text import TextNodeText from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing class TextNode(UniversalBaseModel): """ - Represents text content within the DOM. It contains both the raw text and its HTML representation. Additional attributes can be associated with the text for styling or other purposes. + Update a text node """ - id: typing.Optional[str] = pydantic.Field(default=None) + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() """ Node UUID """ - text: typing.Optional[TextNodeText] = None - attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + text: str = pydantic.Field() """ - The custom attributes of the node + 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: diff --git a/src/webflow/types/text_node_dom.py b/src/webflow/types/text_node_dom.py new file mode 100644 index 0000000..6e238dc --- /dev/null +++ b/src/webflow/types/text_node_dom.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from .text_node_text import TextNodeText +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class TextNodeDom(UniversalBaseModel): + """ + Represents text content within the DOM. It contains both the raw text and its HTML representation. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + text: TextNodeText = pydantic.Field() + """ + The text content of the node + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: 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_text.py b/src/webflow/types/text_node_text.py index 895dc0b..5add2f0 100644 --- a/src/webflow/types/text_node_text.py +++ b/src/webflow/types/text_node_text.py @@ -7,6 +7,10 @@ class TextNodeText(UniversalBaseModel): + """ + The text content of the node + """ + html: typing.Optional[str] = pydantic.Field(default=None) """ The HTML content of the text node. diff --git a/src/webflow/types/trigger_type.py b/src/webflow/types/trigger_type.py index e12b650..6540e4b 100644 --- a/src/webflow/types/trigger_type.py +++ b/src/webflow/types/trigger_type.py @@ -18,7 +18,9 @@ "collection_item_created", "collection_item_changed", "collection_item_deleted", + "collection_item_published", "collection_item_unpublished", + "comment_created", ], typing.Any, ] diff --git a/src/webflow/types/updated_order.py b/src/webflow/types/updated_order.py new file mode 100644 index 0000000..a3fc241 --- /dev/null +++ b/src/webflow/types/updated_order.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .order import Order +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UpdatedOrder(UniversalBaseModel): + """ + The Webhook payload for when an order is updated + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Order] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user.py b/src/webflow/types/user.py index a27a063..d6c3ade 100644 --- a/src/webflow/types/user.py +++ b/src/webflow/types/user.py @@ -57,11 +57,7 @@ class User(UniversalBaseModel): The timestamp the user was logged in """ - status: typing.Optional[UserStatus] = pydantic.Field(default=None) - """ - The status of the user - """ - + status: typing.Optional[UserStatus] = None access_groups: typing_extensions.Annotated[ typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") ] = pydantic.Field(default=None) diff --git a/src/webflow/types/user_access.py b/src/webflow/types/user_access.py new file mode 100644 index 0000000..7c869dd --- /dev/null +++ b/src/webflow/types/user_access.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UserAccess(UniversalBaseModel): + method: typing.Optional[WorkspaceAuditLogItemPayloadUserAccessMethod] = None + location: typing.Optional[str] = pydantic.Field(default=None) + """ + The geolocation based on the logged IP address + """ + + ip_address: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ipAddress")] = pydantic.Field( + default=None + ) + """ + The captured IP address of the user + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_audit_log_item.py b/src/webflow/types/user_access_audit_log_item.py new file mode 100644 index 0000000..b94e6a7 --- /dev/null +++ b/src/webflow/types/user_access_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .user_access import UserAccess +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccessAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[UserAccess] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_audit_log_item_event_sub_type.py b/src/webflow/types/user_access_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..382f247 --- /dev/null +++ b/src/webflow/types/user_access_audit_log_item_event_sub_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +UserAccessAuditLogItemEventSubType = typing.Union[typing.Literal["login", "logout"], typing.Any] diff --git a/src/webflow/types/webhook_list.py b/src/webflow/types/webhook_list.py index ea705c4..1740272 100644 --- a/src/webflow/types/webhook_list.py +++ b/src/webflow/types/webhook_list.py @@ -2,15 +2,15 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing -from .pagination import Pagination from .webhook import Webhook +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic class WebhookList(UniversalBaseModel): - pagination: typing.Optional[Pagination] = None webhooks: typing.Optional[typing.List[Webhook]] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/workspace_audit_log_item.py b/src/webflow/types/workspace_audit_log_item.py new file mode 100644 index 0000000..4f95a56 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item.py @@ -0,0 +1,141 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor +from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType +from .user_access import UserAccess +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType +from .custom_role import CustomRole +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +from .workspace_membership import WorkspaceMembership +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from .site_membership import SiteMembership +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .workspace_invitation import WorkspaceInvitation + + +class Base(UniversalBaseModel): + timestamp: typing.Optional[dt.datetime] = None + actor: typing.Optional[WorkspaceAuditLogItemActor] = None + workspace: typing.Optional[WorkspaceAuditLogItemWorkspace] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_UserAccess(Base): + event_type: typing_extensions.Annotated[typing.Literal["user_access"], FieldMetadata(alias="eventType")] = ( + "user_access" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[UserAccess] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_CustomRole(Base): + event_type: typing_extensions.Annotated[typing.Literal["custom_role"], FieldMetadata(alias="eventType")] = ( + "custom_role" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[CustomRole] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_WorkspaceMembership(Base): + event_type: typing_extensions.Annotated[ + typing.Literal["workspace_membership"], FieldMetadata(alias="eventType") + ] = "workspace_membership" + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_SiteMembership(Base): + event_type: typing_extensions.Annotated[typing.Literal["site_membership"], FieldMetadata(alias="eventType")] = ( + "site_membership" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SiteMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_WorkspaceInvitation(Base): + event_type: typing_extensions.Annotated[ + typing.Literal["workspace_invitation"], FieldMetadata(alias="eventType") + ] = "workspace_invitation" + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceInvitation] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +WorkspaceAuditLogItem = typing.Union[ + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_WorkspaceInvitation, +] diff --git a/src/webflow/types/workspace_audit_log_item_actor.py b/src/webflow/types/workspace_audit_log_item_actor.py new file mode 100644 index 0000000..7da609c --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_actor.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemActor(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py new file mode 100644 index 0000000..8dbb6ad --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadSiteMembershipMethod = typing.Union[ + typing.Literal["sso", "invite", "scim", "dashboard", "admin"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py new file mode 100644 index 0000000..6d392bd --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadSiteMembershipSite(UniversalBaseModel): + id: typing.Optional[str] = None + slug: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py new file mode 100644 index 0000000..bcfc37b --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadSiteMembershipTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py new file mode 100644 index 0000000..47b5168 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadSiteMembershipUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py b/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py new file mode 100644 index 0000000..5417cff --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadUserAccessMethod = typing.Union[ + typing.Literal["dashboard", "sso", "api", "google"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py new file mode 100644 index 0000000..79a3042 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod = typing.Union[ + typing.Literal["sso", "dashboard", "admin"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py new file mode 100644 index 0000000..1360978 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py new file mode 100644 index 0000000..980d3a9 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py new file mode 100644 index 0000000..a86a23c --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod = typing.Union[ + typing.Literal["sso", "dashboard", "admin"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py new file mode 100644 index 0000000..6ce0f6a --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py new file mode 100644 index 0000000..dad636f --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_workspace.py b/src/webflow/types/workspace_audit_log_item_workspace.py new file mode 100644 index 0000000..6c13bf5 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_workspace.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemWorkspace(UniversalBaseModel): + id: typing.Optional[str] = None + slug: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_response.py b/src/webflow/types/workspace_audit_log_response.py new file mode 100644 index 0000000..f6d0d13 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item import WorkspaceAuditLogItem +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogResponse(UniversalBaseModel): + items: typing.Optional[typing.List[WorkspaceAuditLogItem]] = None + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation.py b/src/webflow/types/workspace_invitation.py new file mode 100644 index 0000000..0bfa99e --- /dev/null +++ b/src/webflow/types/workspace_invitation.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_workspace_invitation_method import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, +) +from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +) +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class WorkspaceInvitation(UniversalBaseModel): + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation_audit_log_item.py b/src/webflow/types/workspace_invitation_audit_log_item.py new file mode 100644 index 0000000..e41f504 --- /dev/null +++ b/src/webflow/types/workspace_invitation_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .workspace_invitation import WorkspaceInvitation +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceInvitationAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceInvitation] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py b/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..821fd81 --- /dev/null +++ b/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceInvitationAuditLogItemEventSubType = typing.Union[ + typing.Literal["invite_sent", "invite_accepted", "invite_updated", "invite_canceled", "invite_declined"], typing.Any +] diff --git a/src/webflow/types/workspace_membership.py b/src/webflow/types/workspace_membership.py new file mode 100644 index 0000000..1c369a2 --- /dev/null +++ b/src/webflow/types/workspace_membership.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_workspace_membership_method import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, +) +from .workspace_audit_log_item_payload_workspace_membership_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, +) +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class WorkspaceMembership(UniversalBaseModel): + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_membership_audit_log_item.py b/src/webflow/types/workspace_membership_audit_log_item.py new file mode 100644 index 0000000..4ac92d7 --- /dev/null +++ b/src/webflow/types/workspace_membership_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .workspace_membership import WorkspaceMembership +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceMembershipAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py b/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..4d90d7a --- /dev/null +++ b/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceMembershipAuditLogItemEventSubType = typing.Union[ + typing.Literal["user_added", "user_removed", "user_role_updated"], typing.Any +] diff --git a/tests/collections/test_fields.py b/tests/collections/test_fields.py index f64c447..dc18ff3 100644 --- a/tests/collections/test_fields.py +++ b/tests/collections/test_fields.py @@ -3,43 +3,50 @@ from webflow import Webflow from webflow import AsyncWebflow import typing +from webflow import StaticField from ..utilities import validate_response async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "75821f618da60c18383330bcc0ca488b", - "isRequired": False, + "id": "562ac0395358780a1f5e6fbc", "isEditable": True, + "isRequired": False, "type": "RichText", - "slug": "post-body", "displayName": "Post Body", "helpText": "Add the body of your post here", } expected_types: typing.Any = { "id": None, - "isRequired": None, "isEditable": None, + "isRequired": None, "type": None, - "slug": None, "displayName": None, "helpText": None, } response = client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) validate_response(async_response, expected_response, expected_types) @@ -68,6 +75,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "slug": "post-body", "displayName": "Post Body", "helpText": "Add the body of your post here", + "validations": {"additionalProperties": "additionalProperties"}, } expected_types: typing.Any = { "id": None, @@ -77,6 +85,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, + "validations": {"additionalProperties": None}, } response = client.collections.fields.update( collection_id="580e63fc8c9a982ac9b8b745", diff --git a/tests/collections/test_items.py b/tests/collections/test_items.py index fc926a7..ded27e7 100644 --- a/tests/collections/test_items.py +++ b/tests/collections/test_items.py @@ -6,12 +6,15 @@ from ..utilities import validate_response from webflow import CollectionItemPostSingle from webflow import CollectionItemPostSingleFieldData +from webflow.resources.collections.resources.items import ItemsDeleteItemsRequestItemsItem from webflow import CollectionItemWithIdInput from webflow import CollectionItemWithIdInputFieldData from webflow import CollectionItem from webflow import CollectionItemFieldData +from webflow.resources.collections.resources.items import ItemsDeleteItemsLiveRequestItemsItem from webflow.resources.collections.resources.items import SingleCmsItem from webflow import CollectionItemPatchSingleFieldData +from webflow.resources.collections.resources.items import ItemIDs async def test_list_items(client: Webflow, async_client: AsyncWebflow) -> None: @@ -140,42 +143,123 @@ async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: async def test_delete_items(client: Webflow, async_client: AsyncWebflow) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( - client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) assert ( - await async_client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + await async_client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) async def test_update_items(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "id", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35.560Z", - "lastUpdated": "2023-03-17T18:47:35.560Z", - "createdOn": "2023-03-17T18:47:35.560Z", - "isArchived": True, - "isDraft": True, - "fieldData": { - "name": "My new item", - "slug": "my-new-item", - "date": "2022-11-18T00:00:00.000Z", - "featured": False, - "color": "#db4b68", - }, + "items": [ + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Au Revoir et Merci pour Tous les Poissons", + "slug": "au-revoir-et-merci", + "featured": False, + }, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Hasta Luego y Gracias por Todo el Pescado", + "slug": "hasta-luego-y-gracias", + "featured": False, + }, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 4}, } expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, + "items": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 2: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 3: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, } response = client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", @@ -366,12 +450,18 @@ async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> async def test_delete_items_live(client: Webflow, async_client: AsyncWebflow) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( - client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) assert ( - await async_client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + await async_client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) @@ -382,31 +472,31 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> { "id": "66f6ed9576ddacf3149d5ea6", "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, }, { "id": "66f6ed9576ddacf3149d5ea6", "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, }, { "id": "66f6ed9576ddacf3149d5eaa", "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": { "name": "Au Revoir et Merci pour Tous les Poissons", "slug": "au-revoir-et-merci", @@ -416,11 +506,11 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> { "id": "66f6ed9576ddacf3149d5eaa", "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": { "name": "Hasta Luego y Gracias por Todo el Pescado", "slug": "hasta-luego-y-gracias", @@ -801,10 +891,14 @@ async def test_publish_item(client: Webflow, async_client: AsyncWebflow) -> None "errors": ["Staging item ID 643fd856d66b6528195ee2cf not found."], } expected_types: typing.Any = {"publishedItemIds": ("list", {0: None, 1: None}), "errors": ("list", {0: None})} - response = client.collections.items.publish_item(collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"]) + response = client.collections.items.publish_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), + ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.items.publish_item( - collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"] + collection_id="580e63fc8c9a982ac9b8b745", + request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/conftest.py b/tests/conftest.py index 019aab8..8d87434 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ from webflow import Webflow import os +from webflow.environment import WebflowEnvironment import pytest from webflow import AsyncWebflow @@ -9,12 +10,26 @@ @pytest.fixture def client() -> Webflow: return Webflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), + environment=WebflowEnvironment( + base=os.getenv("TESTS_BASE_URL", "base_url"), + data_api=os.getenv("TESTS_BASE_URL", "base_url"), + content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), + production=os.getenv("TESTS_BASE_URL", "base_url"), + cdn=os.getenv("TESTS_BASE_URL", "base_url"), + ), ) @pytest.fixture def async_client() -> AsyncWebflow: return AsyncWebflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), + environment=WebflowEnvironment( + base=os.getenv("TESTS_BASE_URL", "base_url"), + data_api=os.getenv("TESTS_BASE_URL", "base_url"), + content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), + production=os.getenv("TESTS_BASE_URL", "base_url"), + cdn=os.getenv("TESTS_BASE_URL", "base_url"), + ), ) diff --git a/tests/sites/test_activity_logs.py b/tests/sites/test_activity_logs.py index f289464..722a4f2 100644 --- a/tests/sites/test_activity_logs.py +++ b/tests/sites/test_activity_logs.py @@ -18,9 +18,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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}, @@ -38,9 +35,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "user": {"id": None, "displayName": None}, "resourceId": None, "resourceName": None, - "newValue": None, - "previousValue": None, - "payload": ("dict", {0: (None, None)}), } }, ), diff --git a/tests/sites/test_comments.py b/tests/sites/test_comments.py new file mode 100644 index 0000000..2be436d --- /dev/null +++ b/tests/sites/test_comments.py @@ -0,0 +1,212 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_list_comment_threads(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "comments": [ + { + "id": "679d2ddb5196117ad04d1ffa", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "Let's go to the pub! [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": { + "userId": "6287ec36a841b25637c663df", + "email": "ford.prefect@heartofgold.spaceship", + "name": "Ford Prefect", + }, + "mentionedUsers": [ + { + "userId": "6287ec36a841b25637c663df", + "email": "arthur.dent@heartofgold.spaceship", + "name": "Arthur Dent", + } + ], + "createdOn": "2025-01-31T20:08:59.759Z", + "lastUpdated": "2025-01-31T20:08:59.759Z", + }, + { + "id": "679d2ddb5196117ad04d1ffc", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "You have five minutes left to drink it [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": { + "userId": "6287ec36a841b25637c663df", + "email": "ford.prefect@heartofgold.spaceship", + "name": "Ford Prefect", + }, + "mentionedUsers": [ + { + "userId": "6287ec36a841b25637c663df", + "email": "arthur.dent@heartofgold.spaceship", + "name": "Arthur Dent", + } + ], + "createdOn": "2025-01-31T20:08:59.759Z", + "lastUpdated": "2025-01-31T20:08:59.759Z", + }, + ], + "pagination": {"limit": 2, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "comments": ( + "list", + { + 0: { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + }, + 1: { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_comment_thread(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e64008c9a982ac9b8b754", + "siteId": "580e64008c9a982ac9b8b754", + "pageId": "580e64008c9a982ac9b8b754", + "localeId": "580e64008c9a982ac9b8b754", + "itemId": "580e64008c9a982ac9b8b754", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "This is a comment reply", + "isResolved": True, + "author": {"userId": "userId", "email": "email", "name": "name"}, + "mentionedUsers": [ + {"userId": "6287ec36a841b25637c663df", "email": "arthur.dent@heartofgold.spaceship", "name": "Arthur Dent"} + ], + "createdOn": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2023-03-17T18:47:35.560Z", + } + expected_types: typing.Any = { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "itemId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + } + response = client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_list_comment_replies(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "comments": [ + { + "id": "679d2ddb5196117ad04d1ffa", + "commentId": "679d2ddb5196117ad04d1ff8", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "breakpoint": "main", + "content": "This comment mentions another user [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": {"id": "id", "email": "email", "name": "name"}, + "mentionedUsers": [{"id": "id", "email": "arthur.dent@example.com", "name": "Arthur Dent"}], + "lastUpdated": "2025-01-31T20:08:59.759Z", + "createdOn": "2025-01-31T20:08:59.759Z", + } + ], + "pagination": {"limit": 2, "offset": 0, "total": 1}, + } + expected_types: typing.Any = { + "comments": ( + "list", + { + 0: { + "id": None, + "commentId": None, + "siteId": None, + "pageId": None, + "localeId": None, + "breakpoint": None, + "content": None, + "isResolved": None, + "author": {"id": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"id": None, "email": None, "name": None}}), + "lastUpdated": None, + "createdOn": None, + } + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_robots_txt.py b/tests/sites/test_robots_txt.py new file mode 100644 index 0000000..cb38204 --- /dev/null +++ b/tests/sites/test_robots_txt.py @@ -0,0 +1,145 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response +from webflow import RobotsRulesItem + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_patch(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_scripts.py b/tests/sites/test_scripts.py index cc5d71c..beb0949 100644 --- a/tests/sites/test_scripts.py +++ b/tests/sites/test_scripts.py @@ -101,7 +101,6 @@ async def test_list_custom_code_blocks(client: Webflow, async_client: AsyncWebfl "blocks": [ { "siteId": "6258612d1ee792848f805dcf", - "pageId": "pageId", "type": "site", "scripts": [ {"id": "chartjs", "location": "header", "version": "4.4.2", "attributes": {"key": "value"}} @@ -126,7 +125,6 @@ async def test_list_custom_code_blocks(client: Webflow, async_client: AsyncWebfl { 0: { "siteId": None, - "pageId": None, "type": None, "scripts": ( "list", diff --git a/tests/sites/test_well_known.py b/tests/sites/test_well_known.py new file mode 100644 index 0000000..feb3609 --- /dev/null +++ b/tests/sites/test_well_known.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow + + +async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.well_known.put(site_id="580e63e98c9a982ac9b8b741", file_name="fileName", file_data="fileData") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", file_name="fileName", file_data="fileData" + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) diff --git a/tests/test_assets.py b/tests/test_assets.py index af158ef..8c9afaa 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -30,9 +30,33 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "quality": 100, } ], - "altText": "A red chair", - } - ] + "altText": "A single candy wrapper", + }, + { + "id": "63e5889e7fe4eafa7384cea5", + "contentType": "image/png", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Gum-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea5_Gum-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", + "variants": [ + { + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, + "height": 900, + "quality": 100, + } + ], + "altText": "A single gum wrapper", + }, + ], + "pagination": {"limit": 2, "offset": 0, "total": 2}, } expected_types: typing.Any = { "assets": ( @@ -63,9 +87,36 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, ), "altText": None, - } + }, + 1: { + "id": None, + "contentType": None, + "size": "integer", + "siteId": None, + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "lastUpdated": "datetime", + "createdOn": "datetime", + "variants": ( + "list", + { + 0: { + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "format": None, + "width": "integer", + "height": "integer", + "quality": "integer", + } + }, + ), + "altText": None, + }, }, - ) + ), + "pagination": {"limit": None, "offset": None, "total": None}, } response = client.assets.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) @@ -94,7 +145,7 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "parentFolder": "6436b1ce5281cace05b65aea", "uploadUrl": "https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", "assetUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png", - "hostedUrl": "https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", + "hostedUrl": "https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", "originalFileName": "file.png", "createdOn": "2023-04-11T16:32:21Z", "lastUpdated": "2023-04-12T20:31:03Z", @@ -136,28 +187,27 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "55131cd036c09f7d07883dfc", + "id": "63e5889e7fe4eafa7384cea4", "contentType": "image/png", - "size": 1500, - "siteId": "62749158efef318abc8d5a0f", - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "example-image-123.png", - "lastUpdated": "2016-09-06T21:12:22Z", - "createdOn": "2016-09-02T23:26:22Z", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Candy-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", "variants": [ { - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "A brown dog", - "format": "format", - "width": 1500, + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, "height": 900, - "quality": 1, - "error": "error", + "quality": 100, } ], - "altText": "A red chair", + "altText": "A single candy wrapper", } expected_types: typing.Any = { "id": None, @@ -180,7 +230,6 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "width": "integer", "height": "integer", "quality": "integer", - "error": None, } }, ), @@ -208,28 +257,27 @@ async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "55131cd036c09f7d07883dfc", + "id": "63e5889e7fe4eafa7384cea4", "contentType": "image/png", - "size": 1500, - "siteId": "62749158efef318abc8d5a0f", - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "example-image-123.png", - "lastUpdated": "2016-09-06T21:12:22Z", - "createdOn": "2016-09-02T23:26:22Z", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Candy-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", "variants": [ { - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "A brown dog", - "format": "format", - "width": 1500, + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, "height": 900, - "quality": 1, - "error": "error", + "quality": 100, } ], - "altText": "A red chair", + "altText": "A single candy wrapper", } expected_types: typing.Any = { "id": None, @@ -252,7 +300,6 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "width": "integer", "height": "integer", "quality": "integer", - "error": None, } }, ), @@ -271,7 +318,6 @@ async def test_list_folders(client: Webflow, async_client: AsyncWebflow) -> None { "id": "6390c49774a71f0e3c1a08ee", "displayName": "emoji icons", - "parentFolder": "6390c49774a71f99f21a08eb", "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], "siteId": "6390c49674a71f84b51a08d8", "createdOn": "2018-10-14T21:55:49Z", @@ -287,7 +333,6 @@ async def test_list_folders(client: Webflow, async_client: AsyncWebflow) -> None 0: { "id": None, "displayName": None, - "parentFolder": None, "assets": ("list", {0: None, 1: None}), "siteId": None, "createdOn": "datetime", diff --git a/tests/test_collections.py b/tests/test_collections.py index 1e76945..1395cbd 100644 --- a/tests/test_collections.py +++ b/tests/test_collections.py @@ -4,6 +4,9 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response +from webflow import StaticField +from webflow import ReferenceField +from webflow import ReferenceFieldMetadata async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: @@ -75,22 +78,40 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", + "id": "562ac0395358780a1f5e6fbd", "displayName": "Blog Posts", "singularName": "Blog Post", - "slug": "post", + "slug": "posts", "createdOn": "2016-10-24T19:41:48Z", "lastUpdated": "2016-10-24T19:42:38Z", "fields": [ { - "id": "23cc2d952d4e4631ffd4345d2743db4e", + "id": "id", "isRequired": True, "isEditable": True, "type": "PlainText", - "slug": "name", - "displayName": "Name", - "helpText": "helpText", - } + "slug": "title", + "displayName": "Title", + "helpText": "The title of the blog post", + }, + { + "id": "id", + "isRequired": True, + "isEditable": True, + "type": "RichText", + "slug": "content", + "displayName": "Content", + "helpText": "The content of the blog post", + }, + { + "id": "id", + "isRequired": True, + "isEditable": True, + "type": "Reference", + "slug": "author", + "displayName": "Author", + "helpText": "The author of the blog post", + }, ], } expected_types: typing.Any = { @@ -111,39 +132,234 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, - } + }, + 1: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 2: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, }, ), } response = client.collections.create( - site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", + fields=[ + StaticField( + is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" + ), + StaticField( + is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), + ), + ], ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.create( - site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", + fields=[ + StaticField( + is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" + ), + StaticField( + is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), + ), + ], ) validate_response(async_response, expected_response, expected_types) async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", - "displayName": "Blog Posts", - "singularName": "Blog Post", - "slug": "post", - "createdOn": "2016-10-24T19:41:48Z", - "lastUpdated": "2016-10-24T19:42:38Z", + "id": "7f15043107e2fc95644e93807ee25dd6", + "displayName": "Guide Entries", + "singularName": "Guide Entry", + "slug": "guide-entry", + "createdOn": "2024-04-12T12:42:00Z", + "lastUpdated": "2024-04-12T12:42:00Z", "fields": [ { - "id": "23cc2d952d4e4631ffd4345d2743db4e", + "id": "5e2a1b3c4d5e6f7890a1b2c3", "isRequired": True, "isEditable": True, "type": "PlainText", "slug": "name", - "displayName": "Name", - "helpText": "helpText", - } + "displayName": "Entry Title", + "helpText": "Name of the entry.", + }, + { + "id": "5e2a1b3c4d5e6f7890a1b2c4", + "isRequired": True, + "isEditable": True, + "type": "PlainText", + "slug": "slug", + "displayName": "Slug", + "helpText": "Slug of the entry.", + }, + { + "id": "6f7e8d9c0b1a2e3d4c5b6a7f", + "isRequired": False, + "isEditable": True, + "type": "PlainText", + "slug": "summary", + "displayName": "Summary", + "helpText": "A short summary of the entry.", + }, + { + "id": "1a2b3c4d5e6f7a8b9c0d1e2f", + "isRequired": False, + "isEditable": True, + "type": "RichText", + "slug": "entry-html", + "displayName": "Entry HTML", + "helpText": "The HTML content of the entry.", + }, + { + "id": "7e8d9c0b1a2e3d4c5b6a7f8e", + "isRequired": False, + "isEditable": True, + "type": "Image", + "slug": "illustration-image", + "displayName": "Illustration Image", + "helpText": "An image of the entry.", + }, + { + "id": "2f3e4d5c6b7a8e9d0c1b2a3f", + "isRequired": False, + "isEditable": True, + "type": "VideoLink", + "slug": "demonstration-video", + "displayName": "Demonstration Video", + "helpText": "A video of the entry.", + }, + { + "id": "8e9d0c1b2a3f4e5d6c7b8a9e", + "isRequired": False, + "isEditable": True, + "type": "Link", + "slug": "more-info-link", + "displayName": "More Info Link", + "helpText": "A link to more information about the entry.", + }, + { + "id": "3f4e5d6c7b8a9e0d1c2b3a4f", + "isRequired": False, + "isEditable": True, + "type": "Number", + "slug": "importance-level", + "displayName": "Importance Level", + "helpText": "The importance level of the entry.", + }, + { + "id": "9e0d1c2b3a4f5e6d7c8b9a0e", + "isRequired": False, + "isEditable": True, + "type": "Switch", + "slug": "is-essential", + "displayName": "Is Essential", + "helpText": "Is this entry essential?", + }, + { + "id": "4f5e6d7c8b9a0e1d2c3b4a5f", + "isRequired": False, + "isEditable": True, + "type": "Color", + "slug": "first-mentioned", + "displayName": "First Mentioned", + "helpText": "Date of the first mention of the subject.", + }, + { + "id": "0e1d2c3b4a5f6e7d8c9b0a1e", + "isRequired": False, + "isEditable": True, + "type": "Color", + "slug": "towel-color", + "displayName": "Towel Color", + "helpText": "The color of the towel.", + }, + { + "id": "5f6e7d8c9b0a1e2d3c4b5a6f", + "isRequired": False, + "isEditable": True, + "type": "Reference", + "slug": "related-entry", + "displayName": "Related Entry", + "helpText": "A related entry.", + }, + { + "id": "1e2d3c4b5a6f7e8d9c0b1a2f", + "isRequired": False, + "isEditable": True, + "type": "MultiReference", + "slug": "mentioned-in-entries", + "displayName": "Mentioned In Entries", + "helpText": "Entries that mention this subject.", + }, + { + "id": "6f7e8d9c0b1a2e3d4c5b6a8f", + "isRequired": False, + "isEditable": True, + "type": "Option", + "slug": "item-type", + "displayName": "Item Type", + "helpText": "The type of item.", + }, + { + "id": "2e3d4c5b6a7f8e9d0c1b2a4f", + "isRequired": False, + "isEditable": True, + "type": "File", + "slug": "guide-file", + "displayName": "Guide File", + }, + { + "id": "7f8e9d0c1b2a3f4e5d6c8b9e", + "isRequired": False, + "isEditable": True, + "type": "Email", + "slug": "contributor-email", + "displayName": "Contributor Email", + }, + { + "id": "3a4f5e6d7c8b9a0e1d2c4b5f", + "isRequired": False, + "isEditable": True, + "type": "Phone", + "slug": "emergency-contact", + "displayName": "Emergency Contact", + }, ], } expected_types: typing.Any = { @@ -164,7 +380,148 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, - } + }, + 1: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 2: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 3: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 4: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 5: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 6: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 7: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 8: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 9: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 10: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 11: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 12: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 13: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 14: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + }, + 15: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + }, + 16: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + }, }, ), } diff --git a/tests/test_components.py b/tests/test_components.py index 2f5a42d..9900c72 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -4,8 +4,12 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response -from webflow import TextNodeWrite -from webflow import ComponentInstanceNodePropertyOverridesWrite +from webflow import TextNode +from webflow import Select +from webflow import SelectNodeWriteChoicesItem +from webflow import TextInput +from webflow import SubmitButton +from webflow import ComponentInstance from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem from webflow.resources.components import ComponentPropertiesWritePropertiesItem @@ -27,20 +31,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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, - }, + {"id": "6258612d1ee792848f805dcf", "name": "Card", "readonly": True}, + {"id": "68a2b1d1ee792848f805dcf", "name": "Nav", "readonly": True}, ], "pagination": {"limit": 20, "offset": 0, "total": 4}, } @@ -50,16 +42,18 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: { 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}, + 2: {"id": None, "name": None, "readonly": None}, + 3: {"id": None, "name": None, "readonly": None}, }, ), "pagination": {"limit": None, "offset": None, "total": None}, } - response = client.components.list(site_id="580e63e98c9a982ac9b8b741") + response = client.components.list(site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833") validate_response(response, expected_response, expected_types) - async_response = await async_client.components.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.components.list( + site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833" + ) validate_response(async_response, expected_response, expected_types) @@ -67,53 +61,53 @@ async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "componentId": "69118560-d0bc-15fc-bbf8-b8fe5f6535b5", "nodes": [ + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, + {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "choices": [{"value": "value", "text": "text"}], + "attributes": {"key": "value"}, + "type": "select", }, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "value": "value", + "waitingText": "waitingText", + "attributes": {"key": "value"}, + "type": "submit-button", }, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", - "componentId": "nodes", + "id": "id", + "componentId": "componentId", "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", - "componentId": "6258612d1ee792848f805dcf", - "propertyOverrides": [ - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", - "type": "Plain Text", - "text": {"text": "Don't Panic!"}, - }, - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", - "type": "Rich Text", - "text": {"html": "

Always know where your towel is.

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

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

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

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInput(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButton(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..."), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -219,6 +234,7 @@ async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> No site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) validate_response(response, expected_response, expected_types) @@ -226,6 +242,7 @@ async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> No site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", ) validate_response(async_response, expected_response, expected_types) @@ -237,6 +254,7 @@ async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" @@ -253,6 +271,7 @@ async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" diff --git a/tests/test_forms.py b/tests/test_forms.py index ee88977..f653d93 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -106,12 +106,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "createdOn": "2016-10-24T19:41:29Z", "lastUpdated": "2016-10-24T19:43:17Z", "fields": { - "660d5bcc9c0772150459dfb1": { - "displayName": "Name", - "type": "Plain", - "placeholder": "Enter your email", - "userVisible": True, - }, + "660d5bcc9c0772150459dfb1": {"displayName": "Name", "type": "Plain", "userVisible": True}, "589a331aa51e760df7ccb89d": { "displayName": "Email", "type": "Email", @@ -122,7 +117,6 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "responseSettings": { "redirectUrl": "https://example.com", "redirectMethod": "GET", - "redirectAction": "POST https://example.com", "sendEmailConfirmation": True, }, "id": "589a331aa51e760df7ccb89e", @@ -140,16 +134,11 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "fields": ( "dict", { - 0: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), + 0: (None, {"displayName": None, "type": None, "userVisible": None}), 1: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), }, ), - "responseSettings": { - "redirectUrl": None, - "redirectMethod": None, - "redirectAction": None, - "sendEmailConfirmation": None, - }, + "responseSettings": {"redirectUrl": None, "redirectMethod": None, "sendEmailConfirmation": None}, "id": None, "siteId": None, "siteDomainId": None, @@ -242,6 +231,19 @@ async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> No validate_response(async_response, expected_response, expected_types) +async def test_delete_submission(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "id": "6321ca84df3949bfc6752327", @@ -264,3 +266,60 @@ async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> async_response = await async_client.forms.update_submission(form_submission_id="580e63e98c9a982ac9b8b741") validate_response(async_response, expected_response, expected_types) + + +async def test_list_submissions_by_site(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "formSubmissions": [ + { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + }, + { + "id": "660d64fabf6e0a0d4edab981", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "formSubmissions": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + 1: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0" + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_inventory.py b/tests/test_inventory.py index a4f1518..95062f9 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -9,11 +9,11 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} - response = client.inventory.list(collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754") + response = client.inventory.list(sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415") validate_response(response, expected_response, expected_types) async_response = await async_client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415" ) validate_response(async_response, expected_response, expected_types) @@ -22,11 +22,11 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} response = client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" ) validate_response(response, expected_response, expected_types) async_response = await async_client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_orders.py b/tests/test_orders.py index a874784..c89ee5f 100644 --- a/tests/test_orders.py +++ b/tests/test_orders.py @@ -15,11 +15,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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"}, @@ -82,7 +77,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -101,7 +96,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "incredible-bronze-towels-sleek-frozen-incredible-metal", "variantSKU": "incredible-bronze-towels-sleek-frozen-incredible-metal", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 83.09 USD"}, "width": 19, @@ -122,14 +117,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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, @@ -160,11 +147,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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"}, @@ -226,7 +209,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -245,7 +228,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -269,14 +252,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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, @@ -328,11 +303,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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}, @@ -437,14 +407,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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, @@ -472,11 +434,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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}, @@ -583,14 +541,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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, @@ -714,7 +664,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -733,7 +683,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -744,12 +694,10 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: ], "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", }, @@ -759,14 +707,6 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "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, @@ -913,24 +853,14 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> 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, @@ -1052,7 +982,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -1071,7 +1001,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -1082,12 +1012,10 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: ], "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", }, @@ -1097,14 +1025,6 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "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, @@ -1251,24 +1171,14 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> 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, @@ -1390,7 +1300,7 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -1409,7 +1319,7 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -1420,12 +1330,10 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No ], "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", }, @@ -1435,14 +1343,6 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "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, @@ -1589,24 +1489,14 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No ), "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, @@ -1728,7 +1618,7 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -1747,7 +1637,7 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -1758,12 +1648,10 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> ], "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", }, @@ -1773,14 +1661,6 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "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, @@ -1927,24 +1807,14 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> ), "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, @@ -2066,7 +1936,7 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, "weight": 11, @@ -2085,7 +1955,7 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, "weight": 38, @@ -2096,12 +1966,10 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: ], "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", }, @@ -2111,14 +1979,6 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "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, @@ -2265,24 +2125,14 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> 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, diff --git a/tests/test_pages.py b/tests/test_pages.py index 716c201..752dc74 100644 --- a/tests/test_pages.py +++ b/tests/test_pages.py @@ -4,11 +4,14 @@ 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.resources.pages import PageMetadataWriteSeo +from webflow.resources.pages import PageMetadataWriteOpenGraph +from webflow import TextNode +from webflow import Select +from webflow import SelectNodeWriteChoicesItem +from webflow import TextInput +from webflow import SubmitButton +from webflow import ComponentInstance from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem @@ -20,15 +23,13 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -47,15 +48,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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.", @@ -81,15 +79,13 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -100,15 +96,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> 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, @@ -133,15 +126,13 @@ async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> None "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, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -160,15 +151,13 @@ async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> 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, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -189,15 +178,13 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) "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, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -216,15 +203,13 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) "siteId": None, "title": None, "slug": None, - "parentId": None, - "collectionId": None, "createdOn": "datetime", "lastUpdated": "datetime", "archived": None, "draft": None, "canBranch": None, "isBranch": None, - "isMembersOnly": None, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -233,56 +218,36 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) response = client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), - last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) validate_response(response, expected_response, expected_types) async_response = await async_client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), - last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) validate_response(async_response, expected_response, expected_types) @@ -290,51 +255,46 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "pageId": "658205daa3e8206a523b5ad4", + "branchId": "68026fa68ef6dc744c75b833", "nodes": [ + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "choices": [{"value": "value", "text": "text"}], + "attributes": {"key": "value"}, + "type": "select", }, + {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", - "componentId": "nodes", + "id": "id", + "componentId": "componentId", "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", - "componentId": "6258612d1ee792848f805dcf", - "propertyOverrides": [ - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", - "type": "Plain Text", - "label": "Catchphrase", - "text": {"text": "Don't Panic!"}, - }, - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", - "type": "Rich Text", - "label": "Tagline", - "text": {"html": "

Always know where your towel is.

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

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInput(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButton(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..."), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( @@ -379,14 +348,23 @@ async def test_update_static_content(client: Webflow, async_client: AsyncWebflow page_id="63c720f9347c2139b248e552", locale_id="localeId", nodes=[ - TextNodeWrite( + TextNode( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

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

Don't Panic!

Always know where your towel is.

", ), - ComponentInstanceNodePropertyOverridesWrite( + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInput(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButton(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..."), + ComponentInstance( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( diff --git a/tests/test_products.py b/tests/test_products.py index 03d28db..ca8a0aa 100644 --- a/tests/test_products.py +++ b/tests/test_products.py @@ -4,7 +4,15 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response +from webflow.resources.products import ProductSkuCreateProduct +from webflow import ProductFieldData +from webflow import SkuPropertyList +from webflow import SkuPropertyListEnumItem +from webflow.resources.products import ProductSkuCreateSku +from webflow import SkuFieldData +from webflow import SkuFieldDataPrice from webflow import Sku +import datetime async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: @@ -28,24 +36,32 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: { "id": "Color", "name": "Color", - "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}], + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], } ], }, }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -93,11 +109,22 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, @@ -130,9 +157,13 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -140,17 +171,25 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -173,7 +212,7 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -189,20 +228,107 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, ), } - response = client.products.create(site_id="580e63e98c9a982ac9b8b741") + response = client.products.create( + site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem(id="red", name="Red", slug="red"), + SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), + SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem(id="small", name="Small", slug="small"), + SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), + SkuPropertyListEnumItem(id="large", name="Large", slug="large"), + ], + ), + ], + ) + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ) + ), + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.products.create(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.products.create( + site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem(id="red", name="Red", slug="red"), + SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), + SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem(id="small", name="Small", slug="small"), + SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), + SkuPropertyListEnumItem(id="large", name="Large", slug="large"), + ], + ), + ], + ) + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ) + ), + ) validate_response(async_response, expected_response, expected_types) @@ -222,9 +348,13 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -232,17 +362,25 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -265,7 +403,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -281,11 +419,22 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, @@ -315,9 +464,13 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -340,7 +493,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -359,17 +512,25 @@ async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ] @@ -385,44 +546,92 @@ async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, ) } response = client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ) + ], ) validate_response(response, expected_response, expected_types) async_response = await async_client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ) + ], ) validate_response(async_response, expected_response, expected_types) async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, "compare-at-price": {"value": 100, "unit": "USD"}, "ec-sku-billing-method": "one-time", "ec-sku-subscription-plan": {"interval": "day", "frequency": 1, "trial": 7, "plans": [{}]}, - "track-inventory": True, - "quantity": 10, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } expected_types: typing.Any = { @@ -432,10 +641,10 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, + "price": {"value": None, "unit": None, "currency": None}, "compare-at-price": {"value": None, "unit": None}, "ec-sku-billing-method": None, "ec-sku-subscription-plan": { @@ -444,15 +653,30 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: "trial": None, "plans": ("list", {0: {}}), }, - "track-inventory": None, - "quantity": None, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, + ), }, } response = client.products.update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ), ) validate_response(response, expected_response, expected_types) @@ -460,6 +684,17 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ), ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 6432530..e884c23 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -14,7 +14,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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", @@ -24,7 +23,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "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", @@ -39,7 +37,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "lastUpdated", "version": "1.0.0", }, - ] + ], + "pagination": {"limit": 100, "offset": 0, "total": 3}, } expected_types: typing.Any = { "registeredScripts": ( @@ -50,7 +49,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "canCopy": None, "displayName": None, "hostedLocation": None, - "integrityHash": None, "createdOn": None, "lastUpdated": None, "version": None, @@ -60,7 +58,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "canCopy": None, "displayName": None, "hostedLocation": None, - "integrityHash": None, "createdOn": None, "lastUpdated": None, "version": None, @@ -76,7 +73,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "version": None, }, }, - ) + ), + "pagination": {"limit": None, "offset": None, "total": None}, } response = client.scripts.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) @@ -131,7 +129,6 @@ async def test_register_inline(client: Webflow, async_client: AsyncWebflow) -> N "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", @@ -141,7 +138,6 @@ async def test_register_inline(client: Webflow, async_client: AsyncWebflow) -> N "canCopy": None, "displayName": None, "hostedLocation": None, - "integrityHash": None, "createdOn": None, "lastUpdated": None, "version": None, diff --git a/tests/test_sites.py b/tests/test_sites.py index 6e9dd9b..5381bc5 100644 --- a/tests/test_sites.py +++ b/tests/test_sites.py @@ -11,40 +11,14 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "id": "670ecf86817e3cc7a510eb6a", "workspaceId": "625860a7a6c16d624927122f", "createdOn": "2024-10-15T20:24:38Z", - "displayName": "The Hitchiker‘s Guide", + "displayName": "The Hitchiker's Guide", "shortName": "hitchikers-guide", - "lastPublished": "2016-10-24T19:43:17Z", "lastUpdated": "2024-10-15T20:24:38Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/580e63e98c9a982ac9b8b741/201610241243.png", - "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, + "dataCollectionEnabled": True, "dataCollectionType": "always", } expected_types: typing.Any = { @@ -53,38 +27,9 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> 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, } @@ -108,7 +53,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "heart-of-gold", "lastPublished": "2023-04-02T12:42:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b741/197910121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b741/197910121200.png", "timeZone": "DeepSpace/InfiniteImprobability", "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ @@ -160,9 +105,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "paranoid-android", "lastPublished": "2023-04-02T12:45:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b742/198110121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b742/198110121200.png", "timeZone": "DeepSpace/Depression", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ {"id": "589a331aa51e760df7ccb89f", "url": "marvin.blog", "lastPublished": "2022-12-07T16:51:37Z"} ], @@ -199,9 +143,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "vogon-poetry", "lastPublished": "2023-04-02T12:50:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b743/198210121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b743/198210121200.png", "timeZone": "Vogsphere/PoetryHall", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ { "id": "589a331aa51e760df7ccb8a0", @@ -299,7 +242,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "previewUrl": None, "timeZone": None, - "parentFolderId": None, "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), "locales": { "primary": { @@ -339,7 +281,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "previewUrl": None, "timeZone": None, - "parentFolderId": None, "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), "locales": { "primary": { @@ -630,8 +571,16 @@ async def test_publish(client: Webflow, async_client: AsyncWebflow) -> None: "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), "publishToWebflowSubdomain": None, } - response = client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + response = client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, + ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_token.py b/tests/test_token.py index d57ee3b..d81bdea 100644 --- a/tests/test_token.py +++ b/tests/test_token.py @@ -57,7 +57,7 @@ async def test_introspect(client: Webflow, async_client: AsyncWebflow) -> None: "userIds": ("list", {0: None}), }, }, - "application": None, + "application": {"id": None, "description": None, "homepage": None, "displayName": None}, } response = client.token.introspect() validate_response(response, expected_response, expected_types) diff --git a/tests/test_users.py b/tests/test_users.py index abcbfd6..a4e1338 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -4,7 +4,8 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response -from webflow.resources.users import UsersUpdateRequestData +import datetime +from webflow import UserAccessGroupsItem async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: @@ -237,16 +238,28 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> 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"], + id="6287ec36a841b25637c663df", + is_email_verified=True, + last_updated=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + invited_on=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + created_on=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + last_login=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + status="verified", + access_groups=[UserAccessGroupsItem(slug="webflowers", type="admin")], ) 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"], + id="6287ec36a841b25637c663df", + is_email_verified=True, + last_updated=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + invited_on=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + created_on=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + last_login=datetime.datetime.fromisoformat("2022-05-20 13:46:12+00:00"), + status="verified", + access_groups=[UserAccessGroupsItem(slug="webflowers", type="admin")], ) validate_response(async_response, expected_response, expected_types) @@ -291,11 +304,11 @@ async def test_invite(client: Webflow, async_client: AsyncWebflow) -> None: }, } response = client.users.invite( - site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"] + site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["accessGroups"] ) 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"] + site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["accessGroups"] ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index 4c19188..2607cf1 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -9,7 +9,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "pagination": {"limit": 100, "offset": 0, "total": 100}, "webhooks": [ { "id": "57ca0a9e418c504a6e1acbb6", @@ -42,9 +41,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "createdOn": "2016-07-19T01:43:40Z", }, ], + "pagination": {"limit": 100, "offset": 0, "total": 100}, } expected_types: typing.Any = { - "pagination": {"limit": None, "offset": None, "total": None}, "webhooks": ( "list", { @@ -80,6 +79,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), + "pagination": {"limit": None, "offset": None, "total": None}, } response = client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) @@ -95,7 +95,6 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "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", } @@ -105,7 +104,6 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "url": None, "workspaceId": None, "siteId": None, - "filter": {"name": None}, "lastTriggered": "datetime", "createdOn": "datetime", } @@ -141,7 +139,6 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "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", } @@ -151,7 +148,6 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "url": None, "workspaceId": None, "siteId": None, - "filter": {"name": None}, "lastTriggered": "datetime", "createdOn": "datetime", } diff --git a/tests/workspaces/__init__.py b/tests/workspaces/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/workspaces/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/workspaces/test_audit_logs.py b/tests/workspaces/test_audit_logs.py new file mode 100644 index 0000000..f1d25db --- /dev/null +++ b/tests/workspaces/test_audit_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 +import datetime +from ..utilities import validate_response + + +async def test_get_workspace_audit_logs(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "eventSubType": "login", + "eventType": "user_access", + "timestamp": "2025-04-29T20:30:06Z", + "actor": {"id": "6661ccb359b561c69f29d554", "email": "someone@email.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + { + "eventSubType": "user_added", + "eventType": "workspace_membership", + "timestamp": "2025-04-30T20:30:06Z", + "actor": {"id": "60492e55bbddce079561cd7a", "email": "someone@webflow.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + { + "eventSubType": "user_added", + "eventType": "site_membership", + "timestamp": "2025-04-30T00:33:31Z", + "actor": {"id": "671fe00d185fc8c1ad409d37", "email": "someone@webflow.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + ], + "pagination": {"limit": 10, "offset": 0, "total": 3}, + } + expected_types: typing.Any = { + "items": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate"}), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + from_=datetime.datetime.fromisoformat("2024-04-22 16:00:31+00:00"), + to=datetime.datetime.fromisoformat("2024-04-22 16:00:31+00:00"), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + from_=datetime.datetime.fromisoformat("2024-04-22 16:00:31+00:00"), + to=datetime.datetime.fromisoformat("2024-04-22 16:00:31+00:00"), + ) + validate_response(async_response, expected_response, expected_types)