Repository: cloudflare/cloudflare-go
Pull request #2548 (2024-06-17 03:48:44)

feat(api): update via SDK Studio


Patch:
diff --git a/.stats.yml b/.stats.yml
index ff2efbe66..21c949824 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 1343
+configured_endpoints: 1352
 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-e3875d4464358c7aee5cbb9a4e0e39f0e400536dfadb684e8f217a2800897d0e.yml
diff --git a/alerting/policy.go b/alerting/policy.go
index 83e25a664..5bd9d80ee 100644
--- a/alerting/policy.go
+++ b/alerting/policy.go
@@ -318,6 +318,30 @@ func (r PolicyAlertType) IsKnown() bool {
 	return false
 }
 
+type PolicyParam struct {
+	// Refers to which event will trigger a Notification dispatch. You can use the
+	// endpoint to get available alert types which then will give you a list of
+	// possible values.
+	AlertType param.Field[PolicyAlertType] `json:"alert_type"`
+	// Optional description for the Notification policy.
+	Description param.Field[string] `json:"description"`
+	// Whether or not the Notification policy is enabled.
+	Enabled param.Field[bool] `json:"enabled"`
+	// Optional filters that allow you to be alerted only on a subset of events for
+	// that alert type based on some criteria. This is only available for select alert
+	// types. See alert type documentation for more details.
+	Filters param.Field[PolicyFilterParam] `json:"filters"`
+	// List of IDs that will be used when dispatching a notification. IDs for email
+	// type will be the email address.
+	Mechanisms param.Field[MechanismParam] `json:"mechanisms"`
+	// Name of the policy.
+	Name param.Field[string] `json:"name"`
+}
+
+func (r PolicyParam) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
 // Optional filters that allow you to be alerted only on a subset of events for
 // that alert type based on some criteria. This is only available for select alert
 // types. See alert type documentation for more details.
diff --git a/api.md b/api.md
index 748f95ef8..08987a53f 100644
--- a/api.md
+++ b/api.md
@@ -2905,8 +2905,13 @@ Methods:
 
 ## Policies
 
+Params Types:
+
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#PolicyParam">PolicyParam</a>
+
 Response Types:
 
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#Policy">Policy</a>
 - <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#PolicyNewResponse">PolicyNewResponse</a>
 - <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#PolicyUpdateResponse">PolicyUpdateResponse</a>
 - <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#PolicyListResponse">PolicyListResponse</a>
@@ -2943,6 +2948,18 @@ Methods:
 - <code title="get /zones/{zone_id}/page_shield/scripts">client.PageShield.Scripts.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#ScriptService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#ScriptListParams">ScriptListParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination#SinglePage">SinglePage</a>[<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#Script">Script</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
 - <code title="get /zones/{zone_id}/page_shield/scripts/{script_id}">client.PageShield.Scripts.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#ScriptService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, scriptID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#ScriptGetParams">ScriptGetParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#ScriptGetResponse">ScriptGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
 
+## Cookies
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieListResponse">CookieListResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieGetResponse">CookieGetResponse</a>
+
+Methods:
+
+- <code title="get /zones/{zone_id}/page_shield/cookies">client.PageShield.Cookies.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieListParams">CookieListParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination#SinglePage">SinglePage</a>[<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieListResponse">CookieListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /zones/{zone_id}/page_shield/cookies/{cookie_id}">client.PageShield.Cookies.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, cookieID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieGetParams">CookieGetParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield">page_shield</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/page_shield#CookieGetResponse">CookieGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
 # Rulesets
 
 Params Types:
@@ -4427,6 +4444,7 @@ Methods:
 Params Types:
 
 - <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting">alerting</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting#MechanismParam">MechanismParam</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting">alerting</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting#PolicyParam">PolicyParam</a>
 - <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting">alerting</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/alerting#PolicyFilterParam">PolicyFilterParam</a>
 
 Response Types:
@@ -7231,3 +7249,35 @@ Response Types:
 Methods:
 
 - <code title="get /accounts/{account_id}/ai-gateway/gateways/{id}/logs">client.AIGateway.Logs.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/ai_gateway#LogService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/ai_gateway">ai_gateway</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/ai_gateway#LogGetParams">LogGetParams</a>) ([]<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/ai_gateway">ai_gateway</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/ai_gateway#LogGetResponse">LogGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# Iam
+
+## PermissionGroups
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupListResponse">IamPermissionGroupListResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupGetResponse">IamPermissionGroupGetResponse</a>
+
+Methods:
+
+- <code title="get /accounts/{account_id}/iam/permission_groups">client.Iam.PermissionGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupListParams">IamPermissionGroupListParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination#V4PagePaginationArray">V4PagePaginationArray</a>[<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupListResponse">IamPermissionGroupListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /accounts/{account_id}/iam/permission_groups/{permission_group_id}">client.Iam.PermissionGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, permissionGroupID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupGetParams">IamPermissionGroupGetParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamPermissionGroupGetResponse">IamPermissionGroupGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+## ResourceGroups
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupNewResponse">IamResourceGroupNewResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupUpdateResponse">IamResourceGroupUpdateResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupListResponse">IamResourceGroupListResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupDeleteResponse">IamResourceGroupDeleteResponse</a>
+- <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupGetResponse">IamResourceGroupGetResponse</a>
+
+Methods:
+
+- <code title="post /accounts/{account_id}/iam/resource_groups">client.Iam.ResourceGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupNewParams">IamResourceGroupNewParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupNewResponse">IamResourceGroupNewResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="put /accounts/{account_id}/iam/resource_groups/{resource_group_id}">client.Iam.ResourceGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupService.Update">Update</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, resourceGroupID <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupUpdateParams">IamResourceGroupUpdateParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupUpdateResponse">IamResourceGroupUpdateResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /accounts/{account_id}/iam/resource_groups">client.Iam.ResourceGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, params <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupListParams">IamResourceGroupListParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2/internal/pagination#V4PagePaginationArray">V4PagePaginationArray</a>[<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupListResponse">IamResourceGroupListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="delete /accounts/{account_id}/iam/resource_groups/{resource_group_id}">client.Iam.ResourceGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, resourceGroupID <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupDeleteParams">IamResourceGroupDeleteParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupDeleteResponse">IamResourceGroupDeleteResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /accounts/{account_id}/iam/resource_groups/{resource_group_id}">client.Iam.ResourceGroups.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, resourceGroupID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupGetParams">IamResourceGroupGetParams</a>) (<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2">cloudflare</a>.<a href="https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#IamResourceGroupGetResponse">IamResourceGroupGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
diff --git a/client.go b/client.go
index e5c7b793a..61dc44d7b 100644
--- a/client.go
+++ b/client.go
@@ -182,6 +182,7 @@ type Client struct {
 	CloudforceOne               *cloudforce_one.CloudforceOneService
 	EventNotifications          *event_notifications.EventNotificationService
 	AIGateway                   *ai_gateway.AIGatewayService
+	Iam                         *IamService
 }
 
 // NewClient generates a new client with the default option read from the
@@ -290,6 +291,7 @@ func NewClient(opts ...option.RequestOption) (r *Client) {
 	r.CloudforceOne = cloudforce_one.NewCloudforceOneService(opts...)
 	r.EventNotifications = event_notifications.NewEventNotificationService(opts...)
 	r.AIGateway = ai_gateway.NewAIGatewayService(opts...)
+	r.Iam = NewIamService(opts...)
 
 	return
 }
diff --git a/iam.go b/iam.go
new file mode 100644
index 000000000..37e97995f
--- /dev/null
+++ b/iam.go
@@ -0,0 +1,30 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package cloudflare
+
+import (
+	"github.com/cloudflare/cloudflare-go/v2/option"
+)
+
+// IamService contains methods and other services that help with interacting with
+// the cloudflare API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewIamService] method instead.
+type IamService struct {
+	Options          []option.RequestOption
+	PermissionGroups *IamPermissionGroupService
+	ResourceGroups   *IamResourceGroupService
+}
+
+// NewIamService generates a new service that applies the given options to each
+// request. These options are applied after the parent client's options (if there
+// is one), and before any request-specific options.
+func NewIamService(opts ...option.RequestOption) (r *IamService) {
+	r = &IamService{}
+	r.Options = opts
+	r.PermissionGroups = NewIamPermissionGroupService(opts...)
+	r.ResourceGroups = NewIamResourceGroupService(opts...)
+	return
+}
diff --git a/iampermissiongroup.go b/iampermissiongroup.go
new file mode 100644
index 000000000..47c664d42
--- /dev/null
+++ b/iampermissiongroup.go
@@ -0,0 +1,137 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package cloudflare
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+
+	"github.com/cloudflare/cloudflare-go/v2/internal/apijson"
+	"github.com/cloudflare/cloudflare-go/v2/internal/apiquery"
+	"github.com/cloudflare/cloudflare-go/v2/internal/pagination"
+	"github.com/cloudflare/cloudflare-go/v2/internal/param"
+	"github.com/cloudflare/cloudflare-go/v2/internal/requestconfig"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+)
+
+// IamPermissionGroupService contains methods and other services that help with
+// interacting with the cloudflare API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewIamPermissionGroupService] method instead.
+type IamPermissionGroupService struct {
+	Options []option.RequestOption
+}
+
+// NewIamPermissionGroupService generates a new service that applies the given
+// options to each request. These options are applied after the parent client's
+// options (if there is one), and before any request-specific options.
+func NewIamPermissionGroupService(opts ...option.RequestOption) (r *IamPermissionGroupService) {
+	r = &IamPermissionGroupService{}
+	r.Options = opts
+	return
+}
+
+// List all the permissions groups for an account.
+func (r *IamPermissionGroupService) List(ctx context.Context, params IamPermissionGroupListParams, opts ...option.RequestOption) (res *pagination.V4PagePaginationArray[IamPermissionGroupListResponse], err error) {
+	var raw *http.Response
+	opts = append(r.Options, opts...)
+	opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+	path := fmt.Sprintf("accounts/%s/iam/permission_groups", params.AccountID)
+	cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...)
+	if err != nil {
+		return nil, err
+	}
+	err = cfg.Execute()
+	if err != nil {
+		return nil, err
+	}
+	res.SetPageConfig(cfg, raw)
+	return res, nil
+}
+
+// List all the permissions groups for an account.
+func (r *IamPermissionGroupService) ListAutoPaging(ctx context.Context, params IamPermissionGroupListParams, opts ...option.RequestOption) *pagination.V4PagePaginationArrayAutoPager[IamPermissionGroupListResponse] {
+	return pagination.NewV4PagePaginationArrayAutoPager(r.List(ctx, params, opts...))
+}
+
+// Get information about a specific permission group in an account.
+func (r *IamPermissionGroupService) Get(ctx context.Context, permissionGroupID string, query IamPermissionGroupGetParams, opts ...option.RequestOption) (res *IamPermissionGroupGetResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	if query.AccountID.Value == "" {
+		err = errors.New("missing required account_id parameter")
+		return
+	}
+	if permissionGroupID == "" {
+		err = errors.New("missing required permission_group_id parameter")
+		return
+	}
+	path := fmt.Sprintf("accounts/%s/iam/permission_groups/%s", query.AccountID, permissionGroupID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+	return
+}
+
+type IamPermissionGroupListResponse = interface{}
+
+// A named group of permissions that map to a group of operations against
+// resources.
+type IamPermissionGroupGetResponse struct {
+	// Identifier of the group.
+	ID string `json:"id,required"`
+	// Attributes associated to the permission group.
+	Meta interface{} `json:"meta"`
+	// Name of the group.
+	Name string                            `json:"name"`
+	JSON iamPermissionGroupGetResponseJSON `json:"-"`
+}
+
+// iamPermissionGroupGetResponseJSON contains the JSON metadata for the struct
+// [IamPermissionGroupGetResponse]
+type iamPermissionGroupGetResponseJSON struct {
+	ID          apijson.Field
+	Meta        apijson.Field
+	Name        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamPermissionGroupGetResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamPermissionGroupGetResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+type IamPermissionGroupListParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+	// ID of the permission group to be fetched.
+	ID param.Field[string] `query:"id"`
+	// Label of the permission group to be fetched.
+	Label param.Field[string] `query:"label"`
+	// Name of the permission group to be fetched.
+	Name param.Field[string] `query:"name"`
+	// Page number of paginated results.
+	Page param.Field[float64] `query:"page"`
+	// Maximum number of results per page.
+	PerPage param.Field[float64] `query:"per_page"`
+}
+
+// URLQuery serializes [IamPermissionGroupListParams]'s query parameters as
+// `url.Values`.
+func (r IamPermissionGroupListParams) URLQuery() (v url.Values) {
+	return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+		ArrayFormat:  apiquery.ArrayQueryFormatRepeat,
+		NestedFormat: apiquery.NestedQueryFormatBrackets,
+	})
+}
+
+type IamPermissionGroupGetParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+}
diff --git a/iamresourcegroup.go b/iamresourcegroup.go
new file mode 100644
index 000000000..5df0631cf
--- /dev/null
+++ b/iamresourcegroup.go
@@ -0,0 +1,553 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package cloudflare
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+
+	"github.com/cloudflare/cloudflare-go/v2/internal/apijson"
+	"github.com/cloudflare/cloudflare-go/v2/internal/apiquery"
+	"github.com/cloudflare/cloudflare-go/v2/internal/pagination"
+	"github.com/cloudflare/cloudflare-go/v2/internal/param"
+	"github.com/cloudflare/cloudflare-go/v2/internal/requestconfig"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+	"github.com/cloudflare/cloudflare-go/v2/shared"
+)
+
+// IamResourceGroupService contains methods and other services that help with
+// interacting with the cloudflare API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewIamResourceGroupService] method instead.
+type IamResourceGroupService struct {
+	Options []option.RequestOption
+}
+
+// NewIamResourceGroupService generates a new service that applies the given
+// options to each request. These options are applied after the parent client's
+// options (if there is one), and before any request-specific options.
+func NewIamResourceGroupService(opts ...option.RequestOption) (r *IamResourceGroupService) {
+	r = &IamResourceGroupService{}
+	r.Options = opts
+	return
+}
+
+// Create a new Resource Group under the specified account.
+func (r *IamResourceGroupService) New(ctx context.Context, params IamResourceGroupNewParams, opts ...option.RequestOption) (res *IamResourceGroupNewResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	if params.AccountID.Value == "" {
+		err = errors.New("missing required account_id parameter")
+		return
+	}
+	path := fmt.Sprintf("accounts/%s/iam/resource_groups", params.AccountID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...)
+	return
+}
+
+// Modify an existing resource group.
+func (r *IamResourceGroupService) Update(ctx context.Context, resourceGroupID string, params IamResourceGroupUpdateParams, opts ...option.RequestOption) (res *IamResourceGroupUpdateResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	if params.AccountID.Value == "" {
+		err = errors.New("missing required account_id parameter")
+		return
+	}
+	if resourceGroupID == "" {
+		err = errors.New("missing required resource_group_id parameter")
+		return
+	}
+	path := fmt.Sprintf("accounts/%s/iam/resource_groups/%s", params.AccountID, resourceGroupID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodPut, path, params, &res, opts...)
+	return
+}
+
+// List all the resource groups for an account.
+func (r *IamResourceGroupService) List(ctx context.Context, params IamResourceGroupListParams, opts ...option.RequestOption) (res *pagination.V4PagePaginationArray[IamResourceGroupListResponse], err error) {
+	var raw *http.Response
+	opts = append(r.Options, opts...)
+	opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+	path := fmt.Sprintf("accounts/%s/iam/resource_groups", params.AccountID)
+	cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...)
+	if err != nil {
+		return nil, err
+	}
+	err = cfg.Execute()
+	if err != nil {
+		return nil, err
+	}
+	res.SetPageConfig(cfg, raw)
+	return res, nil
+}
+
+// List all the resource groups for an account.
+func (r *IamResourceGroupService) ListAutoPaging(ctx context.Context, params IamResourceGroupListParams, opts ...option.RequestOption) *pagination.V4PagePaginationArrayAutoPager[IamResourceGroupListResponse] {
+	return pagination.NewV4PagePaginationArrayAutoPager(r.List(ctx, params, opts...))
+}
+
+// Remove a resource group from an account.
+func (r *IamResourceGroupService) Delete(ctx context.Context, resourceGroupID string, body IamResourceGroupDeleteParams, opts ...option.RequestOption) (res *IamResourceGroupDeleteResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	var env IamResourceGroupDeleteResponseEnvelope
+	if body.AccountID.Value == "" {
+		err = errors.New("missing required account_id parameter")
+		return
+	}
+	if resourceGroupID == "" {
+		err = errors.New("missing required resource_group_id parameter")
+		return
+	}
+	path := fmt.Sprintf("accounts/%s/iam/resource_groups/%s", body.AccountID, resourceGroupID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, &env, opts...)
+	if err != nil {
+		return
+	}
+	res = &env.Result
+	return
+}
+
+// Get information about a specific resource group in an account.
+func (r *IamResourceGroupService) Get(ctx context.Context, resourceGroupID string, query IamResourceGroupGetParams, opts ...option.RequestOption) (res *IamResourceGroupGetResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	if query.AccountID.Value == "" {
+		err = errors.New("missing required account_id parameter")
+		return
+	}
+	if resourceGroupID == "" {
+		err = errors.New("missing required resource_group_id parameter")
+		return
+	}
+	path := fmt.Sprintf("accounts/%s/iam/resource_groups/%s", query.AccountID, resourceGroupID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+	return
+}
+
+// A group of scoped resources.
+type IamResourceGroupNewResponse struct {
+	// Identifier of the group.
+	ID string `json:"id"`
+	// Attributes associated to the resource group.
+	Meta interface{} `json:"meta"`
+	// A scope is a combination of scope objects which provides additional context.
+	Scope IamResourceGroupNewResponseScope `json:"scope"`
+	JSON  iamResourceGroupNewResponseJSON  `json:"-"`
+}
+
+// iamResourceGroupNewResponseJSON contains the JSON metadata for the struct
+// [IamResourceGroupNewResponse]
+type iamResourceGroupNewResponseJSON struct {
+	ID          apijson.Field
+	Meta        apijson.Field
+	Scope       apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupNewResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupNewResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope is a combination of scope objects which provides additional context.
+type IamResourceGroupNewResponseScope struct {
+	// This is a combination of pre-defined resource name and identifier (like Account
+	// ID etc.)
+	Key string `json:"key,required"`
+	// A list of scope objects for additional context. The number of Scope objects
+	// should not be zero.
+	Objects []IamResourceGroupNewResponseScopeObject `json:"objects,required"`
+	JSON    iamResourceGroupNewResponseScopeJSON     `json:"-"`
+}
+
+// iamResourceGroupNewResponseScopeJSON contains the JSON metadata for the struct
+// [IamResourceGroupNewResponseScope]
+type iamResourceGroupNewResponseScopeJSON struct {
+	Key         apijson.Field
+	Objects     apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupNewResponseScope) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupNewResponseScopeJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope object represents any resource that can have actions applied against
+// invite.
+type IamResourceGroupNewResponseScopeObject struct {
+	// This is a combination of pre-defined resource name and identifier (like Zone ID
+	// etc.)
+	Key  string                                     `json:"key,required"`
+	JSON iamResourceGroupNewResponseScopeObjectJSON `json:"-"`
+}
+
+// iamResourceGroupNewResponseScopeObjectJSON contains the JSON metadata for the
+// struct [IamResourceGroupNewResponseScopeObject]
+type iamResourceGroupNewResponseScopeObjectJSON struct {
+	Key         apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupNewResponseScopeObject) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupNewResponseScopeObjectJSON) RawJSON() string {
+	return r.raw
+}
+
+// A group of scoped resources.
+type IamResourceGroupUpdateResponse struct {
+	// Identifier of the group.
+	ID string `json:"id,required"`
+	// The scope associated to the resource group
+	Scope []IamResourceGroupUpdateResponseScope `json:"scope,required"`
+	// Attributes associated to the resource group.
+	Meta interface{} `json:"meta"`
+	// Name of the resource group.
+	Name string                             `json:"name"`
+	JSON iamResourceGroupUpdateResponseJSON `json:"-"`
+}
+
+// iamResourceGroupUpdateResponseJSON contains the JSON metadata for the struct
+// [IamResourceGroupUpdateResponse]
+type iamResourceGroupUpdateResponseJSON struct {
+	ID          apijson.Field
+	Scope       apijson.Field
+	Meta        apijson.Field
+	Name        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupUpdateResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupUpdateResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope is a combination of scope objects which provides additional context.
+type IamResourceGroupUpdateResponseScope struct {
+	// This is a combination of pre-defined resource name and identifier (like Account
+	// ID etc.)
+	Key string `json:"key,required"`
+	// A list of scope objects for additional context.
+	Objects []IamResourceGroupUpdateResponseScopeObject `json:"objects,required"`
+	JSON    iamResourceGroupUpdateResponseScopeJSON     `json:"-"`
+}
+
+// iamResourceGroupUpdateResponseScopeJSON contains the JSON metadata for the
+// struct [IamResourceGroupUpdateResponseScope]
+type iamResourceGroupUpdateResponseScopeJSON struct {
+	Key         apijson.Field
+	Objects     apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupUpdateResponseScope) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupUpdateResponseScopeJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope object represents any resource that can have actions applied against
+// invite.
+type IamResourceGroupUpdateResponseScopeObject struct {
+	// This is a combination of pre-defined resource name and identifier (like Zone ID
+	// etc.)
+	Key  string                                        `json:"key,required"`
+	JSON iamResourceGroupUpdateResponseScopeObjectJSON `json:"-"`
+}
+
+// iamResourceGroupUpdateResponseScopeObjectJSON contains the JSON metadata for the
+// struct [IamResourceGroupUpdateResponseScopeObject]
+type iamResourceGroupUpdateResponseScopeObjectJSON struct {
+	Key         apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupUpdateResponseScopeObject) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupUpdateResponseScopeObjectJSON) RawJSON() string {
+	return r.raw
+}
+
+type IamResourceGroupListResponse = interface{}
+
+type IamResourceGroupDeleteResponse struct {
+	// Identifier
+	ID   string                             `json:"id,required"`
+	JSON iamResourceGroupDeleteResponseJSON `json:"-"`
+}
+
+// iamResourceGroupDeleteResponseJSON contains the JSON metadata for the struct
+// [IamResourceGroupDeleteResponse]
+type iamResourceGroupDeleteResponseJSON struct {
+	ID          apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupDeleteResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupDeleteResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+// A group of scoped resources.
+type IamResourceGroupGetResponse struct {
+	// Identifier of the group.
+	ID string `json:"id,required"`
+	// The scope associated to the resource group
+	Scope []IamResourceGroupGetResponseScope `json:"scope,required"`
+	// Attributes associated to the resource group.
+	Meta interface{} `json:"meta"`
+	// Name of the resource group.
+	Name string                          `json:"name"`
+	JSON iamResourceGroupGetResponseJSON `json:"-"`
+}
+
+// iamResourceGroupGetResponseJSON contains the JSON metadata for the struct
+// [IamResourceGroupGetResponse]
+type iamResourceGroupGetResponseJSON struct {
+	ID          apijson.Field
+	Scope       apijson.Field
+	Meta        apijson.Field
+	Name        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupGetResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupGetResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope is a combination of scope objects which provides additional context.
+type IamResourceGroupGetResponseScope struct {
+	// This is a combination of pre-defined resource name and identifier (like Account
+	// ID etc.)
+	Key string `json:"key,required"`
+	// A list of scope objects for additional context.
+	Objects []IamResourceGroupGetResponseScopeObject `json:"objects,required"`
+	JSON    iamResourceGroupGetResponseScopeJSON     `json:"-"`
+}
+
+// iamResourceGroupGetResponseScopeJSON contains the JSON metadata for the struct
+// [IamResourceGroupGetResponseScope]
+type iamResourceGroupGetResponseScopeJSON struct {
+	Key         apijson.Field
+	Objects     apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupGetResponseScope) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupGetResponseScopeJSON) RawJSON() string {
+	return r.raw
+}
+
+// A scope object represents any resource that can have actions applied against
+// invite.
+type IamResourceGroupGetResponseScopeObject struct {
+	// This is a combination of pre-defined resource name and identifier (like Zone ID
+	// etc.)
+	Key  string                                     `json:"key,required"`
+	JSON iamResourceGroupGetResponseScopeObjectJSON `json:"-"`
+}
+
+// iamResourceGroupGetResponseScopeObjectJSON contains the JSON metadata for the
+// struct [IamResourceGroupGetResponseScopeObject]
+type iamResourceGroupGetResponseScopeObjectJSON struct {
+	Key         apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupGetResponseScopeObject) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupGetResponseScopeObjectJSON) RawJSON() string {
+	return r.raw
+}
+
+type IamResourceGroupNewParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+	// A scope is a combination of scope objects which provides additional context.
+	Scope param.Field[IamResourceGroupNewParamsScope] `json:"scope,required"`
+	// Attributes associated to the resource group.
+	Meta param.Field[interface{}] `json:"meta"`
+}
+
+func (r IamResourceGroupNewParams) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+// A scope is a combination of scope objects which provides additional context.
+type IamResourceGroupNewParamsScope struct {
+	// This is a combination of pre-defined resource name and identifier (like Account
+	// ID etc.)
+	Key param.Field[string] `json:"key,required"`
+	// A list of scope objects for additional context. The number of Scope objects
+	// should not be zero.
+	Objects param.Field[[]IamResourceGroupNewParamsScopeObject] `json:"objects,required"`
+}
+
+func (r IamResourceGroupNewParamsScope) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+// A scope object represents any resource that can have actions applied against
+// invite.
+type IamResourceGroupNewParamsScopeObject struct {
+	// This is a combination of pre-defined resource name and identifier (like Zone ID
+	// etc.)
+	Key param.Field[string] `json:"key,required"`
+}
+
+func (r IamResourceGroupNewParamsScopeObject) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+type IamResourceGroupUpdateParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+	// A scope is a combination of scope objects which provides additional context.
+	Scope param.Field[IamResourceGroupUpdateParamsScope] `json:"scope,required"`
+	// Attributes associated to the resource group.
+	Meta param.Field[interface{}] `json:"meta"`
+}
+
+func (r IamResourceGroupUpdateParams) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+// A scope is a combination of scope objects which provides additional context.
+type IamResourceGroupUpdateParamsScope struct {
+	// This is a combination of pre-defined resource name and identifier (like Account
+	// ID etc.)
+	Key param.Field[string] `json:"key,required"`
+	// A list of scope objects for additional context. The number of Scope objects
+	// should not be zero.
+	Objects param.Field[[]IamResourceGroupUpdateParamsScopeObject] `json:"objects,required"`
+}
+
+func (r IamResourceGroupUpdateParamsScope) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+// A scope object represents any resource that can have actions applied against
+// invite.
+type IamResourceGroupUpdateParamsScopeObject struct {
+	// This is a combination of pre-defined resource name and identifier (like Zone ID
+	// etc.)
+	Key param.Field[string] `json:"key,required"`
+}
+
+func (r IamResourceGroupUpdateParamsScopeObject) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
+type IamResourceGroupListParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+	// ID of the resource group to be fetched.
+	ID param.Field[string] `query:"id"`
+	// Name of the resource group to be fetched.
+	Name param.Field[string] `query:"name"`
+	// Page number of paginated results.
+	Page param.Field[float64] `query:"page"`
+	// Maximum number of results per page.
+	PerPage param.Field[float64] `query:"per_page"`
+}
+
+// URLQuery serializes [IamResourceGroupListParams]'s query parameters as
+// `url.Values`.
+func (r IamResourceGroupListParams) URLQuery() (v url.Values) {
+	return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+		ArrayFormat:  apiquery.ArrayQueryFormatRepeat,
+		NestedFormat: apiquery.NestedQueryFormatBrackets,
+	})
+}
+
+type IamResourceGroupDeleteParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+}
+
+type IamResourceGroupDeleteResponseEnvelope struct {
+	Errors   []shared.ResponseInfo `json:"errors,required"`
+	Messages []shared.ResponseInfo `json:"messages,required"`
+	// Whether the API call was successful
+	Success IamResourceGroupDeleteResponseEnvelopeSuccess `json:"success,required"`
+	Result  IamResourceGroupDeleteResponse                `json:"result,nullable"`
+	JSON    iamResourceGroupDeleteResponseEnvelopeJSON    `json:"-"`
+}
+
+// iamResourceGroupDeleteResponseEnvelopeJSON contains the JSON metadata for the
+// struct [IamResourceGroupDeleteResponseEnvelope]
+type iamResourceGroupDeleteResponseEnvelopeJSON struct {
+	Errors      apijson.Field
+	Messages    apijson.Field
+	Success     apijson.Field
+	Result      apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *IamResourceGroupDeleteResponseEnvelope) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r iamResourceGroupDeleteResponseEnvelopeJSON) RawJSON() string {
+	return r.raw
+}
+
+// Whether the API call was successful
+type IamResourceGroupDeleteResponseEnvelopeSuccess bool
+
+const (
+	IamResourceGroupDeleteResponseEnvelopeSuccessTrue IamResourceGroupDeleteResponseEnvelopeSuccess = true
+)
+
+func (r IamResourceGroupDeleteResponseEnvelopeSuccess) IsKnown() bool {
+	switch r {
+	case IamResourceGroupDeleteResponseEnvelopeSuccessTrue:
+		return true
+	}
+	return false
+}
+
+type IamResourceGroupGetParams struct {
+	// Account identifier tag.
+	AccountID param.Field[string] `path:"account_id,required"`
+}
diff --git a/page_shield/cookie.go b/page_shield/cookie.go
new file mode 100644
index 000000000..b6e2b9fea
--- /dev/null
+++ b/page_shield/cookie.go
@@ -0,0 +1,424 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package page_shield
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"time"
+
+	"github.com/cloudflare/cloudflare-go/v2/internal/apijson"
+	"github.com/cloudflare/cloudflare-go/v2/internal/apiquery"
+	"github.com/cloudflare/cloudflare-go/v2/internal/pagination"
+	"github.com/cloudflare/cloudflare-go/v2/internal/param"
+	"github.com/cloudflare/cloudflare-go/v2/internal/requestconfig"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+	"github.com/cloudflare/cloudflare-go/v2/shared"
+)
+
+// CookieService contains methods and other services that help with interacting
+// with the cloudflare API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewCookieService] method instead.
+type CookieService struct {
+	Options []option.RequestOption
+}
+
+// NewCookieService generates a new service that applies the given options to each
+// request. These options are applied after the parent client's options (if there
+// is one), and before any request-specific options.
+func NewCookieService(opts ...option.RequestOption) (r *CookieService) {
+	r = &CookieService{}
+	r.Options = opts
+	return
+}
+
+// Lists all cookies collected by Page Shield.
+func (r *CookieService) List(ctx context.Context, params CookieListParams, opts ...option.RequestOption) (res *pagination.SinglePage[CookieListResponse], err error) {
+	var raw *http.Response
+	opts = append(r.Options, opts...)
+	opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+	path := fmt.Sprintf("zones/%s/page_shield/cookies", params.ZoneID)
+	cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...)
+	if err != nil {
+		return nil, err
+	}
+	err = cfg.Execute()
+	if err != nil {
+		return nil, err
+	}
+	res.SetPageConfig(cfg, raw)
+	return res, nil
+}
+
+// Lists all cookies collected by Page Shield.
+func (r *CookieService) ListAutoPaging(ctx context.Context, params CookieListParams, opts ...option.RequestOption) *pagination.SinglePageAutoPager[CookieListResponse] {
+	return pagination.NewSinglePageAutoPager(r.List(ctx, params, opts...))
+}
+
+// Fetches a cookie collected by Page Shield by cookie ID.
+func (r *CookieService) Get(ctx context.Context, cookieID string, query CookieGetParams, opts ...option.RequestOption) (res *CookieGetResponse, err error) {
+	opts = append(r.Options[:], opts...)
+	var env CookieGetResponseEnvelope
+	if query.ZoneID.Value == "" {
+		err = errors.New("missing required zone_id parameter")
+		return
+	}
+	if cookieID == "" {
+		err = errors.New("missing required cookie_id parameter")
+		return
+	}
+	path := fmt.Sprintf("zones/%s/page_shield/cookies/%s", query.ZoneID, cookieID)
+	err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &env, opts...)
+	if err != nil {
+		return
+	}
+	res = &env.Result
+	return
+}
+
+type CookieListResponse struct {
+	// Identifier
+	ID                string                              `json:"id,required"`
+	FirstSeenAt       time.Time                           `json:"first_seen_at,required" format:"date-time"`
+	Host              string                              `json:"host,required"`
+	LastSeenAt        time.Time                           `json:"last_seen_at,required" format:"date-time"`
+	Name              string                              `json:"name,required"`
+	Type              CookieListResponseType              `json:"type,required"`
+	DomainAttribute   string                              `json:"domain_attribute"`
+	ExpiresAttribute  time.Time                           `json:"expires_attribute" format:"date-time"`
+	HTTPOnlyAttribute bool                                `json:"http_only_attribute"`
+	MaxAgeAttribute   int64                               `json:"max_age_attribute"`
+	PageURLs          []string                            `json:"page_urls"`
+	PathAttribute     string                              `json:"path_attribute"`
+	SameSiteAttribute CookieListResponseSameSiteAttribute `json:"same_site_attribute"`
+	SecureAttribute   bool                                `json:"secure_attribute"`
+	JSON              cookieListResponseJSON              `json:"-"`
+}
+
+// cookieListResponseJSON contains the JSON metadata for the struct
+// [CookieListResponse]
+type cookieListResponseJSON struct {
+	ID                apijson.Field
+	FirstSeenAt       apijson.Field
+	Host              apijson.Field
+	LastSeenAt        apijson.Field
+	Name              apijson.Field
+	Type              apijson.Field
+	DomainAttribute   apijson.Field
+	ExpiresAttribute  apijson.Field
+	HTTPOnlyAttribute apijson.Field
+	MaxAgeAttribute   apijson.Field
+	PageURLs          apijson.Field
+	PathAttribute     apijson.Field
+	SameSiteAttribute apijson.Field
+	SecureAttribute   apijson.Field
+	raw               string
+	ExtraFields       map[string]apijson.Field
+}
+
+func (r *CookieListResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r cookieListResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+type CookieListResponseType string
+
+const (
+	CookieListResponseTypeFirstParty CookieListResponseType = "first_party"
+	CookieListResponseTypeUnknown    CookieListResponseType = "unknown"
+)
+
+func (r CookieListResponseType) IsKnown() bool {
+	switch r {
+	case CookieListResponseTypeFirstParty, CookieListResponseTypeUnknown:
+		return true
+	}
+	return false
+}
+
+type CookieListResponseSameSiteAttribute string
+
+const (
+	CookieListResponseSameSiteAttributeLax    CookieListResponseSameSiteAttribute = "lax"
+	CookieListResponseSameSiteAttributeStrict CookieListResponseSameSiteAttribute = "strict"
+	CookieListResponseSameSiteAttributeNone   CookieListResponseSameSiteAttribute = "none"
+)
+
+func (r CookieListResponseSameSiteAttribute) IsKnown() bool {
+	switch r {
+	case CookieListResponseSameSiteAttributeLax, CookieListResponseSameSiteAttributeStrict, CookieListResponseSameSiteAttributeNone:
+		return true
+	}
+	return false
+}
+
+type CookieGetResponse struct {
+	// Identifier
+	ID                string                             `json:"id,required"`
+	FirstSeenAt       time.Time                          `json:"first_seen_at,required" format:"date-time"`
+	Host              string                             `json:"host,required"`
+	LastSeenAt        time.Time                          `json:"last_seen_at,required" format:"date-time"`
+	Name              string                             `json:"name,required"`
+	Type              CookieGetResponseType              `json:"type,required"`
+	DomainAttribute   string                             `json:"domain_attribute"`
+	ExpiresAttribute  time.Time                          `json:"expires_attribute" format:"date-time"`
+	HTTPOnlyAttribute bool                               `json:"http_only_attribute"`
+	MaxAgeAttribute   int64                              `json:"max_age_attribute"`
+	PageURLs          []string                           `json:"page_urls"`
+	PathAttribute     string                             `json:"path_attribute"`
+	SameSiteAttribute CookieGetResponseSameSiteAttribute `json:"same_site_attribute"`
+	SecureAttribute   bool                               `json:"secure_attribute"`
+	JSON              cookieGetResponseJSON              `json:"-"`
+}
+
+// cookieGetResponseJSON contains the JSON metadata for the struct
+// [CookieGetResponse]
+type cookieGetResponseJSON struct {
+	ID                apijson.Field
+	FirstSeenAt       apijson.Field
+	Host              apijson.Field
+	LastSeenAt        apijson.Field
+	Name              apijson.Field
+	Type              apijson.Field
+	DomainAttribute   apijson.Field
+	ExpiresAttribute  apijson.Field
+	HTTPOnlyAttribute apijson.Field
+	MaxAgeAttribute   apijson.Field
+	PageURLs          apijson.Field
+	PathAttribute     apijson.Field
+	SameSiteAttribute apijson.Field
+	SecureAttribute   apijson.Field
+	raw               string
+	ExtraFields       map[string]apijson.Field
+}
+
+func (r *CookieGetResponse) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r cookieGetResponseJSON) RawJSON() string {
+	return r.raw
+}
+
+type CookieGetResponseType string
+
+const (
+	CookieGetResponseTypeFirstParty CookieGetResponseType = "first_party"
+	CookieGetResponseTypeUnknown    CookieGetResponseType = "unknown"
+)
+
+func (r CookieGetResponseType) IsKnown() bool {
+	switch r {
+	case CookieGetResponseTypeFirstParty, CookieGetResponseTypeUnknown:
+		return true
+	}
+	return false
+}
+
+type CookieGetResponseSameSiteAttribute string
+
+const (
+	CookieGetResponseSameSiteAttributeLax    CookieGetResponseSameSiteAttribute = "lax"
+	CookieGetResponseSameSiteAttributeStrict CookieGetResponseSameSiteAttribute = "strict"
+	CookieGetResponseSameSiteAttributeNone   CookieGetResponseSameSiteAttribute = "none"
+)
+
+func (r CookieGetResponseSameSiteAttribute) IsKnown() bool {
+	switch r {
+	case CookieGetResponseSameSiteAttributeLax, CookieGetResponseSameSiteAttributeStrict, CookieGetResponseSameSiteAttributeNone:
+		return true
+	}
+	return false
+}
+
+type CookieListParams struct {
+	// Identifier
+	ZoneID param.Field[string] `path:"zone_id,required"`
+	// The direction used to sort returned cookies.'
+	Direction param.Field[CookieListParamsDirection] `query:"direction"`
+	// Filters the returned cookies that match the specified domain attribute
+	Domain param.Field[string] `query:"domain"`
+	// Export the list of cookies as a file. Cannot be used with per_page or page
+	// options.
+	Export param.Field[CookieListParamsExport] `query:"export"`
+	// Includes cookies that match one or more URL-encoded hostnames separated by
+	// commas.
+	//
+	// Wildcards are supported at the start and end of each hostname to support starts
+	// with, ends with and contains. If no wildcards are used, results will be filtered
+	// by exact match
+	Hosts param.Field[string] `query:"hosts"`
+	// Filters the returned cookies that are set with HttpOnly
+	HTTPOnly param.Field[bool] `query:"http_only"`
+	// Filters the returned cookies that match the specified name. Wildcards are
+	// supported at the start and end to support starts with, ends with and contains.
+	// e.g. session\*
+	Name param.Field[string] `query:"name"`
+	// The field used to sort returned cookies.
+	OrderBy param.Field[CookieListParamsOrderBy] `query:"order_by"`
+	// The current page number of the paginated results.
+	Page param.Field[string] `query:"page"`
+	// Includes connections that match one or more page URLs (separated by commas)
+	// where they were last seen
+	//
+	// Wildcards are supported at the start and end of each page URL to support starts
+	// with, ends with and contains. If no wildcards are used, results will be filtered
+	// by exact match
+	PageURL param.Field[string] `query:"page_url"`
+	// Filters the returned cookies that match the specified path attribute
+	Path param.Field[string] `query:"path"`
+	// The number of results per page.
+	PerPage param.Field[float64] `query:"per_page"`
+	// Filters the returned cookies that match the specified same_site attribute
+	SameSite param.Field[CookieListParamsSameSite] `query:"same_site"`
+	// Filters the returned cookies that are set with Secure
+	Secure param.Field[bool] `query:"secure"`
+	// Filters the returned cookies that match the specified type attribute
+	Type param.Field[CookieListParamsType] `query:"type"`
+}
+
+// URLQuery serializes [CookieListParams]'s query parameters as `url.Values`.
+func (r CookieListParams) URLQuery() (v url.Values) {
+	return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+		ArrayFormat:  apiquery.ArrayQueryFormatRepeat,
+		NestedFormat: apiquery.NestedQueryFormatBrackets,
+	})
+}
+
+// The direction used to sort returned cookies.'
+type CookieListParamsDirection string
+
+const (
+	CookieListParamsDirectionAsc  CookieListParamsDirection = "asc"
+	CookieListParamsDirectionDesc CookieListParamsDirection = "desc"
+)
+
+func (r CookieListParamsDirection) IsKnown() bool {
+	switch r {
+	case CookieListParamsDirectionAsc, CookieListParamsDirectionDesc:
+		return true
+	}
+	return false
+}
+
+// Export the list of cookies as a file. Cannot be used with per_page or page
+// options.
+type CookieListParamsExport string
+
+const (
+	CookieListParamsExportCsv CookieListParamsExport = "csv"
+)
+
+func (r CookieListParamsExport) IsKnown() bool {
+	switch r {
+	case CookieListParamsExportCsv:
+		return true
+	}
+	return false
+}
+
+// The field used to sort returned cookies.
+type CookieListParamsOrderBy string
+
+const (
+	CookieListParamsOrderByFirstSeenAt CookieListParamsOrderBy = "first_seen_at"
+	CookieListParamsOrderByLastSeenAt  CookieListParamsOrderBy = "last_seen_at"
+)
+
+func (r CookieListParamsOrderBy) IsKnown() bool {
+	switch r {
+	case CookieListParamsOrderByFirstSeenAt, CookieListParamsOrderByLastSeenAt:
+		return true
+	}
+	return false
+}
+
+// Filters the returned cookies that match the specified same_site attribute
+type CookieListParamsSameSite string
+
+const (
+	CookieListParamsSameSiteLax    CookieListParamsSameSite = "lax"
+	CookieListParamsSameSiteStrict CookieListParamsSameSite = "strict"
+	CookieListParamsSameSiteNone   CookieListParamsSameSite = "none"
+)
+
+func (r CookieListParamsSameSite) IsKnown() bool {
+	switch r {
+	case CookieListParamsSameSiteLax, CookieListParamsSameSiteStrict, CookieListParamsSameSiteNone:
+		return true
+	}
+	return false
+}
+
+// Filters the returned cookies that match the specified type attribute
+type CookieListParamsType string
+
+const (
+	CookieListParamsTypeFirstParty CookieListParamsType = "first_party"
+	CookieListParamsTypeUnknown    CookieListParamsType = "unknown"
+)
+
+func (r CookieListParamsType) IsKnown() bool {
+	switch r {
+	case CookieListParamsTypeFirstParty, CookieListParamsTypeUnknown:
+		return true
+	}
+	return false
+}
+
+type CookieGetParams struct {
+	// Identifier
+	ZoneID param.Field[string] `path:"zone_id,required"`
+}
+
+type CookieGetResponseEnvelope struct {
+	Result CookieGetResponse `json:"result,required,nullable"`
+	// Whether the API call was successful
+	Success  CookieGetResponseEnvelopeSuccess `json:"success,required"`
+	Errors   []shared.ResponseInfo            `json:"errors"`
+	Messages []shared.ResponseInfo            `json:"messages"`
+	JSON     cookieGetResponseEnvelopeJSON    `json:"-"`
+}
+
+// cookieGetResponseEnvelopeJSON contains the JSON metadata for the struct
+// [CookieGetResponseEnvelope]
+type cookieGetResponseEnvelopeJSON struct {
+	Result      apijson.Field
+	Success     apijson.Field
+	Errors      apijson.Field
+	Messages    apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *CookieGetResponseEnvelope) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r cookieGetResponseEnvelopeJSON) RawJSON() string {
+	return r.raw
+}
+
+// Whether the API call was successful
+type CookieGetResponseEnvelopeSuccess bool
+
+const (
+	CookieGetResponseEnvelopeSuccessTrue CookieGetResponseEnvelopeSuccess = true
+)
+
+func (r CookieGetResponseEnvelopeSuccess) IsKnown() bool {
+	switch r {
+	case CookieGetResponseEnvelopeSuccessTrue:
+		return true
+	}
+	return false
+}
diff --git a/page_shield/pageshield.go b/page_shield/pageshield.go
index b7150b07b..39ffcdfe8 100644
--- a/page_shield/pageshield.go
+++ b/page_shield/pageshield.go
@@ -26,6 +26,7 @@ type PageShieldService struct {
 	Policies    *PolicyService
 	Connections *ConnectionService
 	Scripts     *ScriptService
+	Cookies     *CookieService
 }
 
 // NewPageShieldService generates a new service that applies the given options to
@@ -37,6 +38,7 @@ func NewPageShieldService(opts ...option.RequestOption) (r *PageShieldService) {
 	r.Policies = NewPolicyService(opts...)
 	r.Connections = NewConnectionService(opts...)
 	r.Scripts = NewScriptService(opts...)
+	r.Cookies = NewCookieService(opts...)
 	return
 }
 
diff --git a/page_shield/policy.go b/page_shield/policy.go
index b8fed09cb..dcec6afc1 100644
--- a/page_shield/policy.go
+++ b/page_shield/policy.go
@@ -134,6 +134,74 @@ func (r *PolicyService) Get(ctx context.Context, policyID string, query PolicyGe
 	return
 }
 
+type Policy struct {
+	// The action to take if the expression matches
+	Action PolicyAction `json:"action,required"`
+	// A description for the policy
+	Description string `json:"description,required"`
+	// Whether the policy is enabled
+	Enabled bool `json:"enabled,required"`
+	// The expression which must match for the policy to be applied, using the
+	// Cloudflare Firewall rule expression syntax
+	Expression string `json:"expression,required"`
+	// The policy which will be applied
+	Value string     `json:"value,required"`
+	JSON  policyJSON `json:"-"`
+}
+
+// policyJSON contains the JSON metadata for the struct [Policy]
+type policyJSON struct {
+	Action      apijson.Field
+	Description apijson.Field
+	Enabled     apijson.Field
+	Expression  apijson.Field
+	Value       apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *Policy) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r policyJSON) RawJSON() string {
+	return r.raw
+}
+
+// The action to take if the expression matches
+type PolicyAction string
+
+const (
+	PolicyActionAllow PolicyAction = "allow"
+	PolicyActionLog   PolicyAction = "log"
+)
+
+func (r PolicyAction) IsKnown() bool {
+	switch r {
+	case PolicyActionAllow, PolicyActionLog:
+		return true
+	}
+	return false
+}
+
+type PolicyParam struct {
+	// The action to take if the expression matches
+	Action param.Field[PolicyAction] `json:"action,required"`
+	// A description for the policy
+	Description param.Field[string] `json:"description,required"`
+	// Whether the policy is enabled
+	Enabled param.Field[bool] `json:"enabled,required"`
+	// The expression which must match for the policy to be applied, using the
+	// Cloudflare Firewall rule expression syntax
+	Expression param.Field[string] `json:"expression,required"`
+	// The policy which will be applied
+	Value param.Field[string] `json:"value,required"`
+}
+
+func (r PolicyParam) MarshalJSON() (data []byte, err error) {
+	return apijson.MarshalRoot(r)
+}
+
 type PolicyNewResponse struct {
 	// Identifier
 	ID string `json:"id,required"`
@@ -353,37 +421,11 @@ func (r PolicyGetResponseAction) IsKnown() bool {
 type PolicyNewParams struct {
 	// Identifier
 	ZoneID param.Field[string] `path:"zone_id,required"`
-	// The action to take if the expression matches
-	Action param.Field[PolicyNewParamsAction] `json:"action,required"`
-	// A description for the policy
-	Description param.Field[string] `json:"description,required"`
-	// Whether the policy is enabled
-	Enabled param.Field[bool] `json:"enabled,required"`
-	// The expression which must match for the policy to be applied, using the
-	// Cloudflare Firewall rule expression syntax
-	Expression param.Field[string] `json:"expression,required"`
-	// The policy which will be applied
-	Value param.Field[string] `json:"value,required"`
+	Policy PolicyParam         `json:"policy,required"`
 }
 
 func (r PolicyNewParams) MarshalJSON() (data []byte, err error) {
-	return apijson.MarshalRoot(r)
-}
-
-// The action to take if the expression matches
-type PolicyNewParamsAction string
-
-const (
-	PolicyNewParamsActionAllow PolicyNewParamsAction = "allow"
-	PolicyNewParamsActionLog   PolicyNewParamsAction = "log"
-)
-
-func (r PolicyNewParamsAction) IsKnown() bool {
-	switch r {
-	case PolicyNewParamsActionAllow, PolicyNewParamsActionLog:
-		return true
-	}
-	return false
+	return apijson.MarshalRoot(r.Policy)
 }
 
 type PolicyNewResponseEnvelope struct {


Test patch:
diff --git a/iampermissiongroup_test.go b/iampermissiongroup_test.go
new file mode 100644
index 000000000..ac042751a
--- /dev/null
+++ b/iampermissiongroup_test.go
@@ -0,0 +1,73 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package cloudflare_test
+
+import (
+	"context"
+	"errors"
+	"os"
+	"testing"
+
+	"github.com/cloudflare/cloudflare-go/v2"
+	"github.com/cloudflare/cloudflare-go/v2/internal/testutil"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+)
+
+func TestIamPermissionGroupListWithOptionalParams(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.PermissionGroups.List(context.TODO(), cloudflare.IamPermissionGroupListParams{
+		AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		ID:        cloudflare.F("6d7f2f5f5b1d4a0e9081fdc98d432fd1"),
+		Label:     cloudflare.F("labelOfThePermissionGroup"),
+		Name:      cloudflare.F("NameOfThePermissionGroup"),
+		Page:      cloudflare.F(1.000000),
+		PerPage:   cloudflare.F(5.000000),
+	})
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestIamPermissionGroupGet(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.PermissionGroups.Get(
+		context.TODO(),
+		"6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+		cloudflare.IamPermissionGroupGetParams{
+			AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		},
+	)
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
diff --git a/iamresourcegroup_test.go b/iamresourcegroup_test.go
new file mode 100644
index 000000000..deb1b6cfb
--- /dev/null
+++ b/iamresourcegroup_test.go
@@ -0,0 +1,181 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package cloudflare_test
+
+import (
+	"context"
+	"errors"
+	"os"
+	"testing"
+
+	"github.com/cloudflare/cloudflare-go/v2"
+	"github.com/cloudflare/cloudflare-go/v2/internal/testutil"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+)
+
+func TestIamResourceGroupNewWithOptionalParams(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.ResourceGroups.New(context.TODO(), cloudflare.IamResourceGroupNewParams{
+		AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		Scope: cloudflare.F(cloudflare.IamResourceGroupNewParamsScope{
+			Key: cloudflare.F("com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4"),
+			Objects: cloudflare.F([]cloudflare.IamResourceGroupNewParamsScopeObject{{
+				Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+			}, {
+				Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+			}, {
+				Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+			}}),
+		}),
+		Meta: cloudflare.F[any](map[string]interface{}{
+			"editable": "false",
+		}),
+	})
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestIamResourceGroupUpdateWithOptionalParams(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.ResourceGroups.Update(
+		context.TODO(),
+		"6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+		cloudflare.IamResourceGroupUpdateParams{
+			AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+			Scope: cloudflare.F(cloudflare.IamResourceGroupUpdateParamsScope{
+				Key: cloudflare.F("com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4"),
+				Objects: cloudflare.F([]cloudflare.IamResourceGroupUpdateParamsScopeObject{{
+					Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+				}, {
+					Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+				}, {
+					Key: cloudflare.F("com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"),
+				}}),
+			}),
+			Meta: cloudflare.F[any](map[string]interface{}{
+				"editable": "false",
+			}),
+		},
+	)
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestIamResourceGroupListWithOptionalParams(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.ResourceGroups.List(context.TODO(), cloudflare.IamResourceGroupListParams{
+		AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		ID:        cloudflare.F("6d7f2f5f5b1d4a0e9081fdc98d432fd1"),
+		Name:      cloudflare.F("NameOfTheResourceGroup"),
+		Page:      cloudflare.F(1.000000),
+		PerPage:   cloudflare.F(5.000000),
+	})
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestIamResourceGroupDelete(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.ResourceGroups.Delete(
+		context.TODO(),
+		"6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+		cloudflare.IamResourceGroupDeleteParams{
+			AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		},
+	)
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestIamResourceGroupGet(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.Iam.ResourceGroups.Get(
+		context.TODO(),
+		"6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+		cloudflare.IamResourceGroupGetParams{
+			AccountID: cloudflare.F("eb78d65290b24279ba6f44721b3ea3c4"),
+		},
+	)
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
diff --git a/page_shield/cookie_test.go b/page_shield/cookie_test.go
new file mode 100644
index 000000000..44146a0cb
--- /dev/null
+++ b/page_shield/cookie_test.go
@@ -0,0 +1,83 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package page_shield_test
+
+import (
+	"context"
+	"errors"
+	"os"
+	"testing"
+
+	"github.com/cloudflare/cloudflare-go/v2"
+	"github.com/cloudflare/cloudflare-go/v2/internal/testutil"
+	"github.com/cloudflare/cloudflare-go/v2/option"
+	"github.com/cloudflare/cloudflare-go/v2/page_shield"
+)
+
+func TestCookieListWithOptionalParams(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.PageShield.Cookies.List(context.TODO(), page_shield.CookieListParams{
+		ZoneID:    cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"),
+		Direction: cloudflare.F(page_shield.CookieListParamsDirectionAsc),
+		Domain:    cloudflare.F("example.com"),
+		Export:    cloudflare.F(page_shield.CookieListParamsExportCsv),
+		Hosts:     cloudflare.F("blog.cloudflare.com,www.example*,*cloudflare.com"),
+		HTTPOnly:  cloudflare.F(true),
+		Name:      cloudflare.F("session_id"),
+		OrderBy:   cloudflare.F(page_shield.CookieListParamsOrderByFirstSeenAt),
+		Page:      cloudflare.F("2"),
+		PageURL:   cloudflare.F("example.com/page,*/checkout,example.com/*,*checkout*"),
+		Path:      cloudflare.F("/"),
+		PerPage:   cloudflare.F(100.000000),
+		SameSite:  cloudflare.F(page_shield.CookieListParamsSameSiteStrict),
+		Secure:    cloudflare.F(true),
+		Type:      cloudflare.F(page_shield.CookieListParamsTypeFirstParty),
+	})
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
+
+func TestCookieGet(t *testing.T) {
+	baseURL := "http://localhost:4010"
+	if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+		baseURL = envURL
+	}
+	if !testutil.CheckTestServer(t, baseURL) {
+		return
+	}
+	client := cloudflare.NewClient(
+		option.WithBaseURL(baseURL),
+		option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
+		option.WithAPIEmail("user@example.com"),
+	)
+	_, err := client.PageShield.Cookies.Get(
+		context.TODO(),
+		"023e105f4ecef8ad9ca31a8372d0c353",
+		page_shield.CookieGetParams{
+			ZoneID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"),
+		},
+	)
+	if err != nil {
+		var apierr *cloudflare.Error
+		if errors.As(err, &apierr) {
+			t.Log(string(apierr.DumpRequest(true)))
+		}
+		t.Fatalf("err should be nil: %s", err.Error())
+	}
+}
diff --git a/page_shield/policy_test.go b/page_shield/policy_test.go
index 429cb24e4..af4ef113e 100644
--- a/page_shield/policy_test.go
+++ b/page_shield/policy_test.go
@@ -28,12 +28,14 @@ func TestPolicyNew(t *testing.T) {
 		option.WithAPIEmail("user@example.com"),
 	)
 	_, err := client.PageShield.Policies.New(context.TODO(), page_shield.PolicyNewParams{
-		ZoneID:      cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"),
-		Action:      cloudflare.F(page_shield.PolicyNewParamsActionAllow),
-		Description: cloudflare.F("Checkout page CSP policy"),
-		Enabled:     cloudflare.F(true),
-		Expression:  cloudflare.F("ends_with(http.request.uri.path, \"/checkout\")"),
-		Value:       cloudflare.F("script-src 'none';"),
+		ZoneID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"),
+		Policy: page_shield.PolicyParam{
+			Action:      cloudflare.F(page_shield.PolicyActionAllow),
+			Description: cloudflare.F("Checkout page CSP policy"),
+			Enabled:     cloudflare.F(true),
+			Expression:  cloudflare.F("ends_with(http.request.uri.path, \"/checkout\")"),
+			Value:       cloudflare.F("script-src 'none';"),
+		},
 	})
 	if err != nil {
 		var apierr *cloudflare.Error