Repository: cloudflare/cloudflare-go
Pull request #1319 (2023-06-24 00:19:52)

Convert access application
## Description

* Converts Access Applications to the `ResourceContainer` to simplify usage
* Adds support for auto pagination for Access Applications

## Has your change been tested?

Existing test pass

## Screenshots (if appropriate):

## Types of changes

What sort of change does your code introduce/modify?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [X] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

- [X] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [X] I have added tests to cover my changes.
- [X] All new and existing tests passed.
- [X] This change is using publicly documented in [cloudflare/api-schemas](https://github.com/cloudflare/api-schemas) 
      and relies on stable APIs.

[1]: https://help.github.com/articles/closing-issues-using-keywords/



Patch:
diff --git a/.changelog/1319.txt b/.changelog/1319.txt
new file mode 100644
index 000000000..be082a586
--- /dev/null
+++ b/.changelog/1319.txt
@@ -0,0 +1,59 @@
+```release-note:breaking-change
+access_application: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_application: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_ca_certificate: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_ca_certificate: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_group: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_group: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_identity_provider: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_identity_provider: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_mutual_tls_certificates: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_mutual_tls_certificates: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_organization: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:breaking-change
+access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:enhancement
+access_policy: add support for auto pagination
+```
+
+```release-note:breaking-change
+access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
+
+```release-note:breaking-change
+access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods
+```
diff --git a/access_application.go b/access_application.go
index bd49cf2c3..1c8bd66e6 100644
--- a/access_application.go
+++ b/access_application.go
@@ -112,64 +112,122 @@ type SaasApplication struct {
 	CustomAttributes   []SAMLAttributeConfig `json:"custom_attributes,omitempty"`
 }
 
-// AccessApplications returns all applications within an account.
-//
-// API reference: https://api.cloudflare.com/#access-applications-list-access-applications
-func (api *API) AccessApplications(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]AccessApplication, ResultInfo, error) {
-	return api.accessApplications(ctx, accountID, pageOpts, AccountRouteRoot)
+type ListAccessApplicationsParams struct {
+	ResultInfo
 }
 
-// ZoneLevelAccessApplications returns all applications within a zone.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-list-access-applications
-func (api *API) ZoneLevelAccessApplications(ctx context.Context, zoneID string, pageOpts PaginationOptions) ([]AccessApplication, ResultInfo, error) {
-	return api.accessApplications(ctx, zoneID, pageOpts, ZoneRouteRoot)
+type CreateAccessApplicationParams struct {
+	AllowedIdps             []string                       `json:"allowed_idps,omitempty"`
+	AppLauncherVisible      *bool                          `json:"app_launcher_visible,omitempty"`
+	AUD                     string                         `json:"aud,omitempty"`
+	AutoRedirectToIdentity  *bool                          `json:"auto_redirect_to_identity,omitempty"`
+	CorsHeaders             *AccessApplicationCorsHeaders  `json:"cors_headers,omitempty"`
+	CustomDenyMessage       string                         `json:"custom_deny_message,omitempty"`
+	CustomDenyURL           string                         `json:"custom_deny_url,omitempty"`
+	Domain                  string                         `json:"domain"`
+	EnableBindingCookie     *bool                          `json:"enable_binding_cookie,omitempty"`
+	GatewayRules            []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"`
+	HttpOnlyCookieAttribute *bool                          `json:"http_only_cookie_attribute,omitempty"`
+	LogoURL                 string                         `json:"logo_url,omitempty"`
+	Name                    string                         `json:"name"`
+	PathCookieAttribute     *bool                          `json:"path_cookie_attribute,omitempty"`
+	PrivateAddress          string                         `json:"private_address"`
+	SaasApplication         *SaasApplication               `json:"saas_app,omitempty"`
+	SameSiteCookieAttribute string                         `json:"same_site_cookie_attribute,omitempty"`
+	SelfHostedDomains       []string                       `json:"self_hosted_domains"`
+	ServiceAuth401Redirect  *bool                          `json:"service_auth_401_redirect,omitempty"`
+	SessionDuration         string                         `json:"session_duration,omitempty"`
+	SkipInterstitial        *bool                          `json:"skip_interstitial,omitempty"`
+	Type                    AccessApplicationType          `json:"type,omitempty"`
+}
+
+type UpdateAccessApplicationParams struct {
+	ID                      string                         `json:"id,omitempty"`
+	AllowedIdps             []string                       `json:"allowed_idps,omitempty"`
+	AppLauncherVisible      *bool                          `json:"app_launcher_visible,omitempty"`
+	AUD                     string                         `json:"aud,omitempty"`
+	AutoRedirectToIdentity  *bool                          `json:"auto_redirect_to_identity,omitempty"`
+	CorsHeaders             *AccessApplicationCorsHeaders  `json:"cors_headers,omitempty"`
+	CustomDenyMessage       string                         `json:"custom_deny_message,omitempty"`
+	CustomDenyURL           string                         `json:"custom_deny_url,omitempty"`
+	Domain                  string                         `json:"domain"`
+	EnableBindingCookie     *bool                          `json:"enable_binding_cookie,omitempty"`
+	GatewayRules            []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"`
+	HttpOnlyCookieAttribute *bool                          `json:"http_only_cookie_attribute,omitempty"`
+	LogoURL                 string                         `json:"logo_url,omitempty"`
+	Name                    string                         `json:"name"`
+	PathCookieAttribute     *bool                          `json:"path_cookie_attribute,omitempty"`
+	PrivateAddress          string                         `json:"private_address"`
+	SaasApplication         *SaasApplication               `json:"saas_app,omitempty"`
+	SameSiteCookieAttribute string                         `json:"same_site_cookie_attribute,omitempty"`
+	SelfHostedDomains       []string                       `json:"self_hosted_domains"`
+	ServiceAuth401Redirect  *bool                          `json:"service_auth_401_redirect,omitempty"`
+	SessionDuration         string                         `json:"session_duration,omitempty"`
+	SkipInterstitial        *bool                          `json:"skip_interstitial,omitempty"`
+	Type                    AccessApplicationType          `json:"type,omitempty"`
 }
 
-func (api *API) accessApplications(ctx context.Context, id string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessApplication, ResultInfo, error) {
-	uri := buildURI(fmt.Sprintf("/%s/%s/access/apps", routeRoot, id), pageOpts)
+// ListAccessApplications returns all applications within an account or zone.
+//
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-list-access-applications
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-list-access-applications
+func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContainer, params ListAccessApplicationsParams) ([]AccessApplication, *ResultInfo, error) {
+	baseURL := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier)
+
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
+	}
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessApplication{}, ResultInfo{}, err
+	if params.PerPage < 1 {
+		params.PerPage = 25
 	}
 
-	var accessApplicationListResponse AccessApplicationListResponse
-	err = json.Unmarshal(res, &accessApplicationListResponse)
-	if err != nil {
-		return []AccessApplication{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	if params.Page < 1 {
+		params.Page = 1
 	}
 
-	return accessApplicationListResponse.Result, accessApplicationListResponse.ResultInfo, nil
-}
+	var applications []AccessApplication
+	var r AccessApplicationListResponse
+
+	for {
+		uri := buildURI(baseURL, params)
+
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+		applications = append(applications, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || autoPaginate {
+			break
+		}
+	}
 
-// AccessApplication returns a single application based on the
-// application ID.
-//
-// API reference: https://api.cloudflare.com/#access-applications-access-applications-details
-func (api *API) AccessApplication(ctx context.Context, accountID, applicationID string) (AccessApplication, error) {
-	return api.accessApplication(ctx, accountID, applicationID, AccountRouteRoot)
+	return applications, &r.ResultInfo, nil
 }
 
-// ZoneLevelAccessApplication returns a single zone level application based on the
-// application ID.
+// GetAccessApplication returns a single application based on the application
+// ID for either account or zone.
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-access-applications-details
-func (api *API) ZoneLevelAccessApplication(ctx context.Context, zoneID, applicationID string) (AccessApplication, error) {
-	return api.accessApplication(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) accessApplication(ctx context.Context, id, applicationID string, routeRoot RouteRoot) (AccessApplication, error) {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-get-an-access-application
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-get-an-access-application
+func (api *API) GetAccessApplication(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessApplication, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		applicationID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return AccessApplication{}, err
+		return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessApplicationDetailResponse AccessApplicationDetailResponse
@@ -183,24 +241,14 @@ func (api *API) accessApplication(ctx context.Context, id, applicationID string,
 
 // CreateAccessApplication creates a new access application.
 //
-// API reference: https://api.cloudflare.com/#access-applications-create-access-application
-func (api *API) CreateAccessApplication(ctx context.Context, accountID string, accessApplication AccessApplication) (AccessApplication, error) {
-	return api.createAccessApplication(ctx, accountID, accessApplication, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessApplication creates a new zone level access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-create-access-application
-func (api *API) CreateZoneLevelAccessApplication(ctx context.Context, zoneID string, accessApplication AccessApplication) (AccessApplication, error) {
-	return api.createAccessApplication(ctx, zoneID, accessApplication, ZoneRouteRoot)
-}
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application
+func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContainer, params CreateAccessApplicationParams) (AccessApplication, error) {
+	uri := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier)
 
-func (api *API) createAccessApplication(ctx context.Context, id string, accessApplication AccessApplication, routeRoot RouteRoot) (AccessApplication, error) {
-	uri := fmt.Sprintf("/%s/%s/access/apps", routeRoot, id)
-
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessApplication)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
-		return AccessApplication{}, err
+		return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessApplicationDetailResponse AccessApplicationDetailResponse
@@ -214,33 +262,23 @@ func (api *API) createAccessApplication(ctx context.Context, id string, accessAp
 
 // UpdateAccessApplication updates an existing access application.
 //
-// API reference: https://api.cloudflare.com/#access-applications-update-access-application
-func (api *API) UpdateAccessApplication(ctx context.Context, accountID string, accessApplication AccessApplication) (AccessApplication, error) {
-	return api.updateAccessApplication(ctx, accountID, accessApplication, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessApplication updates an existing zone level access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-update-access-application
-func (api *API) UpdateZoneLevelAccessApplication(ctx context.Context, zoneID string, accessApplication AccessApplication) (AccessApplication, error) {
-	return api.updateAccessApplication(ctx, zoneID, accessApplication, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessApplication(ctx context.Context, id string, accessApplication AccessApplication, routeRoot RouteRoot) (AccessApplication, error) {
-	if accessApplication.ID == "" {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-update-a-bookmark-application
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-update-a-bookmark-application
+func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContainer, params UpdateAccessApplicationParams) (AccessApplication, error) {
+	if params.ID == "" {
 		return AccessApplication{}, fmt.Errorf("access application ID cannot be empty")
 	}
 
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s",
-		routeRoot,
-		id,
-		accessApplication.ID,
+		rc.Level,
+		rc.Identifier,
+		params.ID,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessApplication)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
-		return AccessApplication{}, err
+		return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessApplicationDetailResponse AccessApplicationDetailResponse
@@ -254,29 +292,19 @@ func (api *API) updateAccessApplication(ctx context.Context, id string, accessAp
 
 // DeleteAccessApplication deletes an access application.
 //
-// API reference: https://api.cloudflare.com/#access-applications-delete-access-application
-func (api *API) DeleteAccessApplication(ctx context.Context, accountID, applicationID string) error {
-	return api.deleteAccessApplication(ctx, accountID, applicationID, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessApplication deletes a zone level access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-delete-access-application
-func (api *API) DeleteZoneLevelAccessApplication(ctx context.Context, zoneID, applicationID string) error {
-	return api.deleteAccessApplication(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessApplication(ctx context.Context, id, applicationID string, routeRoot RouteRoot) error {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-delete-an-access-application
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-delete-an-access-application
+func (api *API) DeleteAccessApplication(ctx context.Context, rc *ResourceContainer, applicationID string) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		applicationID,
 	)
 
 	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
-		return err
+		return fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	return nil
@@ -285,30 +313,19 @@ func (api *API) deleteAccessApplication(ctx context.Context, id, applicationID s
 // RevokeAccessApplicationTokens revokes tokens associated with an
 // access application.
 //
-// API reference: https://api.cloudflare.com/#access-applications-revoke-access-tokens
-func (api *API) RevokeAccessApplicationTokens(ctx context.Context, accountID, applicationID string) error {
-	return api.revokeAccessApplicationTokens(ctx, accountID, applicationID, AccountRouteRoot)
-}
-
-// RevokeZoneLevelAccessApplicationTokens revokes tokens associated with a zone level
-// access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-applications-revoke-access-tokens
-func (api *API) RevokeZoneLevelAccessApplicationTokens(ctx context.Context, zoneID, applicationID string) error {
-	return api.revokeAccessApplicationTokens(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) revokeAccessApplicationTokens(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) error {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-revoke-service-tokens
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-revoke-service-tokens
+func (api *API) RevokeAccessApplicationTokens(ctx context.Context, rc *ResourceContainer, applicationID string) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/revoke-tokens",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		applicationID,
 	)
 
 	_, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil)
 	if err != nil {
-		return err
+		return fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	return nil
diff --git a/access_audit_log.go b/access_audit_log.go
index bb488f634..92eb22bd8 100644
--- a/access_audit_log.go
+++ b/access_audit_log.go
@@ -48,7 +48,7 @@ func (api *API) AccessAuditLogs(ctx context.Context, accountID string, opts Acce
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return []AccessAuditLogRecord{}, err
+		return []AccessAuditLogRecord{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessAuditLogListResponse AccessAuditLogListResponse
diff --git a/access_ca_certificate.go b/access_ca_certificate.go
index 1845bdb33..a1fc12b93 100644
--- a/access_ca_certificate.go
+++ b/access_ca_certificate.go
@@ -8,7 +8,7 @@ import (
 )
 
 // AccessCACertificate is the structure of the CA certificate used for
-// short lived certificates.
+// short-lived certificates.
 type AccessCACertificate struct {
 	ID        string `json:"id"`
 	Aud       string `json:"aud"`
@@ -20,6 +20,7 @@ type AccessCACertificate struct {
 type AccessCACertificateListResponse struct {
 	Response
 	Result []AccessCACertificate `json:"result"`
+	ResultInfo
 }
 
 // AccessCACertificateResponse represents the response of a single CA
@@ -29,55 +30,65 @@ type AccessCACertificateResponse struct {
 	Result AccessCACertificate `json:"result"`
 }
 
-// AccessCACertificates returns all CA certificates within Access.
-//
-// API reference: https://api.cloudflare.com/#access-short-lived-certificates-list-short-lived-certificates
-func (api *API) AccessCACertificates(ctx context.Context, accountID string) ([]AccessCACertificate, error) {
-	return api.accessCACertificates(ctx, accountID, AccountRouteRoot)
+type ListAccessCACertificatesParams struct {
+	ResultInfo
 }
 
-// ZoneLevelAccessCACertificates returns all zone level CA certificates within Access.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-list-short-lived-certificates
-func (api *API) ZoneLevelAccessCACertificates(ctx context.Context, zoneID string) ([]AccessCACertificate, error) {
-	return api.accessCACertificates(ctx, zoneID, ZoneRouteRoot)
+type CreateAccessCACertificateParams struct {
+	ApplicationID string
 }
 
-func (api *API) accessCACertificates(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessCACertificate, error) {
-	uri := fmt.Sprintf("/%s/%s/access/apps/ca", routeRoot, id)
+// ListAccessCACertificates returns all AccessCACertificate within Access.
+//
+// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-list-short-lived-certificate-c-as
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-list-short-lived-certificate-c-as
+func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContainer, params ListAccessCACertificatesParams) ([]AccessCACertificate, *ResultInfo, error) {
+	baseURL := fmt.Sprintf("/%s/%s/access/apps/ca", rc.Level, rc.Identifier)
+
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
+	}
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessCACertificate{}, err
+	if params.PerPage < 1 {
+		params.PerPage = 25
 	}
 
-	var accessCAListResponse AccessCACertificateListResponse
-	err = json.Unmarshal(res, &accessCAListResponse)
-	if err != nil {
-		return []AccessCACertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	if params.Page < 1 {
+		params.Page = 1
 	}
 
-	return accessCAListResponse.Result, nil
-}
+	var accessCACertificates []AccessCACertificate
+	var r AccessCACertificateListResponse
+
+	for {
+		uri := buildURI(baseURL, params)
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+		accessCACertificates = append(accessCACertificates, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || autoPaginate {
+			break
+		}
+	}
 
-// AccessCACertificate returns a single CA certificate associated with an Access
-// Application.
-//
-// API reference: https://api.cloudflare.com/#access-short-lived-certificates-short-lived-certificate-details
-func (api *API) AccessCACertificate(ctx context.Context, accountID, applicationID string) (AccessCACertificate, error) {
-	return api.accessCACertificate(ctx, accountID, applicationID, AccountRouteRoot)
+	return accessCACertificates, &r.ResultInfo, nil
 }
 
-// ZoneLevelAccessCACertificate returns a single zone level CA certificate associated with an Access
-// Application.
+// GetAccessCACertificate returns a single CA certificate associated within
+// Access.
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-short-lived-certificate-details
-func (api *API) ZoneLevelAccessCACertificate(ctx context.Context, zoneID, applicationID string) (AccessCACertificate, error) {
-	return api.accessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) accessCACertificate(ctx context.Context, id, applicationID string, routeRoot RouteRoot) (AccessCACertificate, error) {
-	uri := fmt.Sprintf("/%s/%s/access/apps/%s/ca", routeRoot, id, applicationID)
+// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca
+func (api *API) GetAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessCACertificate, error) {
+	uri := fmt.Sprintf("/%s/%s/access/apps/%s/ca", rc.Level, rc.Identifier, applicationID)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
@@ -93,28 +104,16 @@ func (api *API) accessCACertificate(ctx context.Context, id, applicationID strin
 	return accessCAResponse.Result, nil
 }
 
-// CreateAccessCACertificate creates a new CA certificate for an Access
-// Application.
+// CreateAccessCACertificate creates a new CA certificate for an AccessApplication.
 //
-// API reference: https://api.cloudflare.com/#access-short-lived-certificates-create-short-lived-certificate
-func (api *API) CreateAccessCACertificate(ctx context.Context, accountID, applicationID string) (AccessCACertificate, error) {
-	return api.createAccessCACertificate(ctx, accountID, applicationID, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessCACertificate creates a new zone level CA certificate for an Access
-// Application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-create-short-lived-certificate
-func (api *API) CreateZoneLevelAccessCACertificate(ctx context.Context, zoneID string, applicationID string) (AccessCACertificate, error) {
-	return api.createAccessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) createAccessCACertificate(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) (AccessCACertificate, error) {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca
+func (api *API) CreateAccessCACertificate(ctx context.Context, rc *ResourceContainer, params CreateAccessCACertificateParams) (AccessCACertificate, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/ca",
-		routeRoot,
-		id,
-		applicationID,
+		rc.Level,
+		rc.Identifier,
+		params.ApplicationID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil)
@@ -132,26 +131,15 @@ func (api *API) createAccessCACertificate(ctx context.Context, id string, applic
 }
 
 // DeleteAccessCACertificate deletes an Access CA certificate on a defined
-// Access Application.
+// AccessApplication.
 //
-// API reference: https://api.cloudflare.com/#access-short-lived-certificates-delete-access-certificate
-func (api *API) DeleteAccessCACertificate(ctx context.Context, accountID, applicationID string) error {
-	return api.deleteAccessCACertificate(ctx, accountID, applicationID, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessCACertificate deletes a zone level Access CA certificate on a defined
-// Access Application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-delete-access-certificate
-func (api *API) DeleteZoneLevelAccessCACertificate(ctx context.Context, zoneID, applicationID string) error {
-	return api.deleteAccessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessCACertificate(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) error {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-delete-a-short-lived-certificate-ca
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-delete-a-short-lived-certificate-ca
+func (api *API) DeleteAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/ca",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		applicationID,
 	)
 
diff --git a/access_group.go b/access_group.go
index 9527e5709..c21a80eeb 100644
--- a/access_group.go
+++ b/access_group.go
@@ -21,11 +21,11 @@ type AccessGroup struct {
 	Include []interface{} `json:"include"`
 
 	// The exclude group works like a NOT logical operator. The user must
-	// not satisfy all of the rules in exclude.
+	// not satisfy all the rules in exclude.
 	Exclude []interface{} `json:"exclude"`
 
 	// The require group works like a AND logical operator. The user must
-	// satisfy all of the rules in require.
+	// satisfy all the rules in require.
 	Require []interface{} `json:"require"`
 }
 
@@ -39,7 +39,7 @@ type AccessGroupEmail struct {
 }
 
 // AccessGroupEmailDomain is used for managing access based on an email
-// domain domain such as `example.com` instead of individual addresses.
+// domain such as `example.com` instead of individual addresses.
 type AccessGroupEmailDomain struct {
 	EmailDomain struct {
 		Domain string `json:"domain"`
@@ -203,69 +203,102 @@ type AccessGroupDetailResponse struct {
 	Result   AccessGroup `json:"result"`
 }
 
-// AccessGroups returns all access groups for an access application.
-//
-// API reference: https://api.cloudflare.com/#access-groups-list-access-groups
-func (api *API) AccessGroups(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]AccessGroup, ResultInfo, error) {
-	return api.accessGroups(ctx, accountID, pageOpts, AccountRouteRoot)
+type ListAccessGroupsParams struct {
+	ResultInfo
 }
 
-// ZoneLevelAccessGroups returns all zone level access groups for an access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-groups-list-access-groups
-func (api *API) ZoneLevelAccessGroups(ctx context.Context, zoneID string, pageOpts PaginationOptions) ([]AccessGroup, ResultInfo, error) {
-	return api.accessGroups(ctx, zoneID, pageOpts, ZoneRouteRoot)
+type CreateAccessGroupParams struct {
+	Name string `json:"name"`
+
+	// The include group works like an OR logical operator. The user must
+	// satisfy one of the rules.
+	Include []interface{} `json:"include"`
+
+	// The exclude group works like a NOT logical operator. The user must
+	// not satisfy all the rules in exclude.
+	Exclude []interface{} `json:"exclude"`
+
+	// The require group works like a AND logical operator. The user must
+	// satisfy all the rules in require.
+	Require []interface{} `json:"require"`
 }
 
-func (api *API) accessGroups(ctx context.Context, id string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessGroup, ResultInfo, error) {
-	uri := buildURI(
-		fmt.Sprintf(
-			"/%s/%s/access/groups",
-			routeRoot,
-			id,
-		),
-		pageOpts,
-	)
+type UpdateAccessGroupParams struct {
+	ID   string `json:"id,omitempty"`
+	Name string `json:"name"`
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessGroup{}, ResultInfo{}, err
-	}
+	// The include group works like an OR logical operator. The user must
+	// satisfy one of the rules.
+	Include []interface{} `json:"include"`
 
-	var accessGroupListResponse AccessGroupListResponse
-	err = json.Unmarshal(res, &accessGroupListResponse)
-	if err != nil {
-		return []AccessGroup{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
-	}
+	// The exclude group works like a NOT logical operator. The user must
+	// not satisfy all the rules in exclude.
+	Exclude []interface{} `json:"exclude"`
 
-	return accessGroupListResponse.Result, accessGroupListResponse.ResultInfo, nil
+	// The require group works like a AND logical operator. The user must
+	// satisfy all the rules in require.
+	Require []interface{} `json:"require"`
 }
 
-// AccessGroup returns a single group based on the group ID.
+// ListAccessGroups returns all access groups for an access application.
 //
-// API reference: https://api.cloudflare.com/#access-groups-access-group-details
-func (api *API) AccessGroup(ctx context.Context, accountID, groupID string) (AccessGroup, error) {
-	return api.accessGroup(ctx, accountID, groupID, AccountRouteRoot)
-}
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-list-access-groups
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-list-access-groups
+func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, params ListAccessGroupsParams) ([]AccessGroup, *ResultInfo, error) {
+	baseURL := fmt.Sprintf("/%s/%s/access/groups", rc.Level, rc.Identifier)
+
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
+	}
 
-// ZoneLevelAccessGroup returns a single zone level group based on the group ID.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-groups-access-group-details
-func (api *API) ZoneLevelAccessGroup(ctx context.Context, zoneID, groupID string) (AccessGroup, error) {
-	return api.accessGroup(ctx, zoneID, groupID, ZoneRouteRoot)
+	if params.PerPage < 1 {
+		params.PerPage = 25
+	}
+
+	if params.Page < 1 {
+		params.Page = 1
+	}
+
+	var accessGroups []AccessGroup
+	var r AccessGroupListResponse
+
+	for {
+		uri := buildURI(baseURL, params)
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+		accessGroups = append(accessGroups, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || autoPaginate {
+			break
+		}
+	}
+
+	return accessGroups, &r.ResultInfo, nil
 }
 
-func (api *API) accessGroup(ctx context.Context, id, groupID string, routeRoot RouteRoot) (AccessGroup, error) {
+// GetAccessGroup returns a single group based on the group ID.
+//
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-get-an-access-group
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-get-an-access-group
+func (api *API) GetAccessGroup(ctx context.Context, rc *ResourceContainer, groupID string) (AccessGroup, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/groups/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		groupID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return AccessGroup{}, err
+		return AccessGroup{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessGroupDetailResponse AccessGroupDetailResponse
@@ -279,28 +312,18 @@ func (api *API) accessGroup(ctx context.Context, id, groupID string, routeRoot R
 
 // CreateAccessGroup creates a new access group.
 //
-// API reference: https://api.cloudflare.com/#access-groups-create-access-group
-func (api *API) CreateAccessGroup(ctx context.Context, accountID string, accessGroup AccessGroup) (AccessGroup, error) {
-	return api.createAccessGroup(ctx, accountID, accessGroup, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessGroup creates a new zone level access group.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-groups-create-access-group
-func (api *API) CreateZoneLevelAccessGroup(ctx context.Context, zoneID string, accessGroup AccessGroup) (AccessGroup, error) {
-	return api.createAccessGroup(ctx, zoneID, accessGroup, ZoneRouteRoot)
-}
-
-func (api *API) createAccessGroup(ctx context.Context, id string, accessGroup AccessGroup, routeRoot RouteRoot) (AccessGroup, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-create-an-access-group
+// Zone API Reference:https://developers.cloudflare.com/api/operations/zone-level-access-groups-create-an-access-group
+func (api *API) CreateAccessGroup(ctx context.Context, rc *ResourceContainer, params CreateAccessGroupParams) (AccessGroup, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/groups",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessGroup)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
-		return AccessGroup{}, err
+		return AccessGroup{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessGroupDetailResponse AccessGroupDetailResponse
@@ -314,31 +337,21 @@ func (api *API) createAccessGroup(ctx context.Context, id string, accessGroup Ac
 
 // UpdateAccessGroup updates an existing access group.
 //
-// API reference: https://api.cloudflare.com/#access-groups-update-access-group
-func (api *API) UpdateAccessGroup(ctx context.Context, accountID string, accessGroup AccessGroup) (AccessGroup, error) {
-	return api.updateAccessGroup(ctx, accountID, accessGroup, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessGroup updates an existing zone level access group.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-groups-update-access-group
-func (api *API) UpdateZoneLevelAccessGroup(ctx context.Context, zoneID string, accessGroup AccessGroup) (AccessGroup, error) {
-	return api.updateAccessGroup(ctx, zoneID, accessGroup, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessGroup(ctx context.Context, id string, accessGroup AccessGroup, routeRoot RouteRoot) (AccessGroup, error) {
-	if accessGroup.ID == "" {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-update-an-access-group
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-update-an-access-group
+func (api *API) UpdateAccessGroup(ctx context.Context, rc *ResourceContainer, params UpdateAccessGroupParams) (AccessGroup, error) {
+	if params.ID == "" {
 		return AccessGroup{}, fmt.Errorf("access group ID cannot be empty")
 	}
 
 	uri := fmt.Sprintf(
 		"/%s/%s/access/groups/%s",
-		routeRoot,
-		id,
-		accessGroup.ID,
+		rc.Level,
+		rc.Identifier,
+		params.ID,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessGroup)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
 		return AccessGroup{}, err
 	}
@@ -352,31 +365,21 @@ func (api *API) updateAccessGroup(ctx context.Context, id string, accessGroup Ac
 	return accessGroupDetailResponse.Result, nil
 }
 
-// DeleteAccessGroup deletes an access group.
-//
-// API reference: https://api.cloudflare.com/#access-groups-delete-access-group
-func (api *API) DeleteAccessGroup(ctx context.Context, accountID, groupID string) error {
-	return api.deleteAccessGroup(ctx, accountID, groupID, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessGroup deletes a zone level access group.
+// DeleteAccessGroup deletes an access group
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-groups-delete-access-group
-func (api *API) DeleteZoneLevelAccessGroup(ctx context.Context, zoneID, groupID string) error {
-	return api.deleteAccessGroup(ctx, zoneID, groupID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessGroup(ctx context.Context, id string, groupID string, routeRoot RouteRoot) error {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-delete-an-access-group
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-delete-an-access-group
+func (api *API) DeleteAccessGroup(ctx context.Context, rc *ResourceContainer, groupID string) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/groups/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		groupID,
 	)
 
 	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
-		return err
+		return fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	return nil
diff --git a/access_identity_provider.go b/access_identity_provider.go
index 4d21ad38a..c248bc896 100644
--- a/access_identity_provider.go
+++ b/access_identity_provider.go
@@ -59,79 +59,101 @@ type AccessIdentityProviderScimConfiguration struct {
 // Access Identity Providers.
 type AccessIdentityProvidersListResponse struct {
 	Response
-	Result []AccessIdentityProvider `json:"result"`
+	Result     []AccessIdentityProvider `json:"result"`
+	ResultInfo `json:"result_info"`
 }
 
-// AccessIdentityProviderListResponse is the API response for a single
+// AccessIdentityProviderResponse is the API response for a single
 // Access Identity Provider.
-type AccessIdentityProviderListResponse struct {
+type AccessIdentityProviderResponse struct {
 	Response
 	Result AccessIdentityProvider `json:"result"`
 }
 
-// AccessIdentityProviders returns all Access Identity Providers for an
-// account.
-//
-// API reference: https://api.cloudflare.com/#access-identity-providers-list-access-identity-providers
-func (api *API) AccessIdentityProviders(ctx context.Context, accountID string) ([]AccessIdentityProvider, error) {
-	return api.accessIdentityProviders(ctx, accountID, AccountRouteRoot)
+type ListAccessIdentityProvidersParams struct {
+	ResultInfo
 }
 
-// ZoneLevelAccessIdentityProviders returns all Access Identity Providers for an
-// account.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-list-access-identity-providers
-func (api *API) ZoneLevelAccessIdentityProviders(ctx context.Context, zoneID string) ([]AccessIdentityProvider, error) {
-	return api.accessIdentityProviders(ctx, zoneID, ZoneRouteRoot)
+type CreateAccessIdentityProviderParams struct {
+	Name       string                                  `json:"name"`
+	Type       string                                  `json:"type"`
+	Config     AccessIdentityProviderConfiguration     `json:"config"`
+	ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"`
 }
 
-func (api *API) accessIdentityProviders(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessIdentityProvider, error) {
-	uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id)
+type UpdateAccessIdentityProviderParams struct {
+	ID         string                                  `json:"-"`
+	Name       string                                  `json:"name"`
+	Type       string                                  `json:"type"`
+	Config     AccessIdentityProviderConfiguration     `json:"config"`
+	ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"`
+}
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessIdentityProvider{}, err
+// ListAccessIdentityProviders returns all Access Identity Providers for an
+// account or zone.
+//
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-list-access-identity-providers
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-list-access-identity-providers
+func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceContainer, params ListAccessIdentityProvidersParams) ([]AccessIdentityProvider, *ResultInfo, error) {
+	baseURL := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier)
+
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
 	}
 
-	var accessIdentityProviderResponse AccessIdentityProvidersListResponse
-	err = json.Unmarshal(res, &accessIdentityProviderResponse)
-	if err != nil {
-		return []AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	if params.PerPage < 1 {
+		params.PerPage = 25
 	}
 
-	return accessIdentityProviderResponse.Result, nil
-}
+	if params.Page < 1 {
+		params.Page = 1
+	}
 
-// AccessIdentityProviderDetails returns a single Access Identity
-// Provider for an account.
-//
-// API reference: https://api.cloudflare.com/#access-identity-providers-access-identity-providers-details
-func (api *API) AccessIdentityProviderDetails(ctx context.Context, accountID, identityProviderID string) (AccessIdentityProvider, error) {
-	return api.accessIdentityProviderDetails(ctx, accountID, identityProviderID, AccountRouteRoot)
-}
+	var accessProviders []AccessIdentityProvider
+	var r AccessIdentityProvidersListResponse
+
+	for {
+		uri := buildURI(baseURL, params)
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+
+		accessProviders = append(accessProviders, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || !autoPaginate {
+			break
+		}
+	}
 
-// ZoneLevelAccessIdentityProviderDetails returns a single zone level Access Identity
-// Provider for an account.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-access-identity-providers-details
-func (api *API) ZoneLevelAccessIdentityProviderDetails(ctx context.Context, zoneID, identityProviderID string) (AccessIdentityProvider, error) {
-	return api.accessIdentityProviderDetails(ctx, zoneID, identityProviderID, ZoneRouteRoot)
+	return accessProviders, &r.ResultInfo, nil
 }
 
-func (api *API) accessIdentityProviderDetails(ctx context.Context, id string, identityProviderID string, routeRoot RouteRoot) (AccessIdentityProvider, error) {
+// GetAccessIdentityProvider returns a single Access Identity
+// Provider for an account or zone.
+//
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-get-an-access-identity-provider
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-get-an-access-identity-provider
+func (api *API) GetAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderID string) (AccessIdentityProvider, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/identity_providers/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		identityProviderID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return AccessIdentityProvider{}, err
+		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
-	var accessIdentityProviderResponse AccessIdentityProviderListResponse
+	var accessIdentityProviderResponse AccessIdentityProviderResponse
 	err = json.Unmarshal(res, &accessIdentityProviderResponse)
 	if err != nil {
 		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
@@ -142,27 +164,17 @@ func (api *API) accessIdentityProviderDetails(ctx context.Context, id string, id
 
 // CreateAccessIdentityProvider creates a new Access Identity Provider.
 //
-// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
-func (api *API) CreateAccessIdentityProvider(ctx context.Context, accountID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
-	return api.createAccessIdentityProvider(ctx, accountID, identityProviderConfiguration, AccountRouteRoot)
-}
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-add-an-access-identity-provider
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-add-an-access-identity-provider
+func (api *API) CreateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, params CreateAccessIdentityProviderParams) (AccessIdentityProvider, error) {
+	uri := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier)
 
-// CreateZoneLevelAccessIdentityProvider creates a new zone level Access Identity Provider.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-create-access-identity-provider
-func (api *API) CreateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
-	return api.createAccessIdentityProvider(ctx, zoneID, identityProviderConfiguration, ZoneRouteRoot)
-}
-
-func (api *API) createAccessIdentityProvider(ctx context.Context, id string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) {
-	uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id)
-
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, identityProviderConfiguration)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
-		return AccessIdentityProvider{}, err
+		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
-	var accessIdentityProviderResponse AccessIdentityProviderListResponse
+	var accessIdentityProviderResponse AccessIdentityProviderResponse
 	err = json.Unmarshal(res, &accessIdentityProviderResponse)
 	if err != nil {
 		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
@@ -174,33 +186,22 @@ func (api *API) createAccessIdentityProvider(ctx context.Context, id string, ide
 // UpdateAccessIdentityProvider updates an existing Access Identity
 // Provider.
 //
-// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
-func (api *API) UpdateAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
-	return api.updateAccessIdentityProvider(ctx, accountID, identityProviderUUID, identityProviderConfiguration, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessIdentityProvider updates an existing zone level Access Identity
-// Provider.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-update-access-identity-provider
-func (api *API) UpdateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
-	return api.updateAccessIdentityProvider(ctx, zoneID, identityProviderUUID, identityProviderConfiguration, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-update-an-access-identity-provider
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-update-an-access-identity-provider
+func (api *API) UpdateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, params UpdateAccessIdentityProviderParams) (AccessIdentityProvider, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/identity_providers/%s",
-		routeRoot,
-		id,
-		identityProviderUUID,
+		rc.Level,
+		rc.Identifier,
+		params.ID,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, identityProviderConfiguration)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
 		return AccessIdentityProvider{}, err
 	}
 
-	var accessIdentityProviderResponse AccessIdentityProviderListResponse
+	var accessIdentityProviderResponse AccessIdentityProviderResponse
 	err = json.Unmarshal(res, &accessIdentityProviderResponse)
 	if err != nil {
 		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
@@ -211,32 +212,22 @@ func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, ide
 
 // DeleteAccessIdentityProvider deletes an Access Identity Provider.
 //
-// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
-func (api *API) DeleteAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string) (AccessIdentityProvider, error) {
-	return api.deleteAccessIdentityProvider(ctx, accountID, identityProviderUUID, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessIdentityProvider deletes a zone level Access Identity Provider.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-delete-access-identity-provider
-func (api *API) DeleteZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string) (AccessIdentityProvider, error) {
-	return api.deleteAccessIdentityProvider(ctx, zoneID, identityProviderUUID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, routeRoot RouteRoot) (AccessIdentityProvider, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-delete-an-access-identity-provider
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-delete-an-access-identity-provider
+func (api *API) DeleteAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderUUID string) (AccessIdentityProvider, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/identity_providers/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		identityProviderUUID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
-		return AccessIdentityProvider{}, err
+		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
-	var accessIdentityProviderResponse AccessIdentityProviderListResponse
+	var accessIdentityProviderResponse AccessIdentityProviderResponse
 	err = json.Unmarshal(res, &accessIdentityProviderResponse)
 	if err != nil {
 		return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
diff --git a/access_mutual_tls_certificates.go b/access_mutual_tls_certificates.go
index af1eef535..ae80f9801 100644
--- a/access_mutual_tls_certificates.go
+++ b/access_mutual_tls_certificates.go
@@ -25,7 +25,8 @@ type AccessMutualTLSCertificate struct {
 // Mutual TLS certificates.
 type AccessMutualTLSCertificateListResponse struct {
 	Response
-	Result []AccessMutualTLSCertificate `json:"result"`
+	Result     []AccessMutualTLSCertificate `json:"result"`
+	ResultInfo `json:"result_info"`
 }
 
 // AccessMutualTLSCertificateDetailResponse is the API response for a single
@@ -35,70 +36,91 @@ type AccessMutualTLSCertificateDetailResponse struct {
 	Result AccessMutualTLSCertificate `json:"result"`
 }
 
-// AccessMutualTLSCertificates returns all Access TLS certificates for the account
-// level.
-//
-// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-properties
-func (api *API) AccessMutualTLSCertificates(ctx context.Context, accountID string) ([]AccessMutualTLSCertificate, error) {
-	return api.accessMutualTLSCertificates(ctx, accountID, AccountRouteRoot)
+type ListAccessMutualTLSCertificatesParams struct {
+	ResultInfo
 }
 
-// ZoneAccessMutualTLSCertificates returns all Access TLS certificates for the
-// zone level.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-properties
-func (api *API) ZoneAccessMutualTLSCertificates(ctx context.Context, zoneID string) ([]AccessMutualTLSCertificate, error) {
-	return api.accessMutualTLSCertificates(ctx, zoneID, ZoneRouteRoot)
+type CreateAccessMutualTLSCertificateParams struct {
+	ExpiresOn           time.Time `json:"expires_on,omitempty"`
+	Name                string    `json:"name,omitempty"`
+	Fingerprint         string    `json:"fingerprint,omitempty"`
+	Certificate         string    `json:"certificate,omitempty"`
+	AssociatedHostnames []string  `json:"associated_hostnames,omitempty"`
 }
 
-func (api *API) accessMutualTLSCertificates(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessMutualTLSCertificate, error) {
-	uri := fmt.Sprintf(
+type UpdateAccessMutualTLSCertificateParams struct {
+	ID                  string    `json:"-"`
+	ExpiresOn           time.Time `json:"expires_on,omitempty"`
+	Name                string    `json:"name,omitempty"`
+	Fingerprint         string    `json:"fingerprint,omitempty"`
+	Certificate         string    `json:"certificate,omitempty"`
+	AssociatedHostnames []string  `json:"associated_hostnames,omitempty"`
+}
+
+// ListAccessMutualTLSCertificates returns all Access TLS certificates
+//
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-list-mtls-certificates
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-list-mtls-certificates
+func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *ResourceContainer, params ListAccessMutualTLSCertificatesParams) ([]AccessMutualTLSCertificate, *ResultInfo, error) {
+	baseURL := fmt.Sprintf(
 		"/%s/%s/access/certificates",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessMutualTLSCertificate{}, err
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
 	}
 
-	var accessMutualTLSCertificateListResponse AccessMutualTLSCertificateListResponse
-	err = json.Unmarshal(res, &accessMutualTLSCertificateListResponse)
-	if err != nil {
-		return []AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	if params.PerPage < 1 {
+		params.PerPage = 25
 	}
 
-	return accessMutualTLSCertificateListResponse.Result, nil
-}
+	if params.Page < 1 {
+		params.Page = 1
+	}
 
-// AccessMutualTLSCertificate returns a single account level Access Mutual TLS
-// certificate.
-//
-// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-access-certificate-details
-func (api *API) AccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string) (AccessMutualTLSCertificate, error) {
-	return api.accessMutualTLSCertificate(ctx, accountID, certificateID, AccountRouteRoot)
+	var accessCertificates []AccessMutualTLSCertificate
+	var r AccessMutualTLSCertificateListResponse
+
+	for {
+		uri := buildURI(baseURL, params)
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+		accessCertificates = append(accessCertificates, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || autoPaginate {
+			break
+		}
+	}
+
+	return accessCertificates, &r.ResultInfo, nil
 }
 
-// ZoneAccessMutualTLSCertificate returns a single zone level Access Mutual TLS
+// GetAccessMutualTLSCertificate returns a single Access Mutual TLS
 // certificate.
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-access-certificate-details
-func (api *API) ZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string) (AccessMutualTLSCertificate, error) {
-	return api.accessMutualTLSCertificate(ctx, zoneID, certificateID, ZoneRouteRoot)
-}
-
-func (api *API) accessMutualTLSCertificate(ctx context.Context, id, certificateID string, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-get-an-mtls-certificate
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-get-an-mtls-certificate
+func (api *API) GetAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (AccessMutualTLSCertificate, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/certificates/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		certificateID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return AccessMutualTLSCertificate{}, err
+		return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse
@@ -110,32 +132,21 @@ func (api *API) accessMutualTLSCertificate(ctx context.Context, id, certificateI
 	return accessMutualTLSCertificateDetailResponse.Result, nil
 }
 
-// CreateAccessMutualTLSCertificate creates an account level Access TLS Mutual
-// certificate.
-//
-// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-create-access-certificate
-func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, accountID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) {
-	return api.createAccessMutualTLSCertificate(ctx, accountID, certificate, AccountRouteRoot)
-}
-
-// CreateZoneAccessMutualTLSCertificate creates a zone level Access TLS Mutual
+// CreateAccessMutualTLSCertificate creates an Access TLS Mutual
 // certificate.
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-create-access-certificate
-func (api *API) CreateZoneAccessMutualTLSCertificate(ctx context.Context, zoneID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) {
-	return api.createAccessMutualTLSCertificate(ctx, zoneID, certificate, ZoneRouteRoot)
-}
-
-func (api *API) createAccessMutualTLSCertificate(ctx context.Context, id string, certificate AccessMutualTLSCertificate, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-add-an-mtls-certificate
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-add-an-mtls-certificate
+func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, params CreateAccessMutualTLSCertificateParams) (AccessMutualTLSCertificate, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/certificates",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, certificate)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
-		return AccessMutualTLSCertificate{}, err
+		return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse
@@ -150,30 +161,19 @@ func (api *API) createAccessMutualTLSCertificate(ctx context.Context, id string,
 // UpdateAccessMutualTLSCertificate updates an account level Access TLS Mutual
 // certificate.
 //
-// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-update-access-certificate
-func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) {
-	return api.updateAccessMutualTLSCertificate(ctx, accountID, certificateID, certificate, AccountRouteRoot)
-}
-
-// UpdateZoneAccessMutualTLSCertificate updates a zone level Access TLS Mutual
-// certificate.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-update-access-certificate
-func (api *API) UpdateZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) {
-	return api.updateAccessMutualTLSCertificate(ctx, zoneID, certificateID, certificate, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessMutualTLSCertificate(ctx context.Context, id string, certificateID string, certificate AccessMutualTLSCertificate, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-update-an-mtls-certificate
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-update-an-mtls-certificate
+func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, params UpdateAccessMutualTLSCertificateParams) (AccessMutualTLSCertificate, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/certificates/%s",
-		routeRoot,
-		id,
-		certificateID,
+		rc.Level,
+		rc.Identifier,
+		params.ID,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, certificate)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
-		return AccessMutualTLSCertificate{}, err
+		return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse
@@ -185,33 +185,22 @@ func (api *API) updateAccessMutualTLSCertificate(ctx context.Context, id string,
 	return accessMutualTLSCertificateDetailResponse.Result, nil
 }
 
-// DeleteAccessMutualTLSCertificate destroys an account level Access Mutual
+// DeleteAccessMutualTLSCertificate destroys an Access Mutual
 // TLS certificate.
 //
-// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-update-access-certificate
-func (api *API) DeleteAccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string) error {
-	return api.deleteAccessMutualTLSCertificate(ctx, accountID, certificateID, AccountRouteRoot)
-}
-
-// DeleteZoneAccessMutualTLSCertificate destroys a zone level Access Mutual TLS
-// certificate.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-update-access-certificate
-func (api *API) DeleteZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string) error {
-	return api.deleteAccessMutualTLSCertificate(ctx, zoneID, certificateID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessMutualTLSCertificate(ctx context.Context, id, certificateID string, routeRoot RouteRoot) error {
+// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-delete-an-mtls-certificate
+// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-delete-an-mtls-certificate
+func (api *API) DeleteAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/certificates/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		certificateID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
-		return err
+		return fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse
diff --git a/access_organization.go b/access_organization.go
index ff2fef9de..d7f616cf5 100644
--- a/access_organization.go
+++ b/access_organization.go
@@ -47,22 +47,30 @@ type AccessOrganizationDetailResponse struct {
 	Result   AccessOrganization `json:"result"`
 }
 
-// AccessOrganization returns the Access organisation details.
-//
-// API reference: https://api.cloudflare.com/#access-organizations-access-organization-details
-func (api *API) AccessOrganization(ctx context.Context, accountID string) (AccessOrganization, ResultInfo, error) {
-	return api.accessOrganization(ctx, accountID, AccountRouteRoot)
+type GetAccessOrganizationParams struct{}
+
+type CreateAccessOrganizationParams struct {
+	Name                           string                        `json:"name"`
+	AuthDomain                     string                        `json:"auth_domain"`
+	LoginDesign                    AccessOrganizationLoginDesign `json:"login_design"`
+	IsUIReadOnly                   *bool                         `json:"is_ui_read_only,omitempty"`
+	UIReadOnlyToggleReason         string                        `json:"ui_read_only_toggle_reason,omitempty"`
+	UserSeatExpirationInactiveTime string                        `json:"user_seat_expiration_inactive_time,omitempty"`
+	AutoRedirectToIdentity         *bool                         `json:"auto_redirect_to_identity,omitempty"`
 }
 
-// ZoneLevelAccessOrganization returns the zone level Access organisation details.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-organizations-access-organization-details
-func (api *API) ZoneLevelAccessOrganization(ctx context.Context, zoneID string) (AccessOrganization, ResultInfo, error) {
-	return api.accessOrganization(ctx, zoneID, ZoneRouteRoot)
+type UpdateAccessOrganizationParams struct {
+	Name                           string                        `json:"name"`
+	AuthDomain                     string                        `json:"auth_domain"`
+	LoginDesign                    AccessOrganizationLoginDesign `json:"login_design"`
+	IsUIReadOnly                   *bool                         `json:"is_ui_read_only,omitempty"`
+	UIReadOnlyToggleReason         string                        `json:"ui_read_only_toggle_reason,omitempty"`
+	UserSeatExpirationInactiveTime string                        `json:"user_seat_expiration_inactive_time,omitempty"`
+	AutoRedirectToIdentity         *bool                         `json:"auto_redirect_to_identity,omitempty"`
 }
 
-func (api *API) accessOrganization(ctx context.Context, id string, routeRoot RouteRoot) (AccessOrganization, ResultInfo, error) {
-	uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id)
+func (api *API) GetAccessOrganization(ctx context.Context, rc *ResourceContainer, params GetAccessOrganizationParams) (AccessOrganization, ResultInfo, error) {
+	uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
@@ -78,24 +86,10 @@ func (api *API) accessOrganization(ctx context.Context, id string, routeRoot Rou
 	return accessOrganizationListResponse.Result, accessOrganizationListResponse.ResultInfo, nil
 }
 
-// CreateAccessOrganization creates the Access organisation details.
-//
-// API reference: https://api.cloudflare.com/#access-organizations-create-access-organization
-func (api *API) CreateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) {
-	return api.createAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessOrganization creates the zone level Access organisation details.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-organizations-create-access-organization
-func (api *API) CreateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) {
-	return api.createAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot)
-}
-
-func (api *API) createAccessOrganization(ctx context.Context, id string, accessOrganization AccessOrganization, routeRoot RouteRoot) (AccessOrganization, error) {
-	uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id)
+func (api *API) CreateAccessOrganization(ctx context.Context, rc *ResourceContainer, params CreateAccessOrganizationParams) (AccessOrganization, error) {
+	uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessOrganization)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
 		return AccessOrganization{}, err
 	}
@@ -111,22 +105,12 @@ func (api *API) createAccessOrganization(ctx context.Context, id string, accessO
 
 // UpdateAccessOrganization updates the Access organisation details.
 //
-// API reference: https://api.cloudflare.com/#access-organizations-update-access-organization
-func (api *API) UpdateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) {
-	return api.updateAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessOrganization updates the zone level Access organisation details.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization
-func (api *API) UpdateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) {
-	return api.updateAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessOrganization(ctx context.Context, id string, accessOrganization AccessOrganization, routeRoot RouteRoot) (AccessOrganization, error) {
-	uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id)
+// Account API reference: https://api.cloudflare.com/#access-organizations-update-access-organization
+// Zone API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization
+func (api *API) UpdateAccessOrganization(ctx context.Context, rc *ResourceContainer, params UpdateAccessOrganizationParams) (AccessOrganization, error) {
+	uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessOrganization)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
 		return AccessOrganization{}, err
 	}
diff --git a/access_policy.go b/access_policy.go
index a7823f79f..b6d10031d 100644
--- a/access_policy.go
+++ b/access_policy.go
@@ -3,11 +3,16 @@ package cloudflare
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
 )
 
+var (
+	ErrMissingApplicationID = errors.New("missing required application ID")
+)
+
 type AccessApprovalGroup struct {
 	EmailListUuid   string   `json:"email_list_uuid,omitempty"`
 	EmailAddresses  []string `json:"email_addresses,omitempty"`
@@ -35,11 +40,11 @@ type AccessPolicy struct {
 	Include []interface{} `json:"include"`
 
 	// The exclude policy works like a NOT logical operator. The user must
-	// not satisfy all of the rules in exclude.
+	// not satisfy all the rules in exclude.
 	Exclude []interface{} `json:"exclude"`
 
 	// The require policy works like a AND logical operator. The user must
-	// satisfy all of the rules in require.
+	// satisfy all the rules in require.
 	Require []interface{} `json:"require"`
 }
 
@@ -60,71 +65,115 @@ type AccessPolicyDetailResponse struct {
 	Result   AccessPolicy `json:"result"`
 }
 
-// AccessPolicies returns all access policies for an access application.
-//
-// API reference: https://api.cloudflare.com/#access-policy-list-access-policies
-func (api *API) AccessPolicies(ctx context.Context, accountID, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, ResultInfo, error) {
-	return api.accessPolicies(ctx, accountID, applicationID, pageOpts, AccountRouteRoot)
+type ListAccessPoliciesParams struct {
+	ApplicationID string `json:"-"`
+	ResultInfo
 }
 
-// ZoneLevelAccessPolicies returns all zone level access policies for an access application.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-policy-list-access-policies
-func (api *API) ZoneLevelAccessPolicies(ctx context.Context, zoneID, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, ResultInfo, error) {
-	return api.accessPolicies(ctx, zoneID, applicationID, pageOpts, ZoneRouteRoot)
+type GetAccessPolicyParams struct {
+	ApplicationID string `json:"-"`
+	PolicyID      string `json:"-"`
 }
 
-func (api *API) accessPolicies(ctx context.Context, id string, applicationID string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessPolicy, ResultInfo, error) {
-	uri := buildURI(
-		fmt.Sprintf(
-			"/%s/%s/access/apps/%s/policies",
-			routeRoot,
-			id,
-			applicationID,
-		),
-		pageOpts,
-	)
+type CreateAccessPolicyParams struct {
+	ApplicationID string `json:"-"`
 
-	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
-	if err != nil {
-		return []AccessPolicy{}, ResultInfo{}, err
-	}
+	Precedence int    `json:"precedence"`
+	Decision   string `json:"decision"`
+	Name       string `json:"name"`
 
-	var accessPolicyListResponse AccessPolicyListResponse
-	err = json.Unmarshal(res, &accessPolicyListResponse)
-	if err != nil {
-		return []AccessPolicy{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
-	}
+	IsolationRequired            *bool                 `json:"isolation_required,omitempty"`
+	PurposeJustificationRequired *bool                 `json:"purpose_justification_required,omitempty"`
+	PurposeJustificationPrompt   *string               `json:"purpose_justification_prompt,omitempty"`
+	ApprovalRequired             *bool                 `json:"approval_required,omitempty"`
+	ApprovalGroups               []AccessApprovalGroup `json:"approval_groups"`
 
-	return accessPolicyListResponse.Result, accessPolicyListResponse.ResultInfo, nil
+	// The include policy works like an OR logical operator. The user must
+	// satisfy one of the rules.
+	Include []interface{} `json:"include"`
+
+	// The exclude policy works like a NOT logical operator. The user must
+	// not satisfy all the rules in exclude.
+	Exclude []interface{} `json:"exclude"`
+
+	// The require policy works like a AND logical operator. The user must
+	// satisfy all the rules in require.
+	Require []interface{} `json:"require"`
 }
 
-// AccessPolicy returns a single policy based on the policy ID.
-//
-// API reference: https://api.cloudflare.com/#access-policy-access-policy-details
-func (api *API) AccessPolicy(ctx context.Context, accountID, applicationID, policyID string) (AccessPolicy, error) {
-	return api.accessPolicy(ctx, accountID, applicationID, policyID, AccountRouteRoot)
+type DeleteAccessPolicyParams struct {
+	ApplicationID string `json:"-"`
+	PolicyID      string `json:"-"`
 }
 
-// ZoneLevelAccessPolicy returns a single zone level policy based on the policy ID.
+// ListAccessPolicies returns all access policies for an access application.
 //
-// API reference: https://api.cloudflare.com/#zone-level-access-policy-access-policy-details
-func (api *API) ZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID, policyID string) (AccessPolicy, error) {
-	return api.accessPolicy(ctx, zoneID, applicationID, policyID, ZoneRouteRoot)
+// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-list-access-policies
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-list-access-policies
+func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, params ListAccessPoliciesParams) ([]AccessPolicy, *ResultInfo, error) {
+	if params.ApplicationID == "" {
+		return []AccessPolicy{}, &ResultInfo{}, ErrMissingApplicationID
+	}
+
+	baseURL := fmt.Sprintf(
+		"/%s/%s/access/apps/%s/policies",
+		rc.Level,
+		rc.Identifier,
+		params.ApplicationID,
+	)
+
+	autoPaginate := true
+	if params.PerPage >= 1 || params.Page >= 1 {
+		autoPaginate = false
+	}
+
+	if params.PerPage < 1 {
+		params.PerPage = 25
+	}
+
+	if params.Page < 1 {
+		params.Page = 1
+	}
+
+	var accessPolicies []AccessPolicy
+	var r AccessPolicyListResponse
+	for {
+		uri := buildURI(baseURL, params)
+		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+		if err != nil {
+			return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
+		}
+
+		err = json.Unmarshal(res, &r)
+		if err != nil {
+			return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+		}
+		accessPolicies = append(accessPolicies, r.Result...)
+		params.ResultInfo = r.ResultInfo.Next()
+		if params.ResultInfo.Done() || autoPaginate {
+			break
+		}
+	}
+
+	return accessPolicies, &r.ResultInfo, nil
 }
 
-func (api *API) accessPolicy(ctx context.Context, id string, applicationID string, policyID string, routeRoot RouteRoot) (AccessPolicy, error) {
+// GetAccessPolicy returns a single policy based on the policy ID.
+//
+// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-get-an-access-policy
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-get-an-access-policy
+func (api *API) GetAccessPolicy(ctx context.Context, rc *ResourceContainer, params GetAccessPolicyParams) (AccessPolicy, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/policies/%s",
-		routeRoot,
-		id,
-		applicationID,
-		policyID,
+		rc.Level,
+		rc.Identifier,
+		params.ApplicationID,
+		params.PolicyID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
-		return AccessPolicy{}, err
+		return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessPolicyDetailResponse AccessPolicyDetailResponse
@@ -138,29 +187,19 @@ func (api *API) accessPolicy(ctx context.Context, id string, applicationID strin
 
 // CreateAccessPolicy creates a new access policy.
 //
-// API reference: https://api.cloudflare.com/#access-policy-create-access-policy
-func (api *API) CreateAccessPolicy(ctx context.Context, accountID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) {
-	return api.createAccessPolicy(ctx, accountID, applicationID, accessPolicy, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessPolicy creates a new zone level access policy.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-policy-create-access-policy
-func (api *API) CreateZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) {
-	return api.createAccessPolicy(ctx, zoneID, applicationID, accessPolicy, ZoneRouteRoot)
-}
-
-func (api *API) createAccessPolicy(ctx context.Context, id, applicationID string, accessPolicy AccessPolicy, routeRoot RouteRoot) (AccessPolicy, error) {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-create-an-access-policy
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-create-an-access-policy
+func (api *API) CreateAccessPolicy(ctx context.Context, rc *ResourceContainer, params CreateAccessPolicyParams) (AccessPolicy, error) {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/policies",
-		routeRoot,
-		id,
-		applicationID,
+		rc.Level,
+		rc.Identifier,
+		params.ApplicationID,
 	)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessPolicy)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
-		return AccessPolicy{}, err
+		return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessPolicyDetailResponse AccessPolicyDetailResponse
@@ -174,33 +213,23 @@ func (api *API) createAccessPolicy(ctx context.Context, id, applicationID string
 
 // UpdateAccessPolicy updates an existing access policy.
 //
-// API reference: https://api.cloudflare.com/#access-policy-update-access-policy
-func (api *API) UpdateAccessPolicy(ctx context.Context, accountID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) {
-	return api.updateAccessPolicy(ctx, accountID, applicationID, accessPolicy, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessPolicy updates an existing zone level access policy.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-policy-update-access-policy
-func (api *API) UpdateZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) {
-	return api.updateAccessPolicy(ctx, zoneID, applicationID, accessPolicy, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessPolicy(ctx context.Context, id, applicationID string, accessPolicy AccessPolicy, routeRoot RouteRoot) (AccessPolicy, error) {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-update-an-access-policy
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-update-an-access-policy
+func (api *API) UpdateAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) {
 	if accessPolicy.ID == "" {
 		return AccessPolicy{}, fmt.Errorf("access policy ID cannot be empty")
 	}
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/policies/%s",
-		routeRoot,
-		id,
+		rc.Level,
+		rc.Identifier,
 		applicationID,
 		accessPolicy.ID,
 	)
 
 	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessPolicy)
 	if err != nil {
-		return AccessPolicy{}, err
+		return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	var accessPolicyDetailResponse AccessPolicyDetailResponse
@@ -214,30 +243,20 @@ func (api *API) updateAccessPolicy(ctx context.Context, id, applicationID string
 
 // DeleteAccessPolicy deletes an access policy.
 //
-// API reference: https://api.cloudflare.com/#access-policy-update-access-policy
-func (api *API) DeleteAccessPolicy(ctx context.Context, accountID, applicationID, accessPolicyID string) error {
-	return api.deleteAccessPolicy(ctx, accountID, applicationID, accessPolicyID, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessPolicy deletes a zone level access policy.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-policy-delete-access-policy
-func (api *API) DeleteZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID, accessPolicyID string) error {
-	return api.deleteAccessPolicy(ctx, zoneID, applicationID, accessPolicyID, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessPolicy(ctx context.Context, id, applicationID, accessPolicyID string, routeRoot RouteRoot) error {
+// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-delete-an-access-policy
+// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-delete-an-access-policy
+func (api *API) DeleteAccessPolicy(ctx context.Context, rc *ResourceContainer, params DeleteAccessPolicyParams) error {
 	uri := fmt.Sprintf(
 		"/%s/%s/access/apps/%s/policies/%s",
-		routeRoot,
-		id,
-		applicationID,
-		accessPolicyID,
+		rc.Level,
+		rc.Identifier,
+		params.ApplicationID,
+		params.PolicyID,
 	)
 
 	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
-		return err
+		return fmt.Errorf("%s: %w", errMakeRequestError, err)
 	}
 
 	return nil
diff --git a/access_service_tokens.go b/access_service_tokens.go
index d0f5314f2..d3a4d66f8 100644
--- a/access_service_tokens.go
+++ b/access_service_tokens.go
@@ -3,11 +3,16 @@ package cloudflare
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
 )
 
+var (
+	ErrMissingServiceTokenUUID = errors.New("missing required service token UUID")
+)
+
 // AccessServiceToken represents an Access Service Token.
 type AccessServiceToken struct {
 	ClientID  string     `json:"client_id"`
@@ -119,22 +124,19 @@ type AccessServiceTokensRotateSecretDetailResponse struct {
 	Result   AccessServiceTokenRotateResponse `json:"result"`
 }
 
-// AccessServiceTokens returns all Access Service Tokens for an account.
-//
-// API reference: https://api.cloudflare.com/#access-service-tokens-list-access-service-tokens
-func (api *API) AccessServiceTokens(ctx context.Context, accountID string) ([]AccessServiceToken, ResultInfo, error) {
-	return api.accessServiceTokens(ctx, accountID, AccountRouteRoot)
+type ListAccessServiceTokensParams struct{}
+
+type CreateAccessServiceTokenParams struct {
+	Name string `json:"name"`
 }
 
-// ZoneLevelAccessServiceTokens returns all Access Service Tokens for a zone.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-list-access-service-tokens
-func (api *API) ZoneLevelAccessServiceTokens(ctx context.Context, zoneID string) ([]AccessServiceToken, ResultInfo, error) {
-	return api.accessServiceTokens(ctx, zoneID, ZoneRouteRoot)
+type UpdateAccessServiceTokenParams struct {
+	Name string `json:"name"`
+	UUID string `json:"-"`
 }
 
-func (api *API) accessServiceTokens(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessServiceToken, ResultInfo, error) {
-	uri := fmt.Sprintf("/%s/%s/access/service_tokens", routeRoot, id)
+func (api *API) ListAccessServiceTokens(ctx context.Context, rc *ResourceContainer, params ListAccessServiceTokensParams) ([]AccessServiceToken, ResultInfo, error) {
+	uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier)
 
 	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {
@@ -150,27 +152,9 @@ func (api *API) accessServiceTokens(ctx context.Context, id string, routeRoot Ro
 	return accessServiceTokensListResponse.Result, accessServiceTokensListResponse.ResultInfo, nil
 }
 
-// CreateAccessServiceToken creates a new Access Service Token for an account.
-//
-// API reference: https://api.cloudflare.com/#access-service-tokens-create-access-service-token
-func (api *API) CreateAccessServiceToken(ctx context.Context, accountID, name string) (AccessServiceTokenCreateResponse, error) {
-	return api.createAccessServiceToken(ctx, accountID, name, AccountRouteRoot)
-}
-
-// CreateZoneLevelAccessServiceToken creates a new Access Service Token for a zone.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-create-access-service-token
-func (api *API) CreateZoneLevelAccessServiceToken(ctx context.Context, zoneID, name string) (AccessServiceTokenCreateResponse, error) {
-	return api.createAccessServiceToken(ctx, zoneID, name, ZoneRouteRoot)
-}
-
-func (api *API) createAccessServiceToken(ctx context.Context, id, name string, routeRoot RouteRoot) (AccessServiceTokenCreateResponse, error) {
-	uri := fmt.Sprintf("/%s/%s/access/service_tokens", routeRoot, id)
-	marshalledName, _ := json.Marshal(struct {
-		Name string `json:"name"`
-	}{name})
-
-	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, marshalledName)
+func (api *API) CreateAccessServiceToken(ctx context.Context, rc *ResourceContainer, params CreateAccessServiceTokenParams) (AccessServiceTokenCreateResponse, error) {
+	uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier)
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 
 	if err != nil {
 		return AccessServiceTokenCreateResponse{}, err
@@ -185,30 +169,14 @@ func (api *API) createAccessServiceToken(ctx context.Context, id, name string, r
 	return accessServiceTokenCreation.Result, nil
 }
 
-// UpdateAccessServiceToken updates an existing Access Service Token for an
-// account.
-//
-// API reference: https://api.cloudflare.com/#access-service-tokens-update-access-service-token
-func (api *API) UpdateAccessServiceToken(ctx context.Context, accountID, uuid, name string) (AccessServiceTokenUpdateResponse, error) {
-	return api.updateAccessServiceToken(ctx, accountID, uuid, name, AccountRouteRoot)
-}
-
-// UpdateZoneLevelAccessServiceToken updates an existing Access Service Token for a
-// zone.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-update-access-service-token
-func (api *API) UpdateZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid, name string) (AccessServiceTokenUpdateResponse, error) {
-	return api.updateAccessServiceToken(ctx, zoneID, uuid, name, ZoneRouteRoot)
-}
-
-func (api *API) updateAccessServiceToken(ctx context.Context, id, uuid, name string, routeRoot RouteRoot) (AccessServiceTokenUpdateResponse, error) {
-	uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", routeRoot, id, uuid)
+func (api *API) UpdateAccessServiceToken(ctx context.Context, rc *ResourceContainer, params UpdateAccessServiceTokenParams) (AccessServiceTokenUpdateResponse, error) {
+	if params.UUID == "" {
+		return AccessServiceTokenUpdateResponse{}, ErrMissingServiceTokenUUID
+	}
 
-	marshalledName, _ := json.Marshal(struct {
-		Name string `json:"name"`
-	}{name})
+	uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, params.UUID)
 
-	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, marshalledName)
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
 	if err != nil {
 		return AccessServiceTokenUpdateResponse{}, err
 	}
@@ -222,24 +190,8 @@ func (api *API) updateAccessServiceToken(ctx context.Context, id, uuid, name str
 	return accessServiceTokenUpdate.Result, nil
 }
 
-// DeleteAccessServiceToken removes an existing Access Service Token for an
-// account.
-//
-// API reference: https://api.cloudflare.com/#access-service-tokens-delete-access-service-token
-func (api *API) DeleteAccessServiceToken(ctx context.Context, accountID, uuid string) (AccessServiceTokenUpdateResponse, error) {
-	return api.deleteAccessServiceToken(ctx, accountID, uuid, AccountRouteRoot)
-}
-
-// DeleteZoneLevelAccessServiceToken removes an existing Access Service Token for a
-// zone.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-delete-access-service-token
-func (api *API) DeleteZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid string) (AccessServiceTokenUpdateResponse, error) {
-	return api.deleteAccessServiceToken(ctx, zoneID, uuid, ZoneRouteRoot)
-}
-
-func (api *API) deleteAccessServiceToken(ctx context.Context, id, uuid string, routeRoot RouteRoot) (AccessServiceTokenUpdateResponse, error) {
-	uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", routeRoot, id, uuid)
+func (api *API) DeleteAccessServiceToken(ctx context.Context, rc *ResourceContainer, uuid string) (AccessServiceTokenUpdateResponse, error) {
+	uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, uuid)
 
 	res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
 	if err != nil {
diff --git a/access_user_tokens.go b/access_user_tokens.go
index 81f73fa30..ba32d7fbf 100644
--- a/access_user_tokens.go
+++ b/access_user_tokens.go
@@ -6,30 +6,16 @@ import (
 	"net/http"
 )
 
-type AccessUserEmail struct {
+type RevokeAccessUserTokensParams struct {
 	Email string `json:"email"`
 }
 
 // RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user
 // Access User.
-//
-// API reference: https://api.cloudflare.com/#access-organizations-revoke-all-access-tokens-for-a-user
-func (api *API) RevokeAccessUserTokens(ctx context.Context, accountID string, accessUserEmail AccessUserEmail) error {
-	return api.revokeUserTokens(ctx, accountID, accessUserEmail, AccountRouteRoot)
-}
-
-// RevokeZoneLevelAccessUserTokens revokes any outstanding tokens issued for a specific user
-// Access User.
-//
-// API reference: https://api.cloudflare.com/#zone-level-access-organizations-revoke-all-access-tokens-for-a-user
-func (api *API) RevokeZoneLevelAccessUserTokens(ctx context.Context, zoneID string, accessUserEmail AccessUserEmail) error {
-	return api.revokeUserTokens(ctx, zoneID, accessUserEmail, ZoneRouteRoot)
-}
-
-func (api *API) revokeUserTokens(ctx context.Context, id string, accessUserEmail AccessUserEmail, routeRoot RouteRoot) error {
-	uri := fmt.Sprintf("/%s/%s/access/organizations/revoke_user", routeRoot, id)
+func (api *API) RevokeAccessUserTokens(ctx context.Context, rc *ResourceContainer, params RevokeAccessUserTokensParams) error {
+	uri := fmt.Sprintf("/%s/%s/access/organizations/revoke_user", rc.Level, rc.Identifier)
 
-	_, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessUserEmail)
+	_, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
 	if err != nil {
 		return err
 	}


Test patch:
diff --git a/access_application_test.go b/access_application_test.go
index 4275f4525..3c07a5443 100644
--- a/access_application_test.go
+++ b/access_application_test.go
@@ -10,6 +10,10 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+const (
+	testAccessApplicationID = "480f4f69-1a28-4fdd-9240-1ed29f0ac1db"
+)
+
 func TestAccessApplications(t *testing.T) {
 	setup()
 	defer teardown()
@@ -83,7 +87,7 @@ func TestAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)
 
-	actual, _, err := client.AccessApplications(context.Background(), testAccountID, PaginationOptions{})
+	actual, _, err := client.ListAccessApplications(context.Background(), AccountIdentifier(testAccountID), ListAccessApplicationsParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -91,7 +95,7 @@ func TestAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler)
 
-	actual, _, err = client.ZoneLevelAccessApplications(context.Background(), testZoneID, PaginationOptions{})
+	actual, _, err = client.ListAccessApplications(context.Background(), ZoneIdentifier(testZoneID), ListAccessApplicationsParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -163,7 +167,7 @@ func TestAccessApplication(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err := client.AccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	actual, err := client.GetAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -171,7 +175,7 @@ func TestAccessApplication(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err = client.ZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	actual, err = client.GetAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -238,7 +242,7 @@ func TestCreateAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)
 
-	actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{
+	actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{
 		Name:            "Admin Site",
 		Domain:          "test.example.com/admin",
 		SessionDuration: "24h",
@@ -250,7 +254,7 @@ func TestCreateAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler)
 
-	actual, err = client.CreateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{
+	actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), CreateAccessApplicationParams{
 		Name:            "Admin Site",
 		Domain:          "test.example.com/admin",
 		SessionDuration: "24h",
@@ -296,8 +300,6 @@ func TestUpdateAccessApplication(t *testing.T) {
 		`)
 	}
 
-	createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
-	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 	fullAccessApplication := AccessApplication{
 		ID:                     "480f4f69-1a28-4fdd-9240-1ed29f0ac1db",
 		Name:                   "Admin Site",
@@ -319,9 +321,28 @@ func TestUpdateAccessApplication(t *testing.T) {
 		UpdatedAt:              &updatedAt,
 	}
 
+	params := UpdateAccessApplicationParams{
+		ID:                     "480f4f69-1a28-4fdd-9240-1ed29f0ac1db",
+		Name:                   "Admin Site",
+		Domain:                 "test.example.com/admin",
+		SelfHostedDomains:      []string{"test.example.com/admin", "test.example.com/admin2"},
+		Type:                   "self_hosted",
+		SessionDuration:        "24h",
+		AUD:                    "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
+		AllowedIdps:            []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"},
+		AutoRedirectToIdentity: BoolPtr(false),
+		EnableBindingCookie:    BoolPtr(false),
+		AppLauncherVisible:     BoolPtr(true),
+		ServiceAuth401Redirect: BoolPtr(true),
+		CustomDenyMessage:      "denied!",
+		CustomDenyURL:          "https://www.example.com",
+		LogoURL:                "https://www.example.com/example.png",
+		SkipInterstitial:       BoolPtr(true),
+	}
+
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err := client.UpdateAccessApplication(context.Background(), testAccountID, fullAccessApplication)
+	actual, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), params)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, fullAccessApplication, actual)
@@ -329,7 +350,24 @@ func TestUpdateAccessApplication(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err = client.UpdateZoneLevelAccessApplication(context.Background(), testZoneID, fullAccessApplication)
+	actual, err = client.UpdateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), UpdateAccessApplicationParams{
+		ID:                     "480f4f69-1a28-4fdd-9240-1ed29f0ac1db",
+		Name:                   "Admin Site",
+		Domain:                 "test.example.com/admin",
+		SelfHostedDomains:      []string{"test.example.com/admin", "test.example.com/admin2"},
+		Type:                   "self_hosted",
+		SessionDuration:        "24h",
+		AUD:                    "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
+		AllowedIdps:            []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"},
+		AutoRedirectToIdentity: BoolPtr(false),
+		EnableBindingCookie:    BoolPtr(false),
+		AppLauncherVisible:     BoolPtr(true),
+		ServiceAuth401Redirect: BoolPtr(true),
+		CustomDenyMessage:      "denied!",
+		CustomDenyURL:          "https://www.example.com",
+		LogoURL:                "https://www.example.com/example.png",
+		SkipInterstitial:       BoolPtr(true),
+	})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, fullAccessApplication, actual)
@@ -340,10 +378,10 @@ func TestUpdateAccessApplicationWithMissingID(t *testing.T) {
 	setup()
 	defer teardown()
 
-	_, err := client.UpdateAccessApplication(context.Background(), testZoneID, AccessApplication{})
+	_, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), UpdateAccessApplicationParams{})
 	assert.EqualError(t, err, "access application ID cannot be empty")
 
-	_, err = client.UpdateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{})
+	_, err = client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), UpdateAccessApplicationParams{})
 	assert.EqualError(t, err, "access application ID cannot be empty")
 }
 
@@ -366,12 +404,12 @@ func TestDeleteAccessApplication(t *testing.T) {
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
-	err := client.DeleteAccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	err := client.DeleteAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
-	err = client.DeleteZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	err = client.DeleteAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	assert.NoError(t, err)
 }
@@ -392,12 +430,12 @@ func TestRevokeAccessApplicationTokens(t *testing.T) {
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db/revoke-tokens", handler)
-	err := client.RevokeAccessApplicationTokens(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	err := client.RevokeAccessApplicationTokens(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db/revoke-tokens", handler)
-	err = client.RevokeZoneLevelAccessApplicationTokens(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	err = client.RevokeAccessApplicationTokens(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	assert.NoError(t, err)
 }
@@ -461,7 +499,7 @@ func TestAccessApplicationWithCORS(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err := client.AccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	actual, err := client.GetAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -469,7 +507,7 @@ func TestAccessApplicationWithCORS(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
 
-	actual, err = client.ZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
+	actual, err = client.GetAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -542,7 +580,7 @@ func TestCreatePrivateAccessApplication(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)
 
-	actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{
+	actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{
 		Name:            "Admin Site",
 		PrivateAddress:  "198.51.100.0",
 		SessionDuration: "24h",
@@ -668,7 +706,7 @@ func TestCreateSaasAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)
 
-	actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{
+	actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{
 		Name: "Admin Saas Site",
 		SaasApplication: &SaasApplication{
 			ConsumerServiceUrl: "https://examplesaas.com",
@@ -684,7 +722,7 @@ func TestCreateSaasAccessApplications(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler)
 
-	actual, err = client.CreateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{
+	actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), CreateAccessApplicationParams{
 		Name: "Admin Saas Site",
 		SaasApplication: &SaasApplication{
 			ConsumerServiceUrl: "https://saas.example.com",
diff --git a/access_ca_certificate_test.go b/access_ca_certificate_test.go
index d21141efe..bb75b90a1 100644
--- a/access_ca_certificate_test.go
+++ b/access_ca_certificate_test.go
@@ -9,7 +9,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestAcessCACertificate(t *testing.T) {
+func TestAccessCACertificate(t *testing.T) {
 	setup()
 	defer teardown()
 
@@ -35,24 +35,24 @@ func TestAcessCACertificate(t *testing.T) {
 		PublicKey: "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTI...3urg/XpGMdgaSs5ZdptUPw= open-ssh-ca@cloudflareaccess.org",
 	}
 
-	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
+	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testAccessApplicationID+"/ca", handler)
 
-	actual, err := client.AccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.GetAccessCACertificate(context.Background(), testAccountRC, testAccessApplicationID)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
 	}
 
-	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
+	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+testAccessApplicationID+"/ca", handler)
 
-	actual, err = client.ZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err = client.GetAccessCACertificate(context.Background(), testZoneRC, testAccessApplicationID)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
 	}
 }
 
-func TestAcessCACertificates(t *testing.T) {
+func TestAccessCACertificates(t *testing.T) {
 	setup()
 	defer teardown()
 
@@ -80,7 +80,7 @@ func TestAcessCACertificates(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/ca", handler)
 
-	actual, err := client.AccessCACertificates(context.Background(), testAccountID)
+	actual, _, err := client.ListAccessCACertificates(context.Background(), testAccountRC, ListAccessCACertificatesParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -88,14 +88,14 @@ func TestAcessCACertificates(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/ca", handler)
 
-	actual, err = client.ZoneLevelAccessCACertificates(context.Background(), testZoneID)
+	actual, _, err = client.ListAccessCACertificates(context.Background(), testZoneRC, ListAccessCACertificatesParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
 	}
 }
 
-func TestCreateAcessCACertificates(t *testing.T) {
+func TestCreateAccessCACertificates(t *testing.T) {
 	setup()
 	defer teardown()
 
@@ -123,7 +123,7 @@ func TestCreateAcessCACertificates(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
 
-	actual, err := client.CreateAccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.CreateAccessCACertificate(context.Background(), testAccountRC, CreateAccessCACertificateParams{ApplicationID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -131,14 +131,14 @@ func TestCreateAcessCACertificates(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
 
-	actual, err = client.CreateZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err = client.CreateAccessCACertificate(context.Background(), testZoneRC, CreateAccessCACertificateParams{ApplicationID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
 	}
 }
 
-func TestDeleteAcessCACertificates(t *testing.T) {
+func TestDeleteAccessCACertificates(t *testing.T) {
 	setup()
 	defer teardown()
 
@@ -158,13 +158,13 @@ func TestDeleteAcessCACertificates(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
 
-	err := client.DeleteAccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	err := client.DeleteAccessCACertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler)
 
-	err = client.DeleteZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	err = client.DeleteAccessCACertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	assert.NoError(t, err)
 }
diff --git a/access_group_test.go b/access_group_test.go
index 7491a2aa4..11f538079 100644
--- a/access_group_test.go
+++ b/access_group_test.go
@@ -91,7 +91,7 @@ func TestAccessGroups(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler)
 
-	actual, _, err := client.AccessGroups(context.Background(), testAccountID, pageOptions)
+	actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, ListAccessGroupsParams{ResultInfo{}})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual)
@@ -99,7 +99,7 @@ func TestAccessGroups(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler)
 
-	actual, _, err = client.ZoneLevelAccessGroups(context.Background(), testZoneID, pageOptions)
+	actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, ListAccessGroupsParams{ResultInfo{}})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual)
@@ -150,7 +150,7 @@ func TestAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler)
 
-	actual, err := client.AccessGroup(context.Background(), testAccountID, accessGroupID)
+	actual, err := client.GetAccessGroup(context.Background(), testAccountRC, accessGroupID)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
@@ -158,7 +158,7 @@ func TestAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler)
 
-	actual, err = client.ZoneLevelAccessGroup(context.Background(), testZoneID, accessGroupID)
+	actual, err = client.GetAccessGroup(context.Background(), testZoneRC, accessGroupID)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
@@ -209,7 +209,7 @@ func TestCreateAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler)
 
-	accessGroup := AccessGroup{
+	params := CreateAccessGroupParams{
 		Name: "Allow devs",
 		Include: []interface{}{
 			AccessGroupEmail{struct {
@@ -228,7 +228,7 @@ func TestCreateAccessGroup(t *testing.T) {
 		},
 	}
 
-	actual, err := client.CreateAccessGroup(context.Background(), testAccountID, accessGroup)
+	actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, params)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
@@ -236,7 +236,7 @@ func TestCreateAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler)
 
-	actual, err = client.CreateZoneLevelAccessGroup(context.Background(), testZoneID, accessGroup)
+	actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, params)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
@@ -285,15 +285,28 @@ func TestUpdateAccessGroup(t *testing.T) {
 		`)
 	}
 
+	params := UpdateAccessGroupParams{
+		ID:   "699d98642c564d2e855e9661899b7252",
+		Name: "Allow devs",
+		Include: []interface{}{
+			map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}},
+		},
+		Exclude: []interface{}{
+			map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}},
+		},
+		Require: []interface{}{
+			map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}},
+		},
+	}
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler)
-	actual, err := client.UpdateAccessGroup(context.Background(), testAccountID, expectedAccessGroup)
+	actual, err := client.UpdateAccessGroup(context.Background(), testAccountRC, params)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
 	}
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler)
-	actual, err = client.UpdateZoneLevelAccessGroup(context.Background(), testZoneID, expectedAccessGroup)
+	actual, err = client.UpdateAccessGroup(context.Background(), testZoneRC, params)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroup, actual)
@@ -304,10 +317,10 @@ func TestUpdateAccessGroupWithMissingID(t *testing.T) {
 	setup()
 	defer teardown()
 
-	_, err := client.UpdateAccessGroup(context.Background(), testAccountID, AccessGroup{})
+	_, err := client.UpdateAccessGroup(context.Background(), testAccountRC, UpdateAccessGroupParams{})
 	assert.EqualError(t, err, "access group ID cannot be empty")
 
-	_, err = client.UpdateZoneLevelAccessGroup(context.Background(), testZoneID, AccessGroup{})
+	_, err = client.UpdateAccessGroup(context.Background(), testZoneRC, UpdateAccessGroupParams{})
 	assert.EqualError(t, err, "access group ID cannot be empty")
 }
 
@@ -330,12 +343,12 @@ func TestDeleteAccessGroup(t *testing.T) {
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler)
-	err := client.DeleteAccessGroup(context.Background(), testAccountID, accessGroupID)
+	err := client.DeleteAccessGroup(context.Background(), testAccountRC, accessGroupID)
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler)
-	err = client.DeleteZoneLevelAccessGroup(context.Background(), testZoneID, accessGroupID)
+	err = client.DeleteAccessGroup(context.Background(), testZoneRC, accessGroupID)
 
 	assert.NoError(t, err)
 }
@@ -370,7 +383,7 @@ func TestCreateIPListAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler)
 
-	accessGroup := AccessGroup{
+	accessGroup := CreateAccessGroupParams{
 		Name: "Allow devs by iplist",
 		Include: []interface{}{
 			AccessGroupIPList{struct {
@@ -379,7 +392,7 @@ func TestCreateIPListAccessGroup(t *testing.T) {
 		},
 	}
 
-	actual, err := client.CreateAccessGroup(context.Background(), testAccountID, accessGroup)
+	actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, accessGroup)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroupIpList, actual)
@@ -387,7 +400,7 @@ func TestCreateIPListAccessGroup(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler)
 
-	actual, err = client.CreateZoneLevelAccessGroup(context.Background(), testZoneID, accessGroup)
+	actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, accessGroup)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessGroupIpList, actual)
diff --git a/access_identity_provider_test.go b/access_identity_provider_test.go
index 3b69798ab..ad9b6935b 100644
--- a/access_identity_provider_test.go
+++ b/access_identity_provider_test.go
@@ -9,12 +9,14 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestAccessIdentityProviders(t *testing.T) {
+func TestListAccessIdentityProviders(t *testing.T) {
 	setup()
 	defer teardown()
 
 	handler := func(w http.ResponseWriter, r *http.Request) {
 		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		assert.Equal(t, "1", r.URL.Query().Get("page"))
+		assert.Equal(t, "25", r.URL.Query().Get("per_page"))
 		w.Header().Set("content-type", "application/json")
 		fmt.Fprintf(w, `{
 			"success": true,
@@ -30,7 +32,13 @@ func TestAccessIdentityProviders(t *testing.T) {
 						"client_secret": "a-secret-key"
 					}
 				}
-			]
+			],
+			"result_info": {
+				"count": 1,
+				"page": 1,
+				"per_page": 20,
+				"total_count": 1
+		  	}
 		}
 		`)
 	}
@@ -49,7 +57,7 @@ func TestAccessIdentityProviders(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler)
 
-	actual, err := client.AccessIdentityProviders(context.Background(), testAccountID)
+	actual, _, err := client.ListAccessIdentityProviders(context.Background(), testAccountRC, ListAccessIdentityProvidersParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -57,7 +65,7 @@ func TestAccessIdentityProviders(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler)
 
-	actual, err = client.ZoneLevelAccessIdentityProviders(context.Background(), testZoneID)
+	actual, _, err = client.ListAccessIdentityProviders(context.Background(), testZoneRC, ListAccessIdentityProvidersParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -100,7 +108,7 @@ func TestAccessIdentityProviderDetails(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc841", handler)
 
-	actual, err := client.AccessIdentityProviderDetails(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc841")
+	actual, err := client.GetAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc841")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -108,7 +116,7 @@ func TestAccessIdentityProviderDetails(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc841", handler)
 
-	actual, err = client.ZoneLevelAccessIdentityProviderDetails(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc841")
+	actual, err = client.GetAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc841")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -139,7 +147,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
 		`)
 	}
 
-	newIdentityProvider := AccessIdentityProvider{
+	newIdentityProvider := CreateAccessIdentityProviderParams{
 		Name: "Widget Corps OTP",
 		Type: "github",
 		Config: AccessIdentityProviderConfiguration{
@@ -160,7 +168,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler)
 
-	actual, err := client.CreateAccessIdentityProvider(context.Background(), testAccountID, newIdentityProvider)
+	actual, err := client.CreateAccessIdentityProvider(context.Background(), testAccountRC, newIdentityProvider)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -168,7 +176,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler)
 
-	actual, err = client.CreateZoneLevelAccessIdentityProvider(context.Background(), testZoneID, newIdentityProvider)
+	actual, err = client.CreateAccessIdentityProvider(context.Background(), testZoneRC, newIdentityProvider)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -198,7 +206,8 @@ func TestUpdateAccessIdentityProvider(t *testing.T) {
 		`)
 	}
 
-	updatedIdentityProvider := AccessIdentityProvider{
+	updatedIdentityProvider := UpdateAccessIdentityProviderParams{
+		ID:   "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
 		Name: "Widget Corps OTP",
 		Type: "github",
 		Config: AccessIdentityProviderConfiguration{
@@ -219,7 +228,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider)
+	actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountRC, updatedIdentityProvider)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -227,7 +236,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.UpdateZoneLevelAccessIdentityProvider(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider)
+	actual, err = client.UpdateAccessIdentityProvider(context.Background(), testZoneRC, updatedIdentityProvider)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -270,7 +279,7 @@ func TestDeleteAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.DeleteAccessIdentityProvider(context.Background(), "01a7362d577a6c3019a474fd6f485823", "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.DeleteAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -278,7 +287,7 @@ func TestDeleteAccessIdentityProvider(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.DeleteZoneLevelAccessIdentityProvider(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err = client.DeleteAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
diff --git a/access_mutual_tls_certificates_test.go b/access_mutual_tls_certificates_test.go
index fd567398c..235f02134 100644
--- a/access_mutual_tls_certificates_test.go
+++ b/access_mutual_tls_certificates_test.go
@@ -53,7 +53,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates", handler)
 
-	actual, err := client.AccessMutualTLSCertificates(context.Background(), testAccountID)
+	actual, _, err := client.ListAccessMutualTLSCertificates(context.Background(), testAccountRC, ListAccessMutualTLSCertificatesParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -61,7 +61,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/certificates", handler)
 
-	actual, err = client.ZoneAccessMutualTLSCertificates(context.Background(), testZoneID)
+	actual, _, err = client.ListAccessMutualTLSCertificates(context.Background(), testZoneRC, ListAccessMutualTLSCertificatesParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -109,7 +109,7 @@ func TestAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.AccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.GetAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -117,7 +117,7 @@ func TestAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.ZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err = client.GetAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -153,7 +153,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) {
 	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 	expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 
-	certificate := AccessMutualTLSCertificate{
+	certificate := CreateAccessMutualTLSCertificateParams{
 		Name:        "Allow devs",
 		Certificate: "-----BEGIN CERTIFICATE-----\nMIIGAjCCA+qgAwIBAgIJAI7kymlF7CWT...N4RI7KKB7nikiuUf8vhULKy5IX10\nDrUtmu/B\n-----END CERTIFICATE-----",
 	}
@@ -170,7 +170,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates", handler)
 
-	actual, err := client.CreateAccessMutualTLSCertificate(context.Background(), testAccountID, certificate)
+	actual, err := client.CreateAccessMutualTLSCertificate(context.Background(), testAccountRC, certificate)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -178,7 +178,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/certificates", handler)
 
-	actual, err = client.CreateZoneAccessMutualTLSCertificate(context.Background(), testZoneID, certificate)
+	actual, err = client.CreateAccessMutualTLSCertificate(context.Background(), testZoneRC, certificate)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -214,7 +214,8 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) {
 	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 	expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 
-	certificate := AccessMutualTLSCertificate{
+	certificate := UpdateAccessMutualTLSCertificateParams{
+		ID:          "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
 		Name:        "Allow devs",
 		Certificate: "-----BEGIN CERTIFICATE-----\nMIIGAjCCA+qgAwIBAgIJAI7kymlF7CWT...N4RI7KKB7nikiuUf8vhULKy5IX10\nDrUtmu/B\n-----END CERTIFICATE-----",
 	}
@@ -231,7 +232,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate)
+	actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountRC, certificate)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -239,7 +240,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.UpdateZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate)
+	actual, err = client.UpdateAccessMutualTLSCertificate(context.Background(), testZoneRC, certificate)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -265,13 +266,13 @@ func TestDeleteAccessMutualTLSCertificate(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	err := client.DeleteAccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	err := client.DeleteAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	err = client.DeleteZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	err = client.DeleteAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	assert.NoError(t, err)
 }
diff --git a/access_organization_test.go b/access_organization_test.go
index 3ea79970a..1407eb7a9 100644
--- a/access_organization_test.go
+++ b/access_organization_test.go
@@ -63,7 +63,7 @@ func TestAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler)
 
-	actual, _, err := client.AccessOrganization(context.Background(), testAccountID)
+	actual, _, err := client.GetAccessOrganization(context.Background(), testAccountRC, GetAccessOrganizationParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -71,7 +71,7 @@ func TestAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler)
 
-	actual, _, err = client.ZoneLevelAccessOrganization(context.Background(), testZoneID)
+	actual, _, err = client.GetAccessOrganization(context.Background(), testZoneRC, GetAccessOrganizationParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -111,9 +111,9 @@ func TestCreateAccessOrganization(t *testing.T) {
 	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 
 	want := AccessOrganization{
-		Name:       "Widget Corps Internal Applications",
 		CreatedAt:  &createdAt,
 		UpdatedAt:  &updatedAt,
+		Name:       "Widget Corps Internal Applications",
 		AuthDomain: "test.cloudflareaccess.com",
 		LoginDesign: AccessOrganizationLoginDesign{
 			BackgroundColor: "#c5ed1b",
@@ -127,7 +127,18 @@ func TestCreateAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler)
 
-	actual, err := client.CreateAccessOrganization(context.Background(), testAccountID, want)
+	actual, err := client.CreateAccessOrganization(context.Background(), testAccountRC, CreateAccessOrganizationParams{
+		Name:       "Widget Corps Internal Applications",
+		AuthDomain: "test.cloudflareaccess.com",
+		LoginDesign: AccessOrganizationLoginDesign{
+			BackgroundColor: "#c5ed1b",
+			LogoPath:        "https://example.com/logo.png",
+			TextColor:       "#c5ed1b",
+			HeaderText:      "Widget Corp",
+			FooterText:      "© Widget Corp",
+		},
+		IsUIReadOnly: BoolPtr(true),
+	})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -135,7 +146,18 @@ func TestCreateAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler)
 
-	actual, err = client.CreateZoneLevelAccessOrganization(context.Background(), testZoneID, want)
+	actual, err = client.CreateAccessOrganization(context.Background(), testZoneRC, CreateAccessOrganizationParams{
+		Name:       "Widget Corps Internal Applications",
+		AuthDomain: "test.cloudflareaccess.com",
+		LoginDesign: AccessOrganizationLoginDesign{
+			BackgroundColor: "#c5ed1b",
+			LogoPath:        "https://example.com/logo.png",
+			TextColor:       "#c5ed1b",
+			HeaderText:      "Widget Corp",
+			FooterText:      "© Widget Corp",
+		},
+		IsUIReadOnly: BoolPtr(true),
+	})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -176,9 +198,9 @@ func TestUpdateAccessOrganization(t *testing.T) {
 	updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
 
 	want := AccessOrganization{
-		Name:       "Widget Corps Internal Applications",
 		CreatedAt:  &createdAt,
 		UpdatedAt:  &updatedAt,
+		Name:       "Widget Corps Internal Applications",
 		AuthDomain: "test.cloudflareaccess.com",
 		LoginDesign: AccessOrganizationLoginDesign{
 			BackgroundColor: "#c5ed1b",
@@ -193,7 +215,19 @@ func TestUpdateAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler)
 
-	actual, err := client.UpdateAccessOrganization(context.Background(), testAccountID, want)
+	actual, err := client.UpdateAccessOrganization(context.Background(), testAccountRC, UpdateAccessOrganizationParams{
+		Name:       "Widget Corps Internal Applications",
+		AuthDomain: "test.cloudflareaccess.com",
+		LoginDesign: AccessOrganizationLoginDesign{
+			BackgroundColor: "#c5ed1b",
+			LogoPath:        "https://example.com/logo.png",
+			TextColor:       "#c5ed1b",
+			HeaderText:      "Widget Corp",
+			FooterText:      "© Widget Corp",
+		},
+		IsUIReadOnly:           BoolPtr(false),
+		UIReadOnlyToggleReason: "this is my reason",
+	})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -201,7 +235,19 @@ func TestUpdateAccessOrganization(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler)
 
-	actual, err = client.UpdateZoneLevelAccessOrganization(context.Background(), testZoneID, want)
+	actual, err = client.UpdateAccessOrganization(context.Background(), testZoneRC, UpdateAccessOrganizationParams{
+		Name:       "Widget Corps Internal Applications",
+		AuthDomain: "test.cloudflareaccess.com",
+		LoginDesign: AccessOrganizationLoginDesign{
+			BackgroundColor: "#c5ed1b",
+			LogoPath:        "https://example.com/logo.png",
+			TextColor:       "#c5ed1b",
+			HeaderText:      "Widget Corp",
+			FooterText:      "© Widget Corp",
+		},
+		IsUIReadOnly:           BoolPtr(false),
+		UIReadOnlyToggleReason: "this is my reason",
+	})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
diff --git a/access_policy_test.go b/access_policy_test.go
index 1164b29d4..f3f8a66fd 100644
--- a/access_policy_test.go
+++ b/access_policy_test.go
@@ -69,63 +69,65 @@ func TestAccessPolicies(t *testing.T) {
 			"errors": [],
 			"messages": [],
 			"result": [
-				{
-					"id": "699d98642c564d2e855e9661899b7252",
-					"precedence": 1,
-					"decision": "allow",
-					"created_at": "2014-01-01T05:20:00.12345Z",
-					"updated_at": "2014-01-01T05:20:00.12345Z",
-					"name": "Allow devs",
-					"include": [
-						{
-							"email": {
-								"email": "test@example.com"
-							}
-						}
-					],
-					"exclude": [
-						{
-							"email": {
-								"email": "test@example.com"
-							}
-						}
-					],
-					"require": [
-						{
-							"email": {
-								"email": "test@example.com"
-							}
-						}
+			  {
+				"id": "699d98642c564d2e855e9661899b7252",
+				"precedence": 1,
+				"decision": "allow",
+				"created_at": "2014-01-01T05:20:00.12345Z",
+				"updated_at": "2014-01-01T05:20:00.12345Z",
+				"name": "Allow devs",
+				"include": [
+				  {
+					"email": {
+					  "email": "test@example.com"
+					}
+				  }
+				],
+				"exclude": [
+				  {
+					"email": {
+					  "email": "test@example.com"
+					}
+				  }
+				],
+				"require": [
+				  {
+					"email": {
+					  "email": "test@example.com"
+					}
+				  }
+				],
+				"isolation_required": true,
+				"purpose_justification_required": true,
+				"purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.",
+				"approval_required": true,
+				"approval_groups": [
+				  {
+					"email_list_uuid": "2413b6d7-bbe5-48bd-8fbb-e52069c85561",
+					"approvals_needed": 3
+				  },
+				  {
+					"email_addresses": [
+					  "email1@example.com",
+					  "email2@example.com"
 					],
-					"isolation_required": true,
-					"purpose_justification_required": true,
-					"purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.",
-					"approval_required": true,
-					"approval_groups": [
-						{
-							"email_list_uuid": "2413b6d7-bbe5-48bd-8fbb-e52069c85561",
-							"approvals_needed": 3
-						},
-						{
-							"email_addresses": ["email1@example.com", "email2@example.com"],
-							"approvals_needed": 1
-						}
-					]
-				}
+					"approvals_needed": 1
+				  }
+				]
+			  }
 			],
 			"result_info": {
-				"page": 1,
-				"per_page": 20,
-				"count": 1,
-				"total_count": 2000
+			  "page": 1,
+			  "per_page": 20,
+			  "count": 1,
+			  "total_count": 20
 			}
-		}
-		`)
+		  }`)
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler)
 
-	actual, _, err := client.AccessPolicies(context.Background(), testAccountID, accessApplicationID, pageOptions)
+	actual, _, err := client.ListAccessPolicies(context.Background(), testAccountRC, ListAccessPoliciesParams{ApplicationID: accessApplicationID})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual)
@@ -133,7 +135,7 @@ func TestAccessPolicies(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler)
 
-	actual, _, err = client.ZoneLevelAccessPolicies(context.Background(), testZoneID, accessApplicationID, pageOptions)
+	actual, _, err = client.ListAccessPolicies(context.Background(), testZoneRC, ListAccessPoliciesParams{ApplicationID: accessApplicationID})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual)
@@ -200,7 +202,7 @@ func TestAccessPolicy(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
 
-	actual, err := client.AccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicyID)
+	actual, err := client.GetAccessPolicy(context.Background(), testAccountRC, GetAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
@@ -208,7 +210,7 @@ func TestAccessPolicy(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
 
-	actual, err = client.ZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicyID)
+	actual, err = client.GetAccessPolicy(context.Background(), testZoneRC, GetAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
@@ -273,8 +275,9 @@ func TestCreateAccessPolicy(t *testing.T) {
 		`)
 	}
 
-	accessPolicy := AccessPolicy{
-		Name: "Allow devs",
+	accessPolicy := CreateAccessPolicyParams{
+		ApplicationID: accessApplicationID,
+		Name:          "Allow devs",
 		Include: []interface{}{
 			AccessGroupEmail{struct {
 				Email string `json:"email"`
@@ -307,7 +310,7 @@ func TestCreateAccessPolicy(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler)
 
-	actual, err := client.CreateAccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicy)
+	actual, err := client.CreateAccessPolicy(context.Background(), testAccountRC, accessPolicy)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
@@ -315,7 +318,7 @@ func TestCreateAccessPolicy(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler)
 
-	actual, err = client.CreateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicy)
+	actual, err = client.CreateAccessPolicy(context.Background(), testZoneRC, accessPolicy)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
@@ -381,14 +384,14 @@ func TestUpdateAccessPolicy(t *testing.T) {
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
-	actual, err := client.UpdateAccessPolicy(context.Background(), testAccountID, accessApplicationID, expectedAccessPolicy)
+	actual, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, expectedAccessPolicy)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
 	}
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
-	actual, err = client.UpdateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, expectedAccessPolicy)
+	actual, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, expectedAccessPolicy)
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expectedAccessPolicy, actual)
@@ -399,10 +402,10 @@ func TestUpdateAccessPolicyWithMissingID(t *testing.T) {
 	setup()
 	defer teardown()
 
-	_, err := client.UpdateAccessPolicy(context.Background(), testAccountID, accessApplicationID, AccessPolicy{})
+	_, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, AccessPolicy{})
 	assert.EqualError(t, err, "access policy ID cannot be empty")
 
-	_, err = client.UpdateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, AccessPolicy{})
+	_, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, AccessPolicy{})
 	assert.EqualError(t, err, "access policy ID cannot be empty")
 }
 
@@ -425,12 +428,12 @@ func TestDeleteAccessPolicy(t *testing.T) {
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
-	err := client.DeleteAccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicyID)
+	err := client.DeleteAccessPolicy(context.Background(), testAccountRC, DeleteAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID})
 
 	assert.NoError(t, err)
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler)
-	err = client.DeleteZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicyID)
+	err = client.DeleteAccessPolicy(context.Background(), testZoneRC, DeleteAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID})
 
 	assert.NoError(t, err)
 }
diff --git a/access_service_tokens_test.go b/access_service_tokens_test.go
index cbaa69c46..5943e80bc 100644
--- a/access_service_tokens_test.go
+++ b/access_service_tokens_test.go
@@ -52,7 +52,7 @@ func TestAccessServiceTokens(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler)
 
-	actual, _, err := client.AccessServiceTokens(context.Background(), testAccountID)
+	actual, _, err := client.ListAccessServiceTokens(context.Background(), testAccountRC, ListAccessServiceTokensParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -60,7 +60,7 @@ func TestAccessServiceTokens(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler)
 
-	actual, _, err = client.ZoneLevelAccessServiceTokens(context.Background(), testZoneID)
+	actual, _, err = client.ListAccessServiceTokens(context.Background(), testZoneRC, ListAccessServiceTokensParams{})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, actual)
@@ -103,7 +103,7 @@ func TestCreateAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler)
 
-	actual, err := client.CreateAccessServiceToken(context.Background(), testAccountID, "CI/CD token")
+	actual, err := client.CreateAccessServiceToken(context.Background(), testAccountRC, CreateAccessServiceTokenParams{Name: "CI/CD token"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -111,7 +111,7 @@ func TestCreateAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler)
 
-	actual, err = client.CreateZoneLevelAccessServiceToken(context.Background(), testZoneID, "CI/CD token")
+	actual, err = client.CreateAccessServiceToken(context.Background(), testZoneRC, CreateAccessServiceTokenParams{Name: "CI/CD token"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -152,7 +152,7 @@ func TestUpdateAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token")
+	actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountRC, UpdateAccessServiceTokenParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "CI/CD token"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -160,7 +160,7 @@ func TestUpdateAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.UpdateZoneLevelAccessServiceToken(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token")
+	actual, err = client.UpdateAccessServiceToken(context.Background(), testZoneRC, UpdateAccessServiceTokenParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "CI/CD token"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -201,7 +201,7 @@ func TestRefreshAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/refresh", handler)
 
-	actual, err := client.RefreshAccessServiceToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.RefreshAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -244,7 +244,7 @@ func TestRotateAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/rotate", handler)
 
-	actual, err := client.RotateAccessServiceToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.RotateAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -285,7 +285,7 @@ func TestDeleteAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err := client.DeleteAccessServiceToken(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err := client.DeleteAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
@@ -293,7 +293,7 @@ func TestDeleteAccessServiceToken(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
 
-	actual, err = client.DeleteZoneLevelAccessServiceToken(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
+	actual, err = client.DeleteAccessServiceToken(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, expected, actual)
diff --git a/access_user_tokens_test.go b/access_user_tokens_test.go
index c1cb268c9..921c9b85c 100644
--- a/access_user_tokens_test.go
+++ b/access_user_tokens_test.go
@@ -25,9 +25,7 @@ func TestRevokeAccessUserTokens(t *testing.T) {
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations/revoke_user", handler)
 
-	AccessUserEmail := AccessUserEmail{Email: "test@example.com"}
-
-	err := client.RevokeAccessUserTokens(context.Background(), testAccountID, AccessUserEmail)
+	err := client.RevokeAccessUserTokens(context.Background(), testAccountRC, RevokeAccessUserTokensParams{Email: "test@example.com"})
 
 	assert.NoError(t, err)
 }
@@ -48,9 +46,7 @@ func TestRevokeZoneLevelAccessUserTokens(t *testing.T) {
 
 	mux.HandleFunc("/zones/"+testZoneID+"/access/organizations/revoke_user", handler)
 
-	AccessUserEmail := AccessUserEmail{Email: "test@example.com"}
-
-	err := client.RevokeZoneLevelAccessUserTokens(context.Background(), testZoneID, AccessUserEmail)
+	err := client.RevokeAccessUserTokens(context.Background(), testZoneRC, RevokeAccessUserTokensParams{Email: "test@example.com"})
 
 	assert.NoError(t, err)
 }
diff --git a/cloudflare_test.go b/cloudflare_test.go
index c84114421..03654047c 100644
--- a/cloudflare_test.go
+++ b/cloudflare_test.go
@@ -21,6 +21,12 @@ var (
 
 	// server is a test HTTP server used to provide mock API responses.
 	server *httptest.Server
+
+	// testAccountRC is a test account resource container.
+	testAccountRC = AccountIdentifier(testAccountID)
+
+	// testZoneRC is a test zone resource container.
+	testZoneRC = ZoneIdentifier(testZoneID)
 )
 
 func setup(opts ...Option) {
@@ -475,7 +481,7 @@ func TestErrorFromResponseWithUnmarshalingError(t *testing.T) {
 
 	mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/access/apps", handler)
 
-	_, err := client.CreateAccessApplication(context.Background(), "01a7362d577a6c3019a474fd6f485823", AccessApplication{
+	_, err := client.CreateAccessApplication(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), CreateAccessApplicationParams{
 		Name:            "Admin Site",
 		Domain:          "test.example.com/admin",
 		SessionDuration: "24h",