// Copyright 2026 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package recaptchaenterprise provides access to the reCAPTCHA Enterprise API.
//
// For product documentation, see: https://cloud.google.com/recaptcha-enterprise/
//
// # Library status
//
// These client libraries are officially supported by Google. However, this
// library is considered complete and is in maintenance mode. This means
// that we will address critical bugs and security issues but will not add
// any new features.
//
// When possible, we recommend using our newer
// [Cloud Client Libraries for Go](https://pkg.go.dev/cloud.google.com/go)
// that are still actively being worked and iterated on.
//
// # Creating a client
//
// Usage example:
//
//	import "google.golang.org/api/recaptchaenterprise/v1"
//	...
//	ctx := context.Background()
//	recaptchaenterpriseService, err := recaptchaenterprise.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for
// authentication. For information on how to create and obtain Application
// Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// # Other authentication options
//
// To use an API key for authentication (note: some APIs do not support API
// keys), use [google.golang.org/api/option.WithAPIKey]:
//
//	recaptchaenterpriseService, err := recaptchaenterprise.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth
// flow, use [google.golang.org/api/option.WithTokenSource]:
//
//	config := &oauth2.Config{...}
//	// ...
//	token, err := config.Exchange(ctx, ...)
//	recaptchaenterpriseService, err := recaptchaenterprise.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See [google.golang.org/api/option.ClientOption] for details on options.
package recaptchaenterprise // import "google.golang.org/api/recaptchaenterprise/v1"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/googleapis/gax-go/v2/internallog"
	googleapi "google.golang.org/api/googleapi"
	internal "google.golang.org/api/internal"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint
var _ = internal.Version
var _ = internallog.New

const apiId = "recaptchaenterprise:v1"
const apiName = "recaptchaenterprise"
const apiVersion = "v1"
const basePath = "https://recaptchaenterprise.googleapis.com/"
const basePathTemplate = "https://recaptchaenterprise.UNIVERSE_DOMAIN/"
const mtlsBasePath = "https://recaptchaenterprise.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// See, edit, configure, and delete your Google Cloud data and see the email
	// address for your Google Account.
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := internaloption.WithDefaultScopes(
		"https://www.googleapis.com/auth/cloud-platform",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultEndpointTemplate(basePathTemplate))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	opts = append(opts, internaloption.EnableNewAuthLibrary())
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s := &Service{client: client, BasePath: basePath, logger: internaloption.GetLogger(opts)}
	s.Projects = NewProjectsService(s)
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	return NewService(context.TODO(), option.WithHTTPClient(client))
}

type Service struct {
	client    *http.Client
	logger    *slog.Logger
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	Projects *ProjectsService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewProjectsService(s *Service) *ProjectsService {
	rs := &ProjectsService{s: s}
	rs.Assessments = NewProjectsAssessmentsService(s)
	rs.Firewallpolicies = NewProjectsFirewallpoliciesService(s)
	rs.Keys = NewProjectsKeysService(s)
	rs.Relatedaccountgroupmemberships = NewProjectsRelatedaccountgroupmembershipsService(s)
	rs.Relatedaccountgroups = NewProjectsRelatedaccountgroupsService(s)
	return rs
}

type ProjectsService struct {
	s *Service

	Assessments *ProjectsAssessmentsService

	Firewallpolicies *ProjectsFirewallpoliciesService

	Keys *ProjectsKeysService

	Relatedaccountgroupmemberships *ProjectsRelatedaccountgroupmembershipsService

	Relatedaccountgroups *ProjectsRelatedaccountgroupsService
}

func NewProjectsAssessmentsService(s *Service) *ProjectsAssessmentsService {
	rs := &ProjectsAssessmentsService{s: s}
	return rs
}

type ProjectsAssessmentsService struct {
	s *Service
}

func NewProjectsFirewallpoliciesService(s *Service) *ProjectsFirewallpoliciesService {
	rs := &ProjectsFirewallpoliciesService{s: s}
	return rs
}

type ProjectsFirewallpoliciesService struct {
	s *Service
}

func NewProjectsKeysService(s *Service) *ProjectsKeysService {
	rs := &ProjectsKeysService{s: s}
	return rs
}

type ProjectsKeysService struct {
	s *Service
}

func NewProjectsRelatedaccountgroupmembershipsService(s *Service) *ProjectsRelatedaccountgroupmembershipsService {
	rs := &ProjectsRelatedaccountgroupmembershipsService{s: s}
	return rs
}

type ProjectsRelatedaccountgroupmembershipsService struct {
	s *Service
}

func NewProjectsRelatedaccountgroupsService(s *Service) *ProjectsRelatedaccountgroupsService {
	rs := &ProjectsRelatedaccountgroupsService{s: s}
	rs.Memberships = NewProjectsRelatedaccountgroupsMembershipsService(s)
	return rs
}

type ProjectsRelatedaccountgroupsService struct {
	s *Service

	Memberships *ProjectsRelatedaccountgroupsMembershipsService
}

func NewProjectsRelatedaccountgroupsMembershipsService(s *Service) *ProjectsRelatedaccountgroupsMembershipsService {
	rs := &ProjectsRelatedaccountgroupsMembershipsService{s: s}
	return rs
}

type ProjectsRelatedaccountgroupsMembershipsService struct {
	s *Service
}

// GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessment: Account defense
// risk assessment.
type GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessment struct {
	// AccountTakeoverVerdict: Output only. Account takeover risk assessment for
	// this request.
	AccountTakeoverVerdict *GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict `json:"accountTakeoverVerdict,omitempty"`
	// Labels: Output only. Labels for this request.
	//
	// Possible values:
	//   "ACCOUNT_DEFENDER_LABEL_UNSPECIFIED" - Default unspecified type.
	//   "PROFILE_MATCH" - The request matches a trusted profile associated with
	// this account.
	//   "SUSPICIOUS_LOGIN_ACTIVITY" - The request is potentially a suspicious
	// login event and must be further verified either through multi-factor
	// authentication or another system.
	//   "SUSPICIOUS_ACCOUNT_CREATION" - The request matched a profile that
	// previously had suspicious account creation behavior. This can mean that this
	// is a fake account.
	//   "RELATED_ACCOUNTS_NUMBER_HIGH" - The account in the request has a high
	// number of related accounts. It does not necessarily imply that the account
	// is bad but can require further investigation.
	Labels []string `json:"labels,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountTakeoverVerdict") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountTakeoverVerdict") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountRiskReason:
// Risk explainability reasons for Account defense.
type GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountRiskReason struct {
	// Reason: Output only. A risk reason associated with this request.
	//
	// Possible values:
	//   "RISK_REASON_UNSPECIFIED" - Default unspecified type.
	//   "CLIENT_HISTORICAL_BOT_ACTIVITY" - The client has been observed sending
	// bot-like traffic to this site in the past. This reason incorporates
	// historical reputation and indicates that the client is known to use bots,
	// even if the current request is being made by a human.
	//   "ACCOUNT_IN_LARGE_RELATED_GROUP" - The account is part of a large group of
	// related accounts, indicating that it may be part of a fraudulent network.
	// Related accounts are identified based on having similar traffic patterns and
	// request characteristics.
	//   "CLIENT_ACCESSED_MANY_ACCOUNTS" - The client has been observed accessing
	// many accounts on this site.
	//   "DISPOSABLE_EMAIL_DOMAIN" - This email domain is a suspected provider of
	// disposable email addresses.
	Reason string `json:"reason,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Reason") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Reason") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountRiskReason) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountRiskReason
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdi
// ct: Account takeover risk assessment.
type GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict struct {
	// Risk: Output only. Account takeover attempt probability. Values are from 0.0
	// (lowest risk) to 1.0 (highest risk).
	Risk float64 `json:"risk,omitempty"`
	// RiskReasons: Output only. Unordered list. Reasons why the request appears
	// risky. Risk reasons can be returned even if the risk is low, as trustworthy
	// requests can still have some risk signals.
	RiskReasons []*GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountRiskReason `json:"riskReasons,omitempty"`
	// TrustReasons: Output only. Unordered list. Reasons why the request appears
	// trustworthy. Trust reasons can be returned even if the risk is high, as
	// risky requests can still have some trust signals.
	TrustReasons []*GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTrustReason `json:"trustReasons,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Risk") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Risk") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTakeoverVerdict
	var s1 struct {
		Risk gensupport.JSONFloat64 `json:"risk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Risk = float64(s1.Risk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTrustReason:
// Trust explainability reasons for Account defense.
type GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTrustReason struct {
	// Reason: Output only. A trust reason associated with this request.
	//
	// Possible values:
	//   "TRUST_REASON_UNSPECIFIED" - Default unspecified type.
	//   "PROFILE_MATCH" - The request matches a trusted profile associated with
	// this account. Equivalent to `AccountDefenderLabel.PROFILE_MATCH`.
	//   "ACCOUNT_HISTORY_REPUTABLE" - The account's historical activity is
	// reputable. It is unlikely that the account has been compromised in the past.
	//   "IDENTITY_GLOBAL_ACTIVITY_REPUTABLE" - The identity shows a global pattern
	// of reputable activity based on `userInfo` and associated identifiers.
	//   "IDENTITY_HISTORY_REPUTABLE" - The identity shows a long-standing history
	// of reputable activity based on `userInfo` and associated identifiers.
	Reason string `json:"reason,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Reason") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Reason") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTrustReason) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessmentAccountTrustReason
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AccountVerificationInfo: Information about
// account verification, used for identity verification.
type GoogleCloudRecaptchaenterpriseV1AccountVerificationInfo struct {
	// Endpoints: Optional. Endpoints that can be used for identity verification.
	Endpoints []*GoogleCloudRecaptchaenterpriseV1EndpointVerificationInfo `json:"endpoints,omitempty"`
	// LanguageCode: Optional. Language code preference for the verification
	// message, set as a IETF BCP 47 language code.
	LanguageCode string `json:"languageCode,omitempty"`
	// LatestVerificationResult: Output only. Result of the latest account
	// verification challenge.
	//
	// Possible values:
	//   "RESULT_UNSPECIFIED" - No information about the latest account
	// verification.
	//   "SUCCESS_USER_VERIFIED" - The user was successfully verified. This means
	// the account verification challenge was successfully completed.
	//   "ERROR_USER_NOT_VERIFIED" - The user failed the verification challenge.
	//   "ERROR_SITE_ONBOARDING_INCOMPLETE" - The site is not properly onboarded to
	// use the account verification feature.
	//   "ERROR_RECIPIENT_NOT_ALLOWED" - The recipient is not allowed for account
	// verification. This can occur during integration but should not occur in
	// production.
	//   "ERROR_RECIPIENT_ABUSE_LIMIT_EXHAUSTED" - The recipient has already been
	// sent too many verification codes in a short amount of time.
	//   "ERROR_CRITICAL_INTERNAL" - The verification flow could not be completed
	// due to a critical internal error.
	//   "ERROR_CUSTOMER_QUOTA_EXHAUSTED" - The client has exceeded their two
	// factor request quota for this period of time.
	//   "ERROR_VERIFICATION_BYPASSED" - The request cannot be processed at the
	// time because of an incident. This bypass can be restricted to a problematic
	// destination email domain, a customer, or could affect the entire service.
	//   "ERROR_VERDICT_MISMATCH" - The request parameters do not match with the
	// token provided and cannot be processed.
	LatestVerificationResult string `json:"latestVerificationResult,omitempty"`
	// Username: Username of the account that is being verified. Deprecated.
	// Customers should now provide the `account_id` field in `event.user_info`.
	Username string `json:"username,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Endpoints") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Endpoints") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AccountVerificationInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AccountVerificationInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest: The AddIpOverride
// request message.
type GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest struct {
	// IpOverrideData: Required. IP override added to the key.
	IpOverrideData *GoogleCloudRecaptchaenterpriseV1IpOverrideData `json:"ipOverrideData,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IpOverrideData") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IpOverrideData") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AddIpOverrideResponse: Response for
// AddIpOverride.
type GoogleCloudRecaptchaenterpriseV1AddIpOverrideResponse struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleCloudRecaptchaenterpriseV1AndroidKeySettings: Settings specific to
// keys that can be used by Android apps.
type GoogleCloudRecaptchaenterpriseV1AndroidKeySettings struct {
	// AllowAllPackageNames: Optional. If set to true, allowed_package_names are
	// not enforced.
	AllowAllPackageNames bool `json:"allowAllPackageNames,omitempty"`
	// AllowedPackageNames: Optional. Android package names of apps allowed to use
	// the key. Example: 'com.companyname.appname' Each key supports a maximum of
	// 250 package names. To use a key on more apps, set `allow_all_package_names`
	// to true. When this is set, you are responsible for validating the package
	// name by checking the `token_properties.android_package_name` field in each
	// assessment response against your list of allowed package names.
	AllowedPackageNames []string `json:"allowedPackageNames,omitempty"`
	// SupportNonGoogleAppStoreDistribution: Optional. Set to true for keys that
	// are used in an Android application that is available for download in app
	// stores in addition to the Google Play Store.
	SupportNonGoogleAppStoreDistribution bool `json:"supportNonGoogleAppStoreDistribution,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowAllPackageNames") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AllowAllPackageNames") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AndroidKeySettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AndroidKeySettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest: The request
// message to annotate an Assessment.
type GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest struct {
	// AccountId: Optional. A stable account identifier to apply to the assessment.
	// This is an alternative to setting `account_id` in `CreateAssessment`, for
	// example when a stable account identifier is not yet known in the initial
	// request.
	AccountId string `json:"accountId,omitempty"`
	// Annotation: Optional. The annotation that is assigned to the Event. This
	// field can be left empty to provide reasons that apply to an event without
	// concluding whether the event is legitimate or fraudulent.
	//
	// Possible values:
	//   "ANNOTATION_UNSPECIFIED" - Default unspecified type.
	//   "LEGITIMATE" - Provides information that the event turned out to be
	// legitimate.
	//   "FRAUDULENT" - Provides information that the event turned out to be
	// fraudulent.
	//   "PASSWORD_CORRECT" - Provides information that the event was related to a
	// login event in which the user typed the correct password. Deprecated, prefer
	// indicating CORRECT_PASSWORD through the reasons field instead.
	//   "PASSWORD_INCORRECT" - Provides information that the event was related to
	// a login event in which the user typed the incorrect password. Deprecated,
	// prefer indicating INCORRECT_PASSWORD through the reasons field instead.
	Annotation string `json:"annotation,omitempty"`
	// HashedAccountId: Optional. A stable hashed account identifier to apply to
	// the assessment. This is an alternative to setting `hashed_account_id` in
	// `CreateAssessment`, for example when a stable account identifier is not yet
	// known in the initial request.
	HashedAccountId string `json:"hashedAccountId,omitempty"`
	// PhoneAuthenticationEvent: Optional. If using an external multi-factor
	// authentication provider, provide phone authentication details for fraud
	// detection purposes.
	PhoneAuthenticationEvent *GoogleCloudRecaptchaenterpriseV1PhoneAuthenticationEvent `json:"phoneAuthenticationEvent,omitempty"`
	// Reasons: Optional. Reasons for the annotation that are assigned to the
	// event.
	//
	// Possible values:
	//   "REASON_UNSPECIFIED" - Unspecified reason. Do not use.
	//   "CHARGEBACK" - Indicates that the transaction had a chargeback issued with
	// no other details. When possible, specify the type by using CHARGEBACK_FRAUD
	// or CHARGEBACK_DISPUTE instead.
	//   "CHARGEBACK_FRAUD" - Indicates that the transaction had a chargeback
	// issued related to an alleged unauthorized transaction from the cardholder's
	// perspective (for example, the card number was stolen).
	//   "CHARGEBACK_DISPUTE" - Indicates that the transaction had a chargeback
	// issued related to the cardholder having provided their card details but
	// allegedly not being satisfied with the purchase (for example,
	// misrepresentation, attempted cancellation).
	//   "REFUND" - Indicates that the completed payment transaction was refunded
	// by the seller.
	//   "REFUND_FRAUD" - Indicates that the completed payment transaction was
	// determined to be fraudulent by the seller, and was cancelled and refunded as
	// a result.
	//   "TRANSACTION_ACCEPTED" - Indicates that the payment transaction was
	// accepted, and the user was charged.
	//   "TRANSACTION_DECLINED" - Indicates that the payment transaction was
	// declined, for example due to invalid card details.
	//   "PAYMENT_HEURISTICS" - Indicates the transaction associated with the
	// assessment is suspected of being fraudulent based on the payment method,
	// billing details, shipping address or other transaction information.
	//   "INITIATED_TWO_FACTOR" - Indicates that the user was served a 2FA
	// challenge. An old assessment with `ENUM_VALUES.INITIATED_TWO_FACTOR` reason
	// that has not been overwritten with `PASSED_TWO_FACTOR` is treated as an
	// abandoned 2FA flow. This is equivalent to `FAILED_TWO_FACTOR`.
	//   "PASSED_TWO_FACTOR" - Indicates that the user passed a 2FA challenge.
	//   "FAILED_TWO_FACTOR" - Indicates that the user failed a 2FA challenge.
	//   "CORRECT_PASSWORD" - Indicates the user provided the correct password.
	//   "INCORRECT_PASSWORD" - Indicates the user provided an incorrect password.
	//   "SOCIAL_SPAM" - Indicates that the user sent unwanted and abusive messages
	// to other users of the platform, such as spam, scams, phishing, or social
	// engineering.
	Reasons []string `json:"reasons,omitempty"`
	// TransactionEvent: Optional. If the assessment is part of a payment
	// transaction, provide details on payment lifecycle events that occur in the
	// transaction.
	TransactionEvent *GoogleCloudRecaptchaenterpriseV1TransactionEvent `json:"transactionEvent,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentResponse: Empty response
// for AnnotateAssessment.
type GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentResponse struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleCloudRecaptchaenterpriseV1AppleDeveloperId: Contains fields that are
// required to perform Apple-specific integrity checks.
type GoogleCloudRecaptchaenterpriseV1AppleDeveloperId struct {
	// KeyId: Required. The Apple developer key ID (10-character string).
	KeyId string `json:"keyId,omitempty"`
	// PrivateKey: Required. Input only. A private key (downloaded as a text file
	// with a .p8 file extension) generated for your Apple Developer account.
	// Ensure that Apple DeviceCheck is enabled for the private key.
	PrivateKey string `json:"privateKey,omitempty"`
	// TeamId: Required. The Apple team ID (10-character string) owning the
	// provisioning profile used to build your application.
	TeamId string `json:"teamId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KeyId") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KeyId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AppleDeveloperId) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AppleDeveloperId
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Assessment: A reCAPTCHA Enterprise
// assessment resource.
type GoogleCloudRecaptchaenterpriseV1Assessment struct {
	// AccountDefenderAssessment: Output only. Assessment returned by Account
	// defense when an account identifier is provided.
	AccountDefenderAssessment *GoogleCloudRecaptchaenterpriseV1AccountDefenderAssessment `json:"accountDefenderAssessment,omitempty"`
	// AccountVerification: Optional. Account verification information for identity
	// verification. The assessment event must include a token and site key to use
	// this feature.
	AccountVerification *GoogleCloudRecaptchaenterpriseV1AccountVerificationInfo `json:"accountVerification,omitempty"`
	// AssessmentEnvironment: Optional. The environment creating the assessment.
	// This describes your environment (the system invoking CreateAssessment), NOT
	// the environment of your user.
	AssessmentEnvironment *GoogleCloudRecaptchaenterpriseV1AssessmentEnvironment `json:"assessmentEnvironment,omitempty"`
	// Event: Optional. The event being assessed.
	Event *GoogleCloudRecaptchaenterpriseV1Event `json:"event,omitempty"`
	// FirewallPolicyAssessment: Output only. Assessment returned when firewall
	// policies belonging to the project are evaluated using the field
	// firewall_policy_evaluation.
	FirewallPolicyAssessment *GoogleCloudRecaptchaenterpriseV1FirewallPolicyAssessment `json:"firewallPolicyAssessment,omitempty"`
	// FraudPreventionAssessment: Output only. Assessment returned by Fraud
	// Prevention when TransactionData is provided.
	FraudPreventionAssessment *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment `json:"fraudPreventionAssessment,omitempty"`
	// FraudSignals: Output only. Fraud Signals specific to the users involved in a
	// payment transaction.
	FraudSignals *GoogleCloudRecaptchaenterpriseV1FraudSignals `json:"fraudSignals,omitempty"`
	// Name: Output only. Identifier. The resource name for the Assessment in the
	// format `projects/{project}/assessments/{assessment}`.
	Name string `json:"name,omitempty"`
	// PhoneFraudAssessment: Output only. Assessment returned when a site key, a
	// token, and a phone number as `user_id` are provided. SMS defense needs to be
	// enabled.
	PhoneFraudAssessment *GoogleCloudRecaptchaenterpriseV1PhoneFraudAssessment `json:"phoneFraudAssessment,omitempty"`
	// PolicyEvaluation: Output only. Provides information about the policy
	// evaluation for this assessment.
	PolicyEvaluation *GoogleCloudRecaptchaenterpriseV1PolicyEvaluation `json:"policyEvaluation,omitempty"`
	// PrivatePasswordLeakVerification: Optional. The private password leak
	// verification field contains the parameters that are used to to check for
	// leaks privately without sharing user credentials.
	PrivatePasswordLeakVerification *GoogleCloudRecaptchaenterpriseV1PrivatePasswordLeakVerification `json:"privatePasswordLeakVerification,omitempty"`
	// RiskAnalysis: Output only. The risk analysis result for the event being
	// assessed.
	RiskAnalysis *GoogleCloudRecaptchaenterpriseV1RiskAnalysis `json:"riskAnalysis,omitempty"`
	// TokenProperties: Output only. Properties of the provided event token.
	TokenProperties *GoogleCloudRecaptchaenterpriseV1TokenProperties `json:"tokenProperties,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AccountDefenderAssessment")
	// to unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountDefenderAssessment") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Assessment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Assessment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1AssessmentEnvironment: The environment
// creating the assessment. This describes your environment (the system
// invoking CreateAssessment), NOT the environment of your user.
type GoogleCloudRecaptchaenterpriseV1AssessmentEnvironment struct {
	// Client: Optional. Identifies the client module initiating the
	// CreateAssessment request. This can be the link to the client module's
	// project. Examples include: -
	// "github.com/GoogleCloudPlatform/recaptcha-enterprise-google-tag-manager" -
	// "wordpress.org/plugins/recaptcha-something"
	Client string `json:"client,omitempty"`
	// Version: Optional. The version of the client module. For example, "1.0.0".
	Version string `json:"version,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Client") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Client") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1AssessmentEnvironment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1AssessmentEnvironment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Bot: Bot information and metadata.
type GoogleCloudRecaptchaenterpriseV1Bot struct {
	// BotType: Optional. Enumerated field representing the type of bot.
	//
	// Possible values:
	//   "BOT_TYPE_UNSPECIFIED" - Default unspecified type.
	//   "AI_AGENT" - Software program that interacts with a site and performs
	// tasks autonomously.
	//   "CONTENT_SCRAPER" - Software that extracts specific data from sites for
	// use.
	//   "SEARCH_INDEXER" - Software that crawls sites and stores content for the
	// purpose of efficient retrieval, likely as part of a search engine.
	BotType string `json:"botType,omitempty"`
	// Name: Optional. Enumerated string value that indicates the identity of the
	// bot, formatted in kebab-case. Current example values include the following:
	// * google-agent - AI_AGENT * browser-base - AI_AGENT * chat-gpt - AI_AGENT *
	// aws-bedrock - AI_AGENT * cybaa-bot - AI_AGENT * cloudflare - AI_AGENT *
	// payhawk - AI_AGENT * duck-duck-go - SEARCH_INDEXER * mediaboard -
	// CONTENT_SCRAPER * marker-io - AI_AGENT * broadcom - AI_AGENT *
	// anchor-browser - AI_AGENT * shopify - AI_AGENT * stackscope -
	// CONTENT_SCRAPER * manus - AI_AGENT * kernel-sh - AI_AGENT * zvelo -
	// SEARCH_INDEXER Ensure that your applications can handle identifier values
	// not explicitly listed here. Deprecated values might take some time to stop
	// showing up in responses. New values can be pushed so this list should be
	// taken as non exhaustive.
	Name string `json:"name,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BotType") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BotType") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Bot) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Bot
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ChallengeMetrics: Metrics related to
// challenges.
type GoogleCloudRecaptchaenterpriseV1ChallengeMetrics struct {
	// FailedCount: Count of submitted challenge solutions that were incorrect or
	// otherwise deemed suspicious such that a subsequent challenge was triggered.
	FailedCount int64 `json:"failedCount,omitempty,string"`
	// NocaptchaCount: Count of nocaptchas (successful verification without a
	// challenge) issued.
	NocaptchaCount int64 `json:"nocaptchaCount,omitempty,string"`
	// PageloadCount: Count of reCAPTCHA checkboxes or badges rendered. This is
	// mostly equivalent to a count of pageloads for pages that include reCAPTCHA.
	PageloadCount int64 `json:"pageloadCount,omitempty,string"`
	// PassedCount: Count of nocaptchas (successful verification without a
	// challenge) plus submitted challenge solutions that were correct and resulted
	// in verification.
	PassedCount int64 `json:"passedCount,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "FailedCount") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "FailedCount") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ChallengeMetrics) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ChallengeMetrics
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ChallengeRule: A rule to configure the
// behavior of reCAPTCHA for conditionally presenting a challenge.
type GoogleCloudRecaptchaenterpriseV1ChallengeRule struct {
	// Challenge: Present a challenge to the user.
	Challenge *GoogleCloudRecaptchaenterpriseV1ChallengeRuleChallengeOutcome `json:"challenge,omitempty"`
	// Condition: Optional. A CEL condition that must be met for this rule to
	// apply. If unspecified, the rule applies unconditionally. The following
	// fields can be referenced in the condition: * `score` * `user_ip_address` *
	// `user_asn` * `user_agent` * `verified_bots.name` * `verified_bots.bot_type`
	// Examples: * `score < 0.5` * `user_ip_address == "123.45.67.89" *
	// `user_agent.contains("Chrome")` * `score < 0.5 && user_ip_address ==
	// "123.45.67.89"
	Condition string `json:"condition,omitempty"`
	// NoChallenge: Do not present a challenge to the user.
	NoChallenge *GoogleCloudRecaptchaenterpriseV1ChallengeRuleNoChallengeOutcome `json:"noChallenge,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Challenge") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Challenge") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ChallengeRule) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ChallengeRule
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ChallengeRuleChallengeOutcome: An outcome
// that indicates that a challenge of a specified difficulty should be
// presented to the user.
type GoogleCloudRecaptchaenterpriseV1ChallengeRuleChallengeOutcome struct {
	// Difficulty: Optional. The difficulty of the challenge to present to the
	// user. If unspecified, `BALANCE` is used.
	//
	// Possible values:
	//   "CHALLENGE_SECURITY_PREFERENCE_UNSPECIFIED" - Default type that indicates
	// this enum hasn't been specified.
	//   "USABILITY" - Key tends to show fewer and easier challenges.
	//   "BALANCE" - Key tends to show balanced (in amount and difficulty)
	// challenges.
	//   "SECURITY" - Key tends to show more and harder challenges.
	Difficulty string `json:"difficulty,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Difficulty") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Difficulty") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ChallengeRuleChallengeOutcome) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ChallengeRuleChallengeOutcome
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ChallengeRuleEvaluation: Information about
// the evaluation of a `ChallengeRule`.
type GoogleCloudRecaptchaenterpriseV1ChallengeRuleEvaluation struct {
}

// GoogleCloudRecaptchaenterpriseV1ChallengeRuleGroup: A collection of
// challenge rules that applies to one or more actions.
type GoogleCloudRecaptchaenterpriseV1ChallengeRuleGroup struct {
	// Actions: Required. Action name provided at token generation. The action name
	// is not case-sensitive and can only contain alphanumeric characters, slashes,
	// and underscores. If "*" is provided, the rule group applies to all actions.
	// If multiple actions are provided, the rule group is applied to all of them.
	// This field is required.
	Actions []string `json:"actions,omitempty"`
	// ChallengeRules: Required. A list of rules that configure when and how
	// reCAPTCHA presents a challenge. reCAPTCHA evaluates these rules in order and
	// applies the first one that matches.
	ChallengeRules []*GoogleCloudRecaptchaenterpriseV1ChallengeRule `json:"challengeRules,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Actions") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Actions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ChallengeRuleGroup) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ChallengeRuleGroup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ChallengeRuleNoChallengeOutcome: An outcome
// that indicates that no challenge should be presented to the user.
type GoogleCloudRecaptchaenterpriseV1ChallengeRuleNoChallengeOutcome struct {
}

// GoogleCloudRecaptchaenterpriseV1ClientSettings: Configuration for clients to
// protect with reCAPTCHA.
type GoogleCloudRecaptchaenterpriseV1ClientSettings struct {
	// AllowAllDomains: Optional. If set to true, it means allowed_domains are not
	// enforced.
	AllowAllDomains bool `json:"allowAllDomains,omitempty"`
	// AllowedDomains: Optional. Domains or subdomains of websites allowed to use
	// the policy. All subdomains of an allowed domain are automatically allowed. A
	// valid domain requires a host and must not include any path, port, query or
	// fragment. Examples: 'example.com' or 'subdomain.example.com' Each policy
	// supports a maximum of 250 domains. To use a policy on more domains, set
	// `allow_all_domains` to true. When this is set, you are responsible for
	// validating the hostname by checking the `token_properties.hostname` field in
	// each assessment response against your list of allowed domains.
	AllowedDomains []string `json:"allowedDomains,omitempty"`
	// ProtectedEndpointGroup: Optional. Configuration for all API endpoints to
	// protect with reCAPTCHA. If this field is not set, reCAPTCHA will not
	// automatically request tokens on any API endpoints.
	ProtectedEndpointGroup *GoogleCloudRecaptchaenterpriseV1ProtectedEndpointGroup `json:"protectedEndpointGroup,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowAllDomains") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AllowAllDomains") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ClientSettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ClientSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1EndpointVerificationInfo: Information about
// a verification endpoint that can be used for 2FA.
type GoogleCloudRecaptchaenterpriseV1EndpointVerificationInfo struct {
	// EmailAddress: Email address for which to trigger a verification request.
	EmailAddress string `json:"emailAddress,omitempty"`
	// LastVerificationTime: Output only. Timestamp of the last successful
	// verification for the endpoint, if any.
	LastVerificationTime string `json:"lastVerificationTime,omitempty"`
	// PhoneNumber: Phone number for which to trigger a verification request.
	// Should be given in E.164 format.
	PhoneNumber string `json:"phoneNumber,omitempty"`
	// RequestToken: Output only. Token to provide to the client to trigger
	// endpoint verification. It must be used within 15 minutes.
	RequestToken string `json:"requestToken,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EmailAddress") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EmailAddress") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1EndpointVerificationInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1EndpointVerificationInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Event: The event being assessed.
type GoogleCloudRecaptchaenterpriseV1Event struct {
	// ExpectedAction: Optional. The expected action for this type of event. This
	// should be the same action provided at token generation time on client-side
	// platforms already integrated with recaptcha enterprise. Required for
	// Universal keys.
	ExpectedAction string `json:"expectedAction,omitempty"`
	// Express: Optional. Flag for a reCAPTCHA express request for an assessment
	// without a token. If enabled, `site_key` must reference an Express site key.
	Express bool `json:"express,omitempty"`
	// FirewallPolicyEvaluation: Optional. Flag for enabling firewall policy config
	// assessment. If this flag is enabled, the firewall policy is evaluated and a
	// suggested firewall action is returned in the response.
	FirewallPolicyEvaluation bool `json:"firewallPolicyEvaluation,omitempty"`
	// FraudPrevention: Optional. The Fraud Prevention setting for this assessment.
	//
	// Possible values:
	//   "FRAUD_PREVENTION_UNSPECIFIED" - Default, unspecified setting.
	// `fraud_prevention_assessment` is returned if `transaction_data` is present
	// in `Event` and Fraud Prevention is enabled in the Google Cloud console.
	//   "ENABLED" - Enable Fraud Prevention for this assessment, if Fraud
	// Prevention is enabled in the Google Cloud console.
	//   "DISABLED" - Disable Fraud Prevention for this assessment, regardless of
	// the Google Cloud console settings.
	FraudPrevention string `json:"fraudPrevention,omitempty"`
	// HashedAccountId: Optional. Deprecated: use `user_info.account_id` instead.
	// Unique stable hashed user identifier for the request. The identifier must be
	// hashed using hmac-sha256 with stable secret.
	HashedAccountId string `json:"hashedAccountId,omitempty"`
	// Headers: Optional. HTTP header information about the request.
	Headers []string `json:"headers,omitempty"`
	// Ja3: Optional. JA3 fingerprint for SSL clients. To learn how to compute this
	// fingerprint, please refer to https://github.com/salesforce/ja3.
	Ja3 string `json:"ja3,omitempty"`
	// Ja4: Optional. JA4 fingerprint for SSL clients. To learn how to compute this
	// fingerprint, please refer to https://github.com/FoxIO-LLC/ja4.
	Ja4 string `json:"ja4,omitempty"`
	// RequestedUri: Optional. The URI resource the user requested that triggered
	// an assessment.
	RequestedUri string `json:"requestedUri,omitempty"`
	// SiteKey: Optional. The site key that was used to invoke reCAPTCHA Enterprise
	// on your site and generate the token.
	SiteKey string `json:"siteKey,omitempty"`
	// Token: Optional. The user response token provided by the reCAPTCHA
	// Enterprise client-side integration on your site.
	Token string `json:"token,omitempty"`
	// TransactionData: Optional. Data describing a payment transaction to be
	// assessed. Sending this data enables reCAPTCHA Enterprise Fraud Prevention
	// and the FraudPreventionAssessment component in the response.
	TransactionData *GoogleCloudRecaptchaenterpriseV1TransactionData `json:"transactionData,omitempty"`
	// UserAgent: Optional. The user agent present in the request from the user's
	// device related to this event.
	UserAgent string `json:"userAgent,omitempty"`
	// UserInfo: Optional. Information about the user that generates this event,
	// when they can be identified. They are often identified through the use of an
	// account for logged-in requests or login/registration requests, or by
	// providing user identifiers for guest actions like checkout.
	UserInfo *GoogleCloudRecaptchaenterpriseV1UserInfo `json:"userInfo,omitempty"`
	// UserIpAddress: Optional. The IP address in the request from the user's
	// device related to this event.
	UserIpAddress string `json:"userIpAddress,omitempty"`
	// WafTokenAssessment: Optional. Flag for running Web Application Firewall
	// (WAF) token assessment. If enabled, the token must be specified, and have
	// been created by a WAF-enabled key.
	WafTokenAssessment bool `json:"wafTokenAssessment,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExpectedAction") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExpectedAction") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Event) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Event
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ExpressKeySettings: Settings specific to
// keys that can be used for reCAPTCHA Express.
type GoogleCloudRecaptchaenterpriseV1ExpressKeySettings struct {
}

// GoogleCloudRecaptchaenterpriseV1FirewallAction: An individual action. Each
// action represents what to do if a policy matches.
type GoogleCloudRecaptchaenterpriseV1FirewallAction struct {
	// Allow: The user request did not match any policy and should be allowed
	// access to the requested resource.
	Allow *GoogleCloudRecaptchaenterpriseV1FirewallActionAllowAction `json:"allow,omitempty"`
	// Block: This action denies access to a given page. The user gets an HTTP
	// error code.
	Block *GoogleCloudRecaptchaenterpriseV1FirewallActionBlockAction `json:"block,omitempty"`
	// IncludeRecaptchaScript: This action injects reCAPTCHA JavaScript code into
	// the HTML page returned by the site backend.
	IncludeRecaptchaScript *GoogleCloudRecaptchaenterpriseV1FirewallActionIncludeRecaptchaScriptAction `json:"includeRecaptchaScript,omitempty"`
	// Redirect: This action redirects the request to a reCAPTCHA interstitial to
	// attach a token.
	Redirect *GoogleCloudRecaptchaenterpriseV1FirewallActionRedirectAction `json:"redirect,omitempty"`
	// SetHeader: This action sets a custom header but allow the request to
	// continue to the customer backend.
	SetHeader *GoogleCloudRecaptchaenterpriseV1FirewallActionSetHeaderAction `json:"setHeader,omitempty"`
	// Substitute: This action transparently serves a different page to an
	// offending user.
	Substitute *GoogleCloudRecaptchaenterpriseV1FirewallActionSubstituteAction `json:"substitute,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Allow") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Allow") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FirewallAction) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FirewallAction
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionAllowAction: An allow action
// continues processing a request unimpeded.
type GoogleCloudRecaptchaenterpriseV1FirewallActionAllowAction struct {
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionBlockAction: A block action
// serves an HTTP error code a prevents the request from hitting the backend.
type GoogleCloudRecaptchaenterpriseV1FirewallActionBlockAction struct {
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionIncludeRecaptchaScriptAction:
// An include reCAPTCHA script action involves injecting reCAPTCHA JavaScript
// code into the HTML returned by the site backend. This reCAPTCHA script is
// tasked with collecting user signals on the requested web page, issuing
// tokens as a cookie within the site domain, and enabling their utilization in
// subsequent page requests.
type GoogleCloudRecaptchaenterpriseV1FirewallActionIncludeRecaptchaScriptAction struct {
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionRedirectAction: A redirect
// action returns a 307 (temporary redirect) response, pointing the user to a
// reCAPTCHA interstitial page to attach a token.
type GoogleCloudRecaptchaenterpriseV1FirewallActionRedirectAction struct {
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionSetHeaderAction: A set header
// action sets a header and forwards the request to the backend. This can be
// used to trigger custom protection implemented on the backend.
type GoogleCloudRecaptchaenterpriseV1FirewallActionSetHeaderAction struct {
	// Key: Optional. The header key to set in the request to the backend server.
	Key string `json:"key,omitempty"`
	// Value: Optional. The header value to set in the request to the backend
	// server.
	Value string `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Key") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Key") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FirewallActionSetHeaderAction) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FirewallActionSetHeaderAction
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FirewallActionSubstituteAction: A substitute
// action transparently serves a different page than the one requested.
type GoogleCloudRecaptchaenterpriseV1FirewallActionSubstituteAction struct {
	// Path: Optional. The address to redirect to. The target is a relative path in
	// the current host. Example: "/blog/404.html".
	Path string `json:"path,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Path") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Path") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FirewallActionSubstituteAction) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FirewallActionSubstituteAction
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FirewallPolicy: A FirewallPolicy represents
// a single matching pattern and resulting actions to take.
type GoogleCloudRecaptchaenterpriseV1FirewallPolicy struct {
	// Actions: Optional. The actions that the caller should take regarding user
	// access. There should be at most one terminal action. A terminal action is
	// any action that forces a response, such as `AllowAction`, `BlockAction` or
	// `SubstituteAction`. Zero or more non-terminal actions such as `SetHeader`
	// might be specified. A single policy can contain up to 16 actions.
	Actions []*GoogleCloudRecaptchaenterpriseV1FirewallAction `json:"actions,omitempty"`
	// Condition: Optional. A CEL (Common Expression Language) conditional
	// expression that specifies if this policy applies to an incoming user
	// request. If this condition evaluates to true and the requested path matched
	// the path pattern, the associated actions should be executed by the caller.
	// The condition string is checked for CEL syntax correctness on creation. For
	// more information, see the CEL spec (https://github.com/google/cel-spec) and
	// its language definition
	// (https://github.com/google/cel-spec/blob/master/doc/langdef.md). A condition
	// has a max length of 500 characters.
	Condition string `json:"condition,omitempty"`
	// Description: Optional. A description of what this policy aims to achieve,
	// for convenience purposes. The description can at most include 256 UTF-8
	// characters.
	Description string `json:"description,omitempty"`
	// Name: Identifier. The resource name for the FirewallPolicy in the format
	// `projects/{project}/firewallpolicies/{firewallpolicy}`.
	Name string `json:"name,omitempty"`
	// Path: Optional. The path for which this policy applies, specified as a glob
	// pattern. For more information on glob, see the manual page
	// (https://man7.org/linux/man-pages/man7/glob.7.html). A path has a max length
	// of 200 characters.
	Path string `json:"path,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Actions") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Actions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FirewallPolicy) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FirewallPolicy
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FirewallPolicyAssessment: Policy config
// assessment.
type GoogleCloudRecaptchaenterpriseV1FirewallPolicyAssessment struct {
	// Error: Output only. If the processing of a policy config fails, an error is
	// populated and the firewall_policy is left empty.
	Error *GoogleRpcStatus `json:"error,omitempty"`
	// FirewallPolicy: Output only. The policy that matched the request. If more
	// than one policy may match, this is the first match. If no policy matches the
	// incoming request, the policy field is left empty.
	FirewallPolicy *GoogleCloudRecaptchaenterpriseV1FirewallPolicy `json:"firewallPolicy,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Error") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Error") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FirewallPolicyAssessment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FirewallPolicyAssessment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment: Assessment for
// Fraud Prevention.
type GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment struct {
	// BehavioralTrustVerdict: Output only. Assessment of this transaction for
	// behavioral trust.
	BehavioralTrustVerdict *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict `json:"behavioralTrustVerdict,omitempty"`
	// CardTestingVerdict: Output only. Assessment of this transaction for risk of
	// being part of a card testing attack.
	CardTestingVerdict *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict `json:"cardTestingVerdict,omitempty"`
	// RiskReasons: Output only. Reasons why the transaction is probably fraudulent
	// and received a high transaction risk score.
	RiskReasons []*GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentRiskReason `json:"riskReasons,omitempty"`
	// StolenInstrumentVerdict: Output only. Assessment of this transaction for
	// risk of a stolen instrument.
	StolenInstrumentVerdict *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict `json:"stolenInstrumentVerdict,omitempty"`
	// TransactionRisk: Output only. Probability of this transaction being
	// fraudulent. Summarizes the combined risk of attack vectors below. Values are
	// from 0.0 (lowest) to 1.0 (highest).
	TransactionRisk float64 `json:"transactionRisk,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BehavioralTrustVerdict") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BehavioralTrustVerdict") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessment
	var s1 struct {
		TransactionRisk gensupport.JSONFloat64 `json:"transactionRisk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.TransactionRisk = float64(s1.TransactionRisk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdi
// ct: Information about behavioral trust of the transaction.
type GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict struct {
	// Trust: Output only. Probability of this transaction attempt being executed
	// in a behaviorally trustworthy way. Values are from 0.0 (lowest) to 1.0
	// (highest).
	Trust float64 `json:"trust,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Trust") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Trust") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentBehavioralTrustVerdict
	var s1 struct {
		Trust gensupport.JSONFloat64 `json:"trust"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Trust = float64(s1.Trust)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict:
// Information about card testing fraud, where an adversary is testing
// fraudulently obtained cards or brute forcing their details.
type GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict struct {
	// Risk: Output only. Probability of this transaction attempt being part of a
	// card testing attack. Values are from 0.0 (lowest) to 1.0 (highest).
	Risk float64 `json:"risk,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Risk") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Risk") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentCardTestingVerdict
	var s1 struct {
		Risk gensupport.JSONFloat64 `json:"risk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Risk = float64(s1.Risk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentRiskReason: Risk
// reasons applicable to the Fraud Prevention assessment.
type GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentRiskReason struct {
	// Reason: Output only. Risk reasons applicable to the Fraud Prevention
	// assessment.
	//
	// Possible values:
	//   "REASON_UNSPECIFIED" - Default unspecified type.
	//   "HIGH_TRANSACTION_VELOCITY" - A suspiciously high number of recent
	// transactions have used identifiers present in this transaction.
	//   "EXCESSIVE_ENUMERATION_PATTERN" - User is cycling through a suspiciously
	// large number of identifiers, suggesting enumeration or validation attacks
	// within a potential fraud network.
	//   "SHORT_IDENTITY_HISTORY" - User has a short history or no history in the
	// reCAPTCHA network, suggesting the possibility of synthetic identity
	// generation.
	//   "GEOLOCATION_DISCREPANCY" - Identifiers used in this transaction originate
	// from an unusual or conflicting set of geolocations.
	//   "ASSOCIATED_WITH_FRAUD_CLUSTER" - This transaction is linked to a cluster
	// of known fraudulent activity.
	Reason string `json:"reason,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Reason") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Reason") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentRiskReason) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentRiskReason
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerd
// ict: Information about stolen instrument fraud, where the user is not the
// legitimate owner of the instrument being used for the purchase.
type GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict struct {
	// Risk: Output only. Probability of this transaction being executed with a
	// stolen instrument. Values are from 0.0 (lowest) to 1.0 (highest).
	Risk float64 `json:"risk,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Risk") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Risk") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudPreventionAssessmentStolenInstrumentVerdict
	var s1 struct {
		Risk gensupport.JSONFloat64 `json:"risk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Risk = float64(s1.Risk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1FraudSignals: Fraud signals describing users
// and cards involved in the transaction.
type GoogleCloudRecaptchaenterpriseV1FraudSignals struct {
	// CardSignals: Output only. Signals describing the payment card or cards used
	// in this transaction.
	CardSignals *GoogleCloudRecaptchaenterpriseV1FraudSignalsCardSignals `json:"cardSignals,omitempty"`
	// UserSignals: Output only. Signals describing the end user in this
	// transaction.
	UserSignals *GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals `json:"userSignals,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CardSignals") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CardSignals") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudSignals) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudSignals
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FraudSignalsCardSignals: Signals describing
// the payment card used in this transaction.
type GoogleCloudRecaptchaenterpriseV1FraudSignalsCardSignals struct {
	// CardLabels: Output only. The labels for the payment card in this
	// transaction.
	//
	// Possible values:
	//   "CARD_LABEL_UNSPECIFIED" - No label specified.
	//   "PREPAID" - This card has been detected as prepaid.
	//   "VIRTUAL" - This card has been detected as virtual, such as a card number
	// generated for a single transaction or merchant.
	//   "UNEXPECTED_LOCATION" - This card has been detected as being used in an
	// unexpected geographic location.
	CardLabels []string `json:"cardLabels,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CardLabels") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CardLabels") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudSignalsCardSignals) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudSignalsCardSignals
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals: Signals describing
// the user involved in this transaction.
type GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals struct {
	// ActiveDaysLowerBound: Output only. This user (based on email, phone, and
	// other identifiers) has been seen on the internet for at least this number of
	// days.
	ActiveDaysLowerBound int64 `json:"activeDaysLowerBound,omitempty"`
	// SyntheticRisk: Output only. Likelihood (from 0.0 to 1.0) this user includes
	// synthetic components in their identity, such as a randomly generated email
	// address, temporary phone number, or fake shipping address.
	SyntheticRisk float64 `json:"syntheticRisk,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ActiveDaysLowerBound") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ActiveDaysLowerBound") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1FraudSignalsUserSignals
	var s1 struct {
		SyntheticRisk gensupport.JSONFloat64 `json:"syntheticRisk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.SyntheticRisk = float64(s1.SyntheticRisk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1IOSKeySettings: Settings specific to keys
// that can be used by iOS apps.
type GoogleCloudRecaptchaenterpriseV1IOSKeySettings struct {
	// AllowAllBundleIds: Optional. If set to true, allowed_bundle_ids are not
	// enforced.
	AllowAllBundleIds bool `json:"allowAllBundleIds,omitempty"`
	// AllowedBundleIds: Optional. iOS bundle IDs of apps allowed to use the key.
	// Example: 'com.companyname.productname.appname' Each key supports a maximum
	// of 250 bundle IDs. To use a key on more apps, set `allow_all_bundle_ids` to
	// true. When this is set, you are responsible for validating the bundle id by
	// checking the `token_properties.ios_bundle_id` field in each assessment
	// response against your list of allowed bundle IDs.
	AllowedBundleIds []string `json:"allowedBundleIds,omitempty"`
	// AppleDeveloperId: Optional. Apple Developer account details for the app that
	// is protected by the reCAPTCHA Key. reCAPTCHA leverages platform-specific
	// checks like Apple App Attest and Apple DeviceCheck to protect your app from
	// abuse. Providing these fields allows reCAPTCHA to get a better assessment of
	// the integrity of your app.
	AppleDeveloperId *GoogleCloudRecaptchaenterpriseV1AppleDeveloperId `json:"appleDeveloperId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowAllBundleIds") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AllowAllBundleIds") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1IOSKeySettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1IOSKeySettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1IpOverrideData: Information about the IP or
// IP range override.
type GoogleCloudRecaptchaenterpriseV1IpOverrideData struct {
	// Ip: Required. The IP address to override (can be IPv4, IPv6 or CIDR). The IP
	// override must be a valid IPv4 or IPv6 address, or a CIDR range. The IP
	// override must be a public IP address. Example of IPv4: 168.192.5.6 Example
	// of IPv6: 2001:0000:130F:0000:0000:09C0:876A:130B Example of IPv4 with CIDR:
	// 168.192.5.0/24 Example of IPv6 with CIDR: 2001:0DB8:1234::/48
	Ip string `json:"ip,omitempty"`
	// OverrideType: Required. Describes the type of IP override.
	//
	// Possible values:
	//   "OVERRIDE_TYPE_UNSPECIFIED" - Default override type that indicates this
	// enum hasn't been specified.
	//   "ALLOW" - Allowlist the IP address; i.e. give a `risk_analysis.score` of
	// 0.9 for all valid assessments.
	OverrideType string `json:"overrideType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Ip") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Ip") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1IpOverrideData) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1IpOverrideData
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Key: A key used to identify and configure
// applications (web and/or mobile) that use reCAPTCHA Enterprise.
type GoogleCloudRecaptchaenterpriseV1Key struct {
	// AndroidSettings: Settings for keys that can be used by Android apps.
	AndroidSettings *GoogleCloudRecaptchaenterpriseV1AndroidKeySettings `json:"androidSettings,omitempty"`
	// CreateTime: Output only. The timestamp corresponding to the creation of this
	// key.
	CreateTime string `json:"createTime,omitempty"`
	// DisplayName: Required. Human-readable display name of this key. Modifiable
	// by user.
	DisplayName string `json:"displayName,omitempty"`
	// ExpressSettings: Settings for keys that can be used by reCAPTCHA Express.
	ExpressSettings *GoogleCloudRecaptchaenterpriseV1ExpressKeySettings `json:"expressSettings,omitempty"`
	// IosSettings: Settings for keys that can be used by iOS apps.
	IosSettings *GoogleCloudRecaptchaenterpriseV1IOSKeySettings `json:"iosSettings,omitempty"`
	// Labels: Optional. See [Creating and managing labels]
	// (https://cloud.google.com/recaptcha/docs/labels).
	Labels map[string]string `json:"labels,omitempty"`
	// Name: Identifier. The resource name for the Key in the format
	// `projects/{project}/keys/{key}`.
	Name string `json:"name,omitempty"`
	// TestingOptions: Optional. Options for user acceptance testing.
	TestingOptions *GoogleCloudRecaptchaenterpriseV1TestingOptions `json:"testingOptions,omitempty"`
	// UniversalSettings: Settings for keys that are configured through their
	// Policy.
	UniversalSettings *GoogleCloudRecaptchaenterpriseV1UniversalKeySettings `json:"universalSettings,omitempty"`
	// WafSettings: Optional. Settings for Web Application Firewall (WAF).
	WafSettings *GoogleCloudRecaptchaenterpriseV1WafSettings `json:"wafSettings,omitempty"`
	// WebSettings: Settings for keys that can be used by websites.
	WebSettings *GoogleCloudRecaptchaenterpriseV1WebKeySettings `json:"webSettings,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AndroidSettings") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AndroidSettings") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Key) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Key
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse: Response to
// request to list firewall policies belonging to a project.
type GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse struct {
	// FirewallPolicies: Policy details.
	FirewallPolicies []*GoogleCloudRecaptchaenterpriseV1FirewallPolicy `json:"firewallPolicies,omitempty"`
	// NextPageToken: Token to retrieve the next page of results. It is set to
	// empty if no policies remain in results.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "FirewallPolicies") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "FirewallPolicies") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse: Response for
// ListIpOverrides.
type GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse struct {
	// IpOverrides: IP Overrides details.
	IpOverrides []*GoogleCloudRecaptchaenterpriseV1IpOverrideData `json:"ipOverrides,omitempty"`
	// NextPageToken: Token to retrieve the next page of results. If this field is
	// empty, no keys remain in the results.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "IpOverrides") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IpOverrides") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ListKeysResponse: Response to request to
// list keys in a project.
type GoogleCloudRecaptchaenterpriseV1ListKeysResponse struct {
	// Keys: Key details.
	Keys []*GoogleCloudRecaptchaenterpriseV1Key `json:"keys,omitempty"`
	// NextPageToken: Token to retrieve the next page of results. It is set to
	// empty if no keys remain in results.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Keys") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Keys") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ListKeysResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ListKeysResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse:
// The response to a `ListRelatedAccountGroupMemberships` call.
type GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse struct {
	// NextPageToken: A token, which can be sent as `page_token` to retrieve the
	// next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// RelatedAccountGroupMemberships: The memberships listed by the query.
	RelatedAccountGroupMemberships []*GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership `json:"relatedAccountGroupMemberships,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse: The
// response to a `ListRelatedAccountGroups` call.
type GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse struct {
	// NextPageToken: A token, which can be sent as `page_token` to retrieve the
	// next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// RelatedAccountGroups: The groups of related accounts listed by the query.
	RelatedAccountGroups []*GoogleCloudRecaptchaenterpriseV1RelatedAccountGroup `json:"relatedAccountGroups,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Metrics: Metrics for a single Key.
type GoogleCloudRecaptchaenterpriseV1Metrics struct {
	// ChallengeMetrics: Metrics are continuous and in order by dates, and in the
	// granularity of day. Only challenge-based keys (CHECKBOX, INVISIBLE) have
	// challenge-based data.
	ChallengeMetrics []*GoogleCloudRecaptchaenterpriseV1ChallengeMetrics `json:"challengeMetrics,omitempty"`
	// Name: Output only. Identifier. The name of the metrics, in the format
	// `projects/{project}/keys/{key}/metrics`.
	Name string `json:"name,omitempty"`
	// ScoreMetrics: Metrics are continuous and in order by dates, and in the
	// granularity of day. All Key types should have score-based data.
	ScoreMetrics []*GoogleCloudRecaptchaenterpriseV1ScoreMetrics `json:"scoreMetrics,omitempty"`
	// StartTime: Inclusive start time aligned to a day in the America/Los_Angeles
	// (Pacific) timezone.
	StartTime string `json:"startTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ChallengeMetrics") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChallengeMetrics") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Metrics) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Metrics
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest: The migrate key request
// message.
type GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest struct {
	// SkipBillingCheck: Optional. If true, skips the billing check. A reCAPTCHA
	// Enterprise key or migrated key behaves differently than a reCAPTCHA
	// (non-Enterprise version) key when you reach a quota limit (see
	// https://docs.cloud.google.com/recaptcha/quotas#quota_limit). To avoid any
	// disruption of your usage, we check that a billing account is present. If
	// your usage of reCAPTCHA is under the free quota, you can safely skip the
	// billing check and proceed with the migration. See
	// https://cloud.google.com/recaptcha/docs/billing-information.
	SkipBillingCheck bool `json:"skipBillingCheck,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SkipBillingCheck") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SkipBillingCheck") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1PhoneAuthenticationEvent: Details on a phone
// authentication event
type GoogleCloudRecaptchaenterpriseV1PhoneAuthenticationEvent struct {
	// EventTime: Optional. The time at which the multi-factor authentication event
	// (challenge or verification) occurred.
	EventTime string `json:"eventTime,omitempty"`
	// PhoneNumber: Required. Phone number in E.164 format for which a multi-factor
	// authentication challenge was initiated, succeeded, or failed.
	PhoneNumber string `json:"phoneNumber,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EventTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EventTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1PhoneAuthenticationEvent) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1PhoneAuthenticationEvent
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1PhoneFraudAssessment: Assessment for Phone
// Fraud
type GoogleCloudRecaptchaenterpriseV1PhoneFraudAssessment struct {
	// SmsTollFraudVerdict: Output only. Assessment of this phone event for risk of
	// SMS toll fraud.
	SmsTollFraudVerdict *GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict `json:"smsTollFraudVerdict,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SmsTollFraudVerdict") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SmsTollFraudVerdict") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1PhoneFraudAssessment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1PhoneFraudAssessment
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1Policy: A complete configuration set
// containing multiple grouped rules defining the behavior of reCAPTCHA for
// fraud detection and prevention.
type GoogleCloudRecaptchaenterpriseV1Policy struct {
	// ChallengeRuleGroups: Optional. Rules to configure the behavior of reCAPTCHA
	// for showing a challenge. Rule groups are evaluated in order. Evaluation
	// stops when the first matching rule group is found.
	ChallengeRuleGroups []*GoogleCloudRecaptchaenterpriseV1ChallengeRuleGroup `json:"challengeRuleGroups,omitempty"`
	// ClientSettings: Required. Configuration for clients protected by this
	// policy.
	ClientSettings *GoogleCloudRecaptchaenterpriseV1ClientSettings `json:"clientSettings,omitempty"`
	// Name: Identifier. Resource name for this policy. Format:
	// "projects/{project}/keys/{key}/policy" for a policy under a key.
	Name string `json:"name,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ChallengeRuleGroups") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChallengeRuleGroups") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1Policy) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1Policy
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1PolicyEvaluation: Information about the
// policy evaluation.
type GoogleCloudRecaptchaenterpriseV1PolicyEvaluation struct {
	// ChallengeRuleEvaluation: Output only. Populated if one or more Challenge
	// rules were matched. Its presence in the assessment indicates that at least
	// one challenge rule was matched and determined whether a challenge was
	// presented to the user.
	ChallengeRuleEvaluation *GoogleCloudRecaptchaenterpriseV1ChallengeRuleEvaluation `json:"challengeRuleEvaluation,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ChallengeRuleEvaluation") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChallengeRuleEvaluation") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1PolicyEvaluation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1PolicyEvaluation
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1PrivatePasswordLeakVerification: Private
// password leak verification info.
type GoogleCloudRecaptchaenterpriseV1PrivatePasswordLeakVerification struct {
	// EncryptedLeakMatchPrefixes: Output only. List of prefixes of the encrypted
	// potential password leaks that matched the given parameters. They must be
	// compared with the client-side decryption prefix of
	// `reencrypted_user_credentials_hash`
	EncryptedLeakMatchPrefixes []string `json:"encryptedLeakMatchPrefixes,omitempty"`
	// EncryptedUserCredentialsHash: Optional. Encrypted Scrypt hash of the
	// canonicalized username+password. It is re-encrypted by the server and
	// returned through `reencrypted_user_credentials_hash`.
	EncryptedUserCredentialsHash string `json:"encryptedUserCredentialsHash,omitempty"`
	// LookupHashPrefix: Required. Exactly 26-bit prefix of the SHA-256 hash of the
	// canonicalized username. It is used to look up password leaks associated with
	// that hash prefix.
	LookupHashPrefix string `json:"lookupHashPrefix,omitempty"`
	// ReencryptedUserCredentialsHash: Output only. Corresponds to the
	// re-encryption of the `encrypted_user_credentials_hash` field. It is used to
	// match potential password leaks within `encrypted_leak_match_prefixes`.
	ReencryptedUserCredentialsHash string `json:"reencryptedUserCredentialsHash,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EncryptedLeakMatchPrefixes")
	// to unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptedLeakMatchPrefixes") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1PrivatePasswordLeakVerification) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1PrivatePasswordLeakVerification
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ProtectedEndpoint: Configuration for an API
// endpoint to protect with reCAPTCHA.
type GoogleCloudRecaptchaenterpriseV1ProtectedEndpoint struct {
	// Action: Required. Action name to be used for token generation for this
	// endpoint. The action name can only contain alphanumeric characters, slashes,
	// and underscores.
	Action string `json:"action,omitempty"`
	// Path: Required. URI path of the API endpoint to protect. Must start with
	// '/'. Supports glob characters '*' to match a single path segment and '**' to
	// match multiple path segments. Standalone root catch-alls ('/*' and '/**')
	// are invalid because it can negatively impact performance to trigger
	// reCAPTCHA on every single request to your backend. Matching is evaluated
	// against the URL path only (domain, scheme, and query parameters are
	// ignored). Examples: - `/login` matches `/login`,
	// `https://example.com/login`, and `/login?query=1`, but not `/login/step1`. -
	// `/products/*` matches `/products/123`, but not `/products/123/456`. -
	// `/content/**` matches `/content/articles/2024/01/01`.
	Path string `json:"path,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Action") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Action") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ProtectedEndpoint) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ProtectedEndpoint
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ProtectedEndpointGroup: Configuration for
// API endpoints to protect with reCAPTCHA.
type GoogleCloudRecaptchaenterpriseV1ProtectedEndpointGroup struct {
	// ProtectedEndpoints: Optional. List of API endpoints to automatically protect
	// with reCAPTCHA. If any of these endpoints is invoked from a page where a key
	// bound to this policy is installed, a reCAPTCHA token is automatically
	// generated and attached to the request. If multiple protected endpoints match
	// a given API endpoint, the first one in the list is used.
	ProtectedEndpoints []*GoogleCloudRecaptchaenterpriseV1ProtectedEndpoint `json:"protectedEndpoints,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ProtectedEndpoints") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ProtectedEndpoints") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ProtectedEndpointGroup) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ProtectedEndpointGroup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1RelatedAccountGroup: A group of related
// accounts.
type GoogleCloudRecaptchaenterpriseV1RelatedAccountGroup struct {
	// Name: Required. Identifier. The resource name for the related account group
	// in the format
	// `projects/{project}/relatedaccountgroups/{related_account_group}`.
	Name string `json:"name,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Name") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Name") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1RelatedAccountGroup) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RelatedAccountGroup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership: A membership
// in a group of related accounts.
type GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership struct {
	// AccountId: The unique stable account identifier of the member. The
	// identifier corresponds to an `account_id` provided in a previous
	// `CreateAssessment` or `AnnotateAssessment` call.
	AccountId string `json:"accountId,omitempty"`
	// HashedAccountId: Deprecated: use `account_id` instead. The unique stable
	// hashed account identifier of the member. The identifier corresponds to a
	// `hashed_account_id` provided in a previous `CreateAssessment` or
	// `AnnotateAssessment` call.
	HashedAccountId string `json:"hashedAccountId,omitempty"`
	// Name: Required. Identifier. The resource name for this membership in the
	// format
	// `projects/{project}/relatedaccountgroups/{relatedaccountgroup}/memberships/{m
	// embership}`.
	Name string `json:"name,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest: The
// RemoveIpOverride request message.
type GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest struct {
	// IpOverrideData: Required. IP override to be removed from the key.
	IpOverrideData *GoogleCloudRecaptchaenterpriseV1IpOverrideData `json:"ipOverrideData,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IpOverrideData") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IpOverrideData") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideResponse: Response for
// RemoveIpOverride.
type GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideResponse struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest: The reorder
// firewall policies request message.
type GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest struct {
	// Names: Required. A list containing all policy names, in the new order. Each
	// name is in the format
	// `projects/{project}/firewallpolicies/{firewallpolicy}`.
	Names []string `json:"names,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Names") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Names") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesResponse: The reorder
// firewall policies response message.
type GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesResponse struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse: Secret key
// is used only in legacy reCAPTCHA. It must be used in a 3rd party integration
// with legacy reCAPTCHA.
type GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse struct {
	// LegacySecretKey: The secret key (also known as shared secret) authorizes
	// communication between your application backend and the reCAPTCHA Enterprise
	// server to create an assessment. The secret key needs to be kept safe for
	// security purposes.
	LegacySecretKey string `json:"legacySecretKey,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "LegacySecretKey") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "LegacySecretKey") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1RiskAnalysis: Risk analysis result for an
// event.
type GoogleCloudRecaptchaenterpriseV1RiskAnalysis struct {
	// Challenge: Output only. Challenge information for Universal,
	// `POLICY_BASED_CHALLENGE` and `INVISIBLE` keys.
	//
	// Possible values:
	//   "CHALLENGE_UNSPECIFIED" - Default unspecified type.
	//   "NOCAPTCHA" - No challenge was presented for solving.
	//   "PASSED" - A solution was submitted that was correct.
	//   "FAILED" - A solution was submitted that was incorrect or otherwise deemed
	// suspicious.
	Challenge string `json:"challenge,omitempty"`
	// ExtendedVerdictReasons: Output only. Additional reasons contributing to the
	// risk analysis verdict. These reasons are available to Enterprise tier
	// projects only. Contact sales for more information. The set of reasons is
	// subject to change.
	ExtendedVerdictReasons []string `json:"extendedVerdictReasons,omitempty"`
	// LastChallengeType: Output only. Type of the last challenge presented to the
	// user for Universal, `POLICY_BASED_CHALLENGE` and `INVISIBLE` keys. The field
	// is only set when a challenge was presented to the user.
	//
	// Possible values:
	//   "CHALLENGE_TYPE_UNSPECIFIED" - Default unspecified type.
	//   "CHALLENGE_TYPE_VISUAL" - A visual challenge.
	//   "CHALLENGE_TYPE_AUDIO" - An audio challenge.
	LastChallengeType string `json:"lastChallengeType,omitempty"`
	// Reasons: Output only. Reasons contributing to the risk analysis verdict.
	//
	// Possible values:
	//   "CLASSIFICATION_REASON_UNSPECIFIED" - Default unspecified type.
	//   "AUTOMATION" - Interactions matched the behavior of an automated agent.
	//   "UNEXPECTED_ENVIRONMENT" - The event originated from an illegitimate
	// environment.
	//   "TOO_MUCH_TRAFFIC" - Traffic volume from the event source is higher than
	// normal.
	//   "UNEXPECTED_USAGE_PATTERNS" - Interactions with the site were
	// significantly different than expected patterns.
	//   "LOW_CONFIDENCE_SCORE" - Too little traffic has been received from this
	// site thus far to generate quality risk analysis.
	//   "SUSPECTED_CARDING" - Deprecated: Use
	// FraudPreventionAssessment.transaction_risk and
	// FraudPreventionAssessment.RiskReason.Reason.EXCESSIVE_ENUMERATION_PATTERN
	// instead.
	//   "SUSPECTED_CHARGEBACK" - Deprecated: Use
	// FraudPreventionAssessment.transaction_risk and
	// FraudPreventionAssessment.RiskReason.Reason.ASSOCIATED_WITH_FRAUD_CLUSTER
	// instead.
	Reasons []string `json:"reasons,omitempty"`
	// Score: Output only. Legitimate event score from 0.0 to 1.0. (1.0 means very
	// likely legitimate traffic while 0.0 means very likely non-legitimate
	// traffic).
	Score float64 `json:"score,omitempty"`
	// VerifiedBots: Output only. Bots with identities that have been verified by
	// reCAPTCHA and detected in the event.
	VerifiedBots []*GoogleCloudRecaptchaenterpriseV1Bot `json:"verifiedBots,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Challenge") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Challenge") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1RiskAnalysis) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RiskAnalysis
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1RiskAnalysis) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1RiskAnalysis
	var s1 struct {
		Score gensupport.JSONFloat64 `json:"score"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Score = float64(s1.Score)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1ScoreDistribution: Score distribution.
type GoogleCloudRecaptchaenterpriseV1ScoreDistribution struct {
	// ScoreBuckets: Map key is score value multiplied by 100. The scores are
	// discrete values between [0, 1]. The maximum number of buckets is on order of
	// a few dozen, but typically much lower (ie. 10).
	ScoreBuckets map[string]string `json:"scoreBuckets,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ScoreBuckets") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ScoreBuckets") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ScoreDistribution) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ScoreDistribution
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1ScoreMetrics: Metrics related to scoring.
type GoogleCloudRecaptchaenterpriseV1ScoreMetrics struct {
	// ActionMetrics: Action-based metrics. The map key is the action name which
	// specified by the site owners at time of the "execute" client-side call.
	ActionMetrics map[string]GoogleCloudRecaptchaenterpriseV1ScoreDistribution `json:"actionMetrics,omitempty"`
	// OverallMetrics: Aggregated score metrics for all traffic.
	OverallMetrics *GoogleCloudRecaptchaenterpriseV1ScoreDistribution `json:"overallMetrics,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ActionMetrics") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ActionMetrics") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1ScoreMetrics) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1ScoreMetrics
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest:
// The request message to search related account group memberships.
type GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest struct {
	// AccountId: Optional. The unique stable account identifier used to search
	// connections. The identifier should correspond to an `account_id` provided in
	// a previous `CreateAssessment` or `AnnotateAssessment` call. Either
	// hashed_account_id or account_id must be set, but not both.
	AccountId string `json:"accountId,omitempty"`
	// HashedAccountId: Optional. Deprecated: use `account_id` instead. The unique
	// stable hashed account identifier used to search connections. The identifier
	// should correspond to a `hashed_account_id` provided in a previous
	// `CreateAssessment` or `AnnotateAssessment` call. Either hashed_account_id or
	// account_id must be set, but not both.
	HashedAccountId string `json:"hashedAccountId,omitempty"`
	// PageSize: Optional. The maximum number of groups to return. The service
	// might return fewer than this value. If unspecified, at most 50 groups are
	// returned. The maximum value is 1000; values above 1000 are coerced to 1000.
	PageSize int64 `json:"pageSize,omitempty"`
	// PageToken: Optional. A page token, received from a previous
	// `SearchRelatedAccountGroupMemberships` call. Provide this to retrieve the
	// subsequent page. When paginating, all other parameters provided to
	// `SearchRelatedAccountGroupMemberships` must match the call that provided the
	// page token.
	PageToken string `json:"pageToken,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse:
//
//	The response to a `SearchRelatedAccountGroupMemberships` call.
type GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse struct {
	// NextPageToken: A token, which can be sent as `page_token` to retrieve the
	// next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// RelatedAccountGroupMemberships: The queried memberships.
	RelatedAccountGroupMemberships []*GoogleCloudRecaptchaenterpriseV1RelatedAccountGroupMembership `json:"relatedAccountGroupMemberships,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict: Information about SMS
// toll fraud.
type GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict struct {
	// Reasons: Output only. Reasons contributing to the SMS toll fraud verdict.
	//
	// Possible values:
	//   "SMS_TOLL_FRAUD_REASON_UNSPECIFIED" - Default unspecified reason
	//   "INVALID_PHONE_NUMBER" - The provided phone number was invalid
	Reasons []string `json:"reasons,omitempty"`
	// Risk: Output only. Probability of an SMS event being fraudulent. Values are
	// from 0.0 (lowest) to 1.0 (highest).
	Risk float64 `json:"risk,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Reasons") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Reasons") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1SmsTollFraudVerdict
	var s1 struct {
		Risk gensupport.JSONFloat64 `json:"risk"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Risk = float64(s1.Risk)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1TestingOptions: Options for user acceptance
// testing.
type GoogleCloudRecaptchaenterpriseV1TestingOptions struct {
	// TestingChallenge: Optional. For challenge-based keys only (CHECKBOX,
	// INVISIBLE), all challenge requests for this site return nocaptcha if
	// NOCAPTCHA, or an unsolvable challenge if CHALLENGE.
	//
	// Possible values:
	//   "TESTING_CHALLENGE_UNSPECIFIED" - Perform the normal risk analysis and
	// return either nocaptcha or a challenge depending on risk and trust factors.
	//   "NOCAPTCHA" - Challenge requests for this key always return a nocaptcha,
	// which does not require a solution.
	//   "UNSOLVABLE_CHALLENGE" - Challenge requests for this key always return an
	// unsolvable challenge.
	TestingChallenge string `json:"testingChallenge,omitempty"`
	// TestingScore: Optional. All assessments for this Key return this score. Must
	// be between 0 (likely not legitimate) and 1 (likely legitimate) inclusive.
	TestingScore float64 `json:"testingScore,omitempty"`
	// ForceSendFields is a list of field names (e.g. "TestingChallenge") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "TestingChallenge") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TestingOptions) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TestingOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1TestingOptions) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TestingOptions
	var s1 struct {
		TestingScore gensupport.JSONFloat64 `json:"testingScore"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.TestingScore = float64(s1.TestingScore)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1TokenProperties: Properties of the provided
// event token.
type GoogleCloudRecaptchaenterpriseV1TokenProperties struct {
	// Action: Output only. Action name provided at token generation.
	Action string `json:"action,omitempty"`
	// AndroidPackageName: Output only. The name of the Android package with which
	// the token was generated (Android keys only).
	AndroidPackageName string `json:"androidPackageName,omitempty"`
	// ClientSignalsFailed: Output only. Indicates a failure collecting reCAPTCHA
	// signals at token generation. This might be a transient condition, or
	// persistent for a user’s environment.
	ClientSignalsFailed bool `json:"clientSignalsFailed,omitempty"`
	// CreateTime: Output only. The timestamp corresponding to the generation of
	// the token.
	CreateTime string `json:"createTime,omitempty"`
	// Hostname: Output only. The hostname of the page on which the token was
	// generated (Web keys only).
	Hostname string `json:"hostname,omitempty"`
	// InvalidReason: Output only. Reason associated with the response when valid =
	// false.
	//
	// Possible values:
	//   "INVALID_REASON_UNSPECIFIED" - Default unspecified type.
	//   "UNKNOWN_INVALID_REASON" - If the failure reason was not accounted for.
	//   "MALFORMED" - The provided user verification token was malformed.
	//   "EXPIRED" - The user verification token had expired.
	//   "DUPE" - The user verification had already been seen.
	//   "MISSING" - The user verification token was not present.
	//   "BROWSER_ERROR" - A retriable error (such as network failure) occurred on
	// the browser. Could easily be simulated by an attacker.
	//   "UNEXPECTED_ACTION" - The action provided at token generation was
	// different than the `expected_action` in the assessment request. The
	// comparison is case-insensitive. This reason can only be returned if all of
	// the following are true: - your `site_key` has the POLICY_BASED_CHALLENGE
	// integration type - you set an action score threshold higher than 0.0 - you
	// provided a non-empty `expected_action`
	//   "KEY_MISMATCH" - The key used to generate the token does not match the
	// `site_key`.
	//   "DOMAIN_MISMATCH" - The domain of the page on which the token was
	// generated does not match the `allowed_domains` configured in the `site_key`.
	InvalidReason string `json:"invalidReason,omitempty"`
	// IosBundleId: Output only. The ID of the iOS bundle with which the token was
	// generated (iOS keys only).
	IosBundleId string `json:"iosBundleId,omitempty"`
	// Valid: Output only. Indicates whether the provided user response token is
	// valid. If `false`, the token is invalid, either because the user failed the
	// challenge or for a reason provided in the `invalid_reason` field.
	Valid bool `json:"valid,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Action") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Action") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TokenProperties) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TokenProperties
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1TransactionData: Transaction data associated
// with a payment protected by reCAPTCHA Enterprise.
type GoogleCloudRecaptchaenterpriseV1TransactionData struct {
	// BillingAddress: Optional. Address associated with the payment method when
	// applicable.
	BillingAddress *GoogleCloudRecaptchaenterpriseV1TransactionDataAddress `json:"billingAddress,omitempty"`
	// CardBin: Optional. The Bank Identification Number - generally the first 6 or
	// 8 digits of the card.
	CardBin string `json:"cardBin,omitempty"`
	// CardLastFour: Optional. The last four digits of the card.
	CardLastFour string `json:"cardLastFour,omitempty"`
	// CurrencyCode: Optional. The currency code in ISO-4217 format.
	CurrencyCode string `json:"currencyCode,omitempty"`
	// GatewayInfo: Optional. Information about the payment gateway's response to
	// the transaction.
	GatewayInfo *GoogleCloudRecaptchaenterpriseV1TransactionDataGatewayInfo `json:"gatewayInfo,omitempty"`
	// Items: Optional. Items purchased in this transaction.
	Items []*GoogleCloudRecaptchaenterpriseV1TransactionDataItem `json:"items,omitempty"`
	// Merchants: Optional. Information about the user or users fulfilling the
	// transaction.
	Merchants []*GoogleCloudRecaptchaenterpriseV1TransactionDataUser `json:"merchants,omitempty"`
	// PaymentMethod: Optional. The payment method for the transaction. The allowed
	// values are: * credit-card * debit-card * gift-card * processor-{name} (If a
	// third-party is used, for example, processor-paypal) * custom-{name} (If an
	// alternative method is used, for example, custom-crypto)
	PaymentMethod string `json:"paymentMethod,omitempty"`
	// ShippingAddress: Optional. Destination address if this transaction involves
	// shipping a physical item.
	ShippingAddress *GoogleCloudRecaptchaenterpriseV1TransactionDataAddress `json:"shippingAddress,omitempty"`
	// ShippingValue: Optional. The value of shipping in the specified currency. 0
	// for free or no shipping.
	ShippingValue float64 `json:"shippingValue,omitempty"`
	// TransactionId: Unique identifier for the transaction. This custom identifier
	// can be used to reference this transaction in the future, for example,
	// labeling a refund or chargeback event. Two attempts at the same transaction
	// should use the same transaction id.
	TransactionId string `json:"transactionId,omitempty"`
	// User: Optional. Information about the user paying/initiating the
	// transaction.
	User *GoogleCloudRecaptchaenterpriseV1TransactionDataUser `json:"user,omitempty"`
	// Value: Optional. The decimal value of the transaction in the specified
	// currency.
	Value float64 `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BillingAddress") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BillingAddress") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionData) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionData
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1TransactionData) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionData
	var s1 struct {
		ShippingValue gensupport.JSONFloat64 `json:"shippingValue"`
		Value         gensupport.JSONFloat64 `json:"value"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.ShippingValue = float64(s1.ShippingValue)
	s.Value = float64(s1.Value)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1TransactionDataAddress: Structured address
// format for billing and shipping addresses.
type GoogleCloudRecaptchaenterpriseV1TransactionDataAddress struct {
	// Address: Optional. The first lines of the address. The first line generally
	// contains the street name and number, and further lines may include
	// information such as an apartment number.
	Address []string `json:"address,omitempty"`
	// AdministrativeArea: Optional. The state, province, or otherwise
	// administrative area of the address.
	AdministrativeArea string `json:"administrativeArea,omitempty"`
	// Locality: Optional. The town/city of the address.
	Locality string `json:"locality,omitempty"`
	// PostalCode: Optional. The postal or ZIP code of the address.
	PostalCode string `json:"postalCode,omitempty"`
	// Recipient: Optional. The recipient name, potentially including information
	// such as "care of".
	Recipient string `json:"recipient,omitempty"`
	// RegionCode: Optional. The CLDR country/region of the address.
	RegionCode string `json:"regionCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Address") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Address") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionDataAddress) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionDataAddress
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1TransactionDataGatewayInfo: Details about
// the transaction from the gateway.
type GoogleCloudRecaptchaenterpriseV1TransactionDataGatewayInfo struct {
	// AvsResponseCode: Optional. AVS response code from the gateway (available
	// only when reCAPTCHA Enterprise is called after authorization).
	AvsResponseCode string `json:"avsResponseCode,omitempty"`
	// CvvResponseCode: Optional. CVV response code from the gateway (available
	// only when reCAPTCHA Enterprise is called after authorization).
	CvvResponseCode string `json:"cvvResponseCode,omitempty"`
	// GatewayResponseCode: Optional. Gateway response code describing the state of
	// the transaction.
	GatewayResponseCode string `json:"gatewayResponseCode,omitempty"`
	// Name: Optional. Name of the gateway service (for example, stripe, square,
	// paypal).
	Name string `json:"name,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AvsResponseCode") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AvsResponseCode") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionDataGatewayInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionDataGatewayInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1TransactionDataItem: Line items being
// purchased in this transaction.
type GoogleCloudRecaptchaenterpriseV1TransactionDataItem struct {
	// MerchantAccountId: Optional. When a merchant is specified, its corresponding
	// account_id. Necessary to populate marketplace-style transactions.
	MerchantAccountId string `json:"merchantAccountId,omitempty"`
	// Name: Optional. The full name of the item.
	Name string `json:"name,omitempty"`
	// Quantity: Optional. The quantity of this item that is being purchased.
	Quantity int64 `json:"quantity,omitempty,string"`
	// Value: Optional. The value per item that the user is paying, in the
	// transaction currency, after discounts.
	Value float64 `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "MerchantAccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MerchantAccountId") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionDataItem) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionDataItem
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1TransactionDataItem) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionDataItem
	var s1 struct {
		Value gensupport.JSONFloat64 `json:"value"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Value = float64(s1.Value)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1TransactionDataUser: Details about a user's
// account involved in the transaction.
type GoogleCloudRecaptchaenterpriseV1TransactionDataUser struct {
	// AccountId: Optional. Unique account identifier for this user. If using
	// Account defense, this should match the hashed_account_id field. Otherwise, a
	// unique and persistent identifier for this account.
	AccountId string `json:"accountId,omitempty"`
	// CreationMs: Optional. The epoch milliseconds of the user's account creation.
	CreationMs int64 `json:"creationMs,omitempty,string"`
	// Email: Optional. The email address of the user.
	Email string `json:"email,omitempty"`
	// EmailVerified: Optional. Whether the email has been verified to be
	// accessible by the user (OTP or similar).
	EmailVerified bool `json:"emailVerified,omitempty"`
	// PhoneNumber: Optional. The phone number of the user, with country code.
	PhoneNumber string `json:"phoneNumber,omitempty"`
	// PhoneVerified: Optional. Whether the phone number has been verified to be
	// accessible by the user (OTP or similar).
	PhoneVerified bool `json:"phoneVerified,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionDataUser) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionDataUser
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1TransactionEvent: Describes an event in the
// lifecycle of a payment transaction.
type GoogleCloudRecaptchaenterpriseV1TransactionEvent struct {
	// EventTime: Optional. Timestamp when this transaction event occurred;
	// otherwise assumed to be the time of the API call.
	EventTime string `json:"eventTime,omitempty"`
	// EventType: Optional. The type of this transaction event.
	//
	// Possible values:
	//   "TRANSACTION_EVENT_TYPE_UNSPECIFIED" - Default, unspecified event type.
	//   "MERCHANT_APPROVE" - Indicates that the transaction is approved by the
	// merchant. The accompanying reasons can include terms such as 'INHOUSE',
	// 'ACCERTIFY', 'CYBERSOURCE', or 'MANUAL_REVIEW'.
	//   "MERCHANT_DENY" - Indicates that the transaction is denied and concluded
	// due to risks detected by the merchant. The accompanying reasons can include
	// terms such as 'INHOUSE', 'ACCERTIFY', 'CYBERSOURCE', or 'MANUAL_REVIEW'.
	//   "MANUAL_REVIEW" - Indicates that the transaction is being evaluated by a
	// human, due to suspicion or risk.
	//   "AUTHORIZATION" - Indicates that the authorization attempt with the card
	// issuer succeeded.
	//   "AUTHORIZATION_DECLINE" - Indicates that the authorization attempt with
	// the card issuer failed. The accompanying reasons can include Visa's '54'
	// indicating that the card is expired, or '82' indicating that the CVV is
	// incorrect.
	//   "PAYMENT_CAPTURE" - Indicates that the transaction is completed because
	// the funds were settled.
	//   "PAYMENT_CAPTURE_DECLINE" - Indicates that the transaction could not be
	// completed because the funds were not settled.
	//   "CANCEL" - Indicates that the transaction has been canceled. Specify the
	// reason for the cancellation. For example, 'INSUFFICIENT_INVENTORY'.
	//   "CHARGEBACK_INQUIRY" - Indicates that the merchant has received a
	// chargeback inquiry due to fraud for the transaction, requesting additional
	// information before a fraud chargeback is officially issued and a formal
	// chargeback notification is sent.
	//   "CHARGEBACK_ALERT" - Indicates that the merchant has received a chargeback
	// alert due to fraud for the transaction. The process of resolving the dispute
	// without involving the payment network is started.
	//   "FRAUD_NOTIFICATION" - Indicates that a fraud notification is issued for
	// the transaction, sent by the payment instrument's issuing bank because the
	// transaction appears to be fraudulent. We recommend including TC40 or SAFE
	// data in the `reason` field for this event type. For partial chargebacks, we
	// recommend that you include an amount in the `value` field.
	//   "CHARGEBACK" - Indicates that the merchant is informed by the payment
	// network that the transaction has entered the chargeback process due to
	// fraud. Reason code examples include Discover's '6005' and '6041'. For
	// partial chargebacks, we recommend that you include an amount in the `value`
	// field.
	//   "CHARGEBACK_REPRESENTMENT" - Indicates that the transaction has entered
	// the chargeback process due to fraud, and that the merchant has chosen to
	// enter representment. Reason examples include Discover's '6005' and '6041'.
	// For partial chargebacks, we recommend that you include an amount in the
	// `value` field.
	//   "CHARGEBACK_REVERSE" - Indicates that the transaction has had a fraud
	// chargeback which was illegitimate and was reversed as a result. For partial
	// chargebacks, we recommend that you include an amount in the `value` field.
	//   "REFUND_REQUEST" - Indicates that the merchant has received a refund for a
	// completed transaction. For partial refunds, we recommend that you include an
	// amount in the `value` field. Reason example: 'TAX_EXEMPT' (partial refund of
	// exempt tax)
	//   "REFUND_DECLINE" - Indicates that the merchant has received a refund
	// request for this transaction, but that they have declined it. For partial
	// refunds, we recommend that you include an amount in the `value` field.
	// Reason example: 'TAX_EXEMPT' (partial refund of exempt tax)
	//   "REFUND" - Indicates that the completed transaction was refunded by the
	// merchant. For partial refunds, we recommend that you include an amount in
	// the `value` field. Reason example: 'TAX_EXEMPT' (partial refund of exempt
	// tax)
	//   "REFUND_REVERSE" - Indicates that the completed transaction was refunded
	// by the merchant, and that this refund was reversed. For partial refunds, we
	// recommend that you include an amount in the `value` field.
	EventType string `json:"eventType,omitempty"`
	// Reason: Optional. The reason or standardized code that corresponds with this
	// transaction event, if one exists. For example, a CHARGEBACK event with code
	// 6005.
	Reason string `json:"reason,omitempty"`
	// Value: Optional. The value that corresponds with this transaction event, if
	// one exists. For example, a refund event where $5.00 was refunded. Currency
	// is obtained from the original transaction data.
	Value float64 `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EventTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EventTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1TransactionEvent) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionEvent
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1TransactionEvent) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1TransactionEvent
	var s1 struct {
		Value gensupport.JSONFloat64 `json:"value"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Value = float64(s1.Value)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1UniversalKeySettings: Settings for keys that
// are configured through their Policy.
type GoogleCloudRecaptchaenterpriseV1UniversalKeySettings struct {
}

// GoogleCloudRecaptchaenterpriseV1UserId: An identifier associated with a
// user.
type GoogleCloudRecaptchaenterpriseV1UserId struct {
	// Email: Optional. An email address.
	Email string `json:"email,omitempty"`
	// PhoneNumber: Optional. A phone number. Should use the E.164 format.
	PhoneNumber string `json:"phoneNumber,omitempty"`
	// Username: Optional. A unique username, if different from all the other
	// identifiers and `account_id` that are provided. Can be a unique login handle
	// or display name for a user.
	Username string `json:"username,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Email") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Email") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1UserId) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1UserId
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1UserInfo: User information associated with a
// request protected by reCAPTCHA Enterprise.
type GoogleCloudRecaptchaenterpriseV1UserInfo struct {
	// AccountId: Optional. For logged-in requests or login/registration requests,
	// the unique account identifier associated with this user. You can use the
	// username if it is stable (meaning it is the same for every request
	// associated with the same user), or any stable user ID of your choice. Leave
	// blank for non logged-in actions or guest checkout.
	AccountId string `json:"accountId,omitempty"`
	// CreateAccountTime: Optional. Creation time for this account associated with
	// this user. Leave blank for non logged-in actions, guest checkout, or when
	// there is no account associated with the current user.
	CreateAccountTime string `json:"createAccountTime,omitempty"`
	// UserIds: Optional. Identifiers associated with this user or request.
	UserIds []*GoogleCloudRecaptchaenterpriseV1UserId `json:"userIds,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AccountId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1UserInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1UserInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1WafSettings: Settings specific to keys that
// can be used for WAF (Web Application Firewall).
type GoogleCloudRecaptchaenterpriseV1WafSettings struct {
	// WafFeature: Required. The Web Application Firewall (WAF) feature for which
	// this key is enabled.
	//
	// Possible values:
	//   "WAF_FEATURE_UNSPECIFIED" - Undefined feature.
	//   "CHALLENGE_PAGE" - Redirects suspicious traffic to reCAPTCHA.
	//   "SESSION_TOKEN" - Use reCAPTCHA session-tokens to protect the whole user
	// session on the site's domain.
	//   "ACTION_TOKEN" - Use reCAPTCHA action-tokens to protect user actions.
	//   "EXPRESS" - Deprecated: Use `express_settings` instead.
	WafFeature string `json:"wafFeature,omitempty"`
	// WafService: Required. The Web Application Firewall (WAF) service that uses
	// this key.
	//
	// Possible values:
	//   "WAF_SERVICE_UNSPECIFIED" - Undefined WAF
	//   "CA" - Cloud Armor
	//   "FASTLY" - Fastly
	//   "CLOUDFLARE" - Cloudflare
	//   "AKAMAI" - Akamai
	WafService string `json:"wafService,omitempty"`
	// ForceSendFields is a list of field names (e.g. "WafFeature") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "WafFeature") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1WafSettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1WafSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1WebKeySettings: Settings specific to keys
// that can be used by websites.
type GoogleCloudRecaptchaenterpriseV1WebKeySettings struct {
	// AllowAllDomains: Optional. If set to true, it means allowed_domains are not
	// enforced.
	AllowAllDomains bool `json:"allowAllDomains,omitempty"`
	// AllowAmpTraffic: Optional. If set to true, the key can be used on AMP
	// (Accelerated Mobile Pages) websites. This is supported only for the SCORE
	// integration type.
	AllowAmpTraffic bool `json:"allowAmpTraffic,omitempty"`
	// AllowedDomains: Optional. Domains or subdomains of websites allowed to use
	// the key. All subdomains of an allowed domain are automatically allowed. A
	// valid domain requires a host and must not include any path, port, query or
	// fragment. Examples: 'example.com' or 'subdomain.example.com' Each key
	// supports a maximum of 250 domains. To use a key on more domains, set
	// `allow_all_domains` to true. When this is set, you are responsible for
	// validating the hostname by checking the `token_properties.hostname` field in
	// each assessment response against your list of allowed domains.
	AllowedDomains []string `json:"allowedDomains,omitempty"`
	// ChallengeSecurityPreference: Optional. Settings for the frequency and
	// difficulty at which this key triggers captcha challenges. This should only
	// be specified for `IntegrationType` CHECKBOX (defaults to BALANCE), INVISIBLE
	// (defaults to USABILITY), or POLICY_BASED_CHALLENGE (defaults to USABILITY).
	//
	// Possible values:
	//   "CHALLENGE_SECURITY_PREFERENCE_UNSPECIFIED" - Default type that indicates
	// this enum hasn't been specified.
	//   "USABILITY" - Key tends to show fewer and easier challenges.
	//   "BALANCE" - Key tends to show balanced (in amount and difficulty)
	// challenges.
	//   "SECURITY" - Key tends to show more and harder challenges.
	ChallengeSecurityPreference string `json:"challengeSecurityPreference,omitempty"`
	// ChallengeSettings: Optional. Challenge settings.
	ChallengeSettings *GoogleCloudRecaptchaenterpriseV1WebKeySettingsChallengeSettings `json:"challengeSettings,omitempty"`
	// IntegrationType: Required. Describes how this key is integrated with the
	// website.
	//
	// Possible values:
	//   "INTEGRATION_TYPE_UNSPECIFIED" - Default type that indicates this enum
	// hasn't been specified. This is not a valid IntegrationType, one of the other
	// types must be specified instead.
	//   "SCORE" - Only used to produce scores. It doesn't display the "I'm not a
	// robot" checkbox and never shows captcha challenges.
	//   "CHECKBOX" - Displays the "I'm not a robot" checkbox and may show captcha
	// challenges after it is checked.
	//   "INVISIBLE" - Doesn't display the "I'm not a robot" checkbox, but may show
	// captcha challenges after risk analysis.
	//   "POLICY_BASED_CHALLENGE" - Displays a visual challenge or not depending on
	// the user risk analysis score.
	IntegrationType string `json:"integrationType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowAllDomains") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AllowAllDomains") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1WebKeySettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1WebKeySettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings: Per-action
// challenge settings.
type GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings struct {
	// ScoreThreshold: Required. A challenge is triggered if the end-user score is
	// below that threshold. Value must be between 0 and 1 (inclusive).
	ScoreThreshold float64 `json:"scoreThreshold,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ScoreThreshold") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ScoreThreshold") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings
	var s1 struct {
		ScoreThreshold gensupport.JSONFloat64 `json:"scoreThreshold"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.ScoreThreshold = float64(s1.ScoreThreshold)
	return nil
}

// GoogleCloudRecaptchaenterpriseV1WebKeySettingsChallengeSettings: Settings
// for POLICY_BASED_CHALLENGE keys to control when a challenge is triggered.
type GoogleCloudRecaptchaenterpriseV1WebKeySettingsChallengeSettings struct {
	// ActionSettings: Optional. The action to score threshold map. The action name
	// should be the same as the action name passed in the `data-action` attribute
	// (see https://cloud.google.com/recaptcha/docs/actions-website). Action names
	// are case-insensitive. There is a maximum of 100 action settings. An action
	// name has a maximum length of 100.
	ActionSettings map[string]GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings `json:"actionSettings,omitempty"`
	// DefaultSettings: Required. Defines when a challenge is triggered (unless the
	// default threshold is overridden for the given action, see
	// `action_settings`).
	DefaultSettings *GoogleCloudRecaptchaenterpriseV1WebKeySettingsActionSettings `json:"defaultSettings,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ActionSettings") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ActionSettings") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleCloudRecaptchaenterpriseV1WebKeySettingsChallengeSettings) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecaptchaenterpriseV1WebKeySettingsChallengeSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GoogleProtobufEmpty: A generic empty message that you can re-use to avoid
// defining duplicated empty messages in your APIs. A typical example is to use
// it as the request or the response type of an API method. For instance:
// service Foo { rpc Bar(google.protobuf.Empty) returns
// (google.protobuf.Empty); }
type GoogleProtobufEmpty struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleRpcStatus: The `Status` type defines a logical error model that is
// suitable for different programming environments, including REST APIs and RPC
// APIs. It is used by gRPC (https://github.com/grpc). Each `Status` message
// contains three pieces of data: error code, error message, and error details.
// You can find out more about this error model and how to work with it in the
// API Design Guide (https://cloud.google.com/apis/design/errors).
type GoogleRpcStatus struct {
	// Code: The status code, which should be an enum value of google.rpc.Code.
	Code int64 `json:"code,omitempty"`
	// Details: A list of messages that carry the error details. There is a common
	// set of message types for APIs to use.
	Details []googleapi.RawMessage `json:"details,omitempty"`
	// Message: A developer-facing error message, which should be in English. Any
	// user-facing error message should be localized and sent in the
	// google.rpc.Status.details field, or localized by the client.
	Message string `json:"message,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Code") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Code") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GoogleRpcStatus) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleRpcStatus
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type ProjectsAssessmentsAnnotateCall struct {
	s                                                         *Service
	name                                                      string
	googlecloudrecaptchaenterprisev1annotateassessmentrequest *GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest
	urlParams_                                                gensupport.URLParams
	ctx_                                                      context.Context
	header_                                                   http.Header
}

// Annotate: Annotates a previously created Assessment to provide additional
// information on whether the event turned out to be authentic or fraudulent.
//
//   - name: The resource name of the Assessment, in the format
//     `projects/{project}/assessments/{assessment}`.
func (r *ProjectsAssessmentsService) Annotate(name string, googlecloudrecaptchaenterprisev1annotateassessmentrequest *GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentRequest) *ProjectsAssessmentsAnnotateCall {
	c := &ProjectsAssessmentsAnnotateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1annotateassessmentrequest = googlecloudrecaptchaenterprisev1annotateassessmentrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsAssessmentsAnnotateCall) Fields(s ...googleapi.Field) *ProjectsAssessmentsAnnotateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsAssessmentsAnnotateCall) Context(ctx context.Context) *ProjectsAssessmentsAnnotateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsAssessmentsAnnotateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsAssessmentsAnnotateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1annotateassessmentrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:annotate")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.assessments.annotate", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.assessments.annotate" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentResponse.ServerResponse.He
// ader or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsAssessmentsAnnotateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1AnnotateAssessmentResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.assessments.annotate", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsAssessmentsCreateCall struct {
	s                                          *Service
	parent                                     string
	googlecloudrecaptchaenterprisev1assessment *GoogleCloudRecaptchaenterpriseV1Assessment
	urlParams_                                 gensupport.URLParams
	ctx_                                       context.Context
	header_                                    http.Header
}

// Create: Creates an Assessment of the likelihood an event is legitimate.
//
//   - parent: The name of the project in which the assessment is created, in the
//     format `projects/{project}`.
func (r *ProjectsAssessmentsService) Create(parent string, googlecloudrecaptchaenterprisev1assessment *GoogleCloudRecaptchaenterpriseV1Assessment) *ProjectsAssessmentsCreateCall {
	c := &ProjectsAssessmentsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecaptchaenterprisev1assessment = googlecloudrecaptchaenterprisev1assessment
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsAssessmentsCreateCall) Fields(s ...googleapi.Field) *ProjectsAssessmentsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsAssessmentsCreateCall) Context(ctx context.Context) *ProjectsAssessmentsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsAssessmentsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsAssessmentsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1assessment)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/assessments")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.assessments.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.assessments.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Assessment.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsAssessmentsCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Assessment, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Assessment{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.assessments.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsFirewallpoliciesCreateCall struct {
	s                                              *Service
	parent                                         string
	googlecloudrecaptchaenterprisev1firewallpolicy *GoogleCloudRecaptchaenterpriseV1FirewallPolicy
	urlParams_                                     gensupport.URLParams
	ctx_                                           context.Context
	header_                                        http.Header
}

// Create: Creates a new FirewallPolicy, specifying conditions at which
// reCAPTCHA Enterprise actions can be executed. A project may have a maximum
// of 1000 policies.
//
//   - parent: The name of the project this policy applies to, in the format
//     `projects/{project}`.
func (r *ProjectsFirewallpoliciesService) Create(parent string, googlecloudrecaptchaenterprisev1firewallpolicy *GoogleCloudRecaptchaenterpriseV1FirewallPolicy) *ProjectsFirewallpoliciesCreateCall {
	c := &ProjectsFirewallpoliciesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecaptchaenterprisev1firewallpolicy = googlecloudrecaptchaenterprisev1firewallpolicy
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesCreateCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesCreateCall) Context(ctx context.Context) *ProjectsFirewallpoliciesCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1firewallpolicy)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/firewallpolicies")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1FirewallPolicy.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsFirewallpoliciesCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1FirewallPolicy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1FirewallPolicy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsFirewallpoliciesDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes the specified firewall policy.
//
//   - name: The name of the policy to be deleted, in the format
//     `projects/{project}/firewallpolicies/{firewallpolicy}`.
func (r *ProjectsFirewallpoliciesService) Delete(name string) *ProjectsFirewallpoliciesDeleteCall {
	c := &ProjectsFirewallpoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesDeleteCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesDeleteCall) Context(ctx context.Context) *ProjectsFirewallpoliciesDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleProtobufEmpty.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsFirewallpoliciesDeleteCall) Do(opts ...googleapi.CallOption) (*GoogleProtobufEmpty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleProtobufEmpty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsFirewallpoliciesGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Returns the specified firewall policy.
//
//   - name: The name of the requested policy, in the format
//     `projects/{project}/firewallpolicies/{firewallpolicy}`.
func (r *ProjectsFirewallpoliciesService) Get(name string) *ProjectsFirewallpoliciesGetCall {
	c := &ProjectsFirewallpoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesGetCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsFirewallpoliciesGetCall) IfNoneMatch(entityTag string) *ProjectsFirewallpoliciesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesGetCall) Context(ctx context.Context) *ProjectsFirewallpoliciesGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1FirewallPolicy.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsFirewallpoliciesGetCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1FirewallPolicy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1FirewallPolicy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsFirewallpoliciesListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Returns the list of all firewall policies that belong to a project.
//
//   - parent: The name of the project to list the policies for, in the format
//     `projects/{project}`.
func (r *ProjectsFirewallpoliciesService) List(parent string) *ProjectsFirewallpoliciesListCall {
	c := &ProjectsFirewallpoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// policies to return. Default is 10. Max limit is 1000.
func (c *ProjectsFirewallpoliciesListCall) PageSize(pageSize int64) *ProjectsFirewallpoliciesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The next_page_token value
// returned from a previous. ListFirewallPoliciesRequest, if any.
func (c *ProjectsFirewallpoliciesListCall) PageToken(pageToken string) *ProjectsFirewallpoliciesListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesListCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsFirewallpoliciesListCall) IfNoneMatch(entityTag string) *ProjectsFirewallpoliciesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesListCall) Context(ctx context.Context) *ProjectsFirewallpoliciesListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/firewallpolicies")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse.ServerResponse.
// Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsFirewallpoliciesListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsFirewallpoliciesListCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1ListFirewallPoliciesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsFirewallpoliciesPatchCall struct {
	s                                              *Service
	name                                           string
	googlecloudrecaptchaenterprisev1firewallpolicy *GoogleCloudRecaptchaenterpriseV1FirewallPolicy
	urlParams_                                     gensupport.URLParams
	ctx_                                           context.Context
	header_                                        http.Header
}

// Patch: Updates the specified firewall policy.
//
//   - name: Identifier. The resource name for the FirewallPolicy in the format
//     `projects/{project}/firewallpolicies/{firewallpolicy}`.
func (r *ProjectsFirewallpoliciesService) Patch(name string, googlecloudrecaptchaenterprisev1firewallpolicy *GoogleCloudRecaptchaenterpriseV1FirewallPolicy) *ProjectsFirewallpoliciesPatchCall {
	c := &ProjectsFirewallpoliciesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1firewallpolicy = googlecloudrecaptchaenterprisev1firewallpolicy
	return c
}

// UpdateMask sets the optional parameter "updateMask": The mask to control
// which fields of the policy get updated. If the mask is not present, all
// fields are updated.
func (c *ProjectsFirewallpoliciesPatchCall) UpdateMask(updateMask string) *ProjectsFirewallpoliciesPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesPatchCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesPatchCall) Context(ctx context.Context) *ProjectsFirewallpoliciesPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1firewallpolicy)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1FirewallPolicy.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsFirewallpoliciesPatchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1FirewallPolicy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1FirewallPolicy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsFirewallpoliciesReorderCall struct {
	s                                                              *Service
	parent                                                         string
	googlecloudrecaptchaenterprisev1reorderfirewallpoliciesrequest *GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest
	urlParams_                                                     gensupport.URLParams
	ctx_                                                           context.Context
	header_                                                        http.Header
}

// Reorder: Reorders all firewall policies.
//
//   - parent: The name of the project to list the policies for, in the format
//     `projects/{project}`.
func (r *ProjectsFirewallpoliciesService) Reorder(parent string, googlecloudrecaptchaenterprisev1reorderfirewallpoliciesrequest *GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesRequest) *ProjectsFirewallpoliciesReorderCall {
	c := &ProjectsFirewallpoliciesReorderCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecaptchaenterprisev1reorderfirewallpoliciesrequest = googlecloudrecaptchaenterprisev1reorderfirewallpoliciesrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsFirewallpoliciesReorderCall) Fields(s ...googleapi.Field) *ProjectsFirewallpoliciesReorderCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsFirewallpoliciesReorderCall) Context(ctx context.Context) *ProjectsFirewallpoliciesReorderCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsFirewallpoliciesReorderCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsFirewallpoliciesReorderCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1reorderfirewallpoliciesrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/firewallpolicies:reorder")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.reorder", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.firewallpolicies.reorder" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesResponse.ServerRespon
// se.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsFirewallpoliciesReorderCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ReorderFirewallPoliciesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.firewallpolicies.reorder", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysAddIpOverrideCall struct {
	s                                                    *Service
	name                                                 string
	googlecloudrecaptchaenterprisev1addipoverriderequest *GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest
	urlParams_                                           gensupport.URLParams
	ctx_                                                 context.Context
	header_                                              http.Header
}

// AddIpOverride: Adds an IP override to a key. The following restrictions
// hold: * The maximum number of IP overrides per key is 1000. * For any
// conflict (such as IP already exists or IP part of an existing IP range), an
// error is returned.
//
//   - name: The name of the key to which the IP override is added, in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) AddIpOverride(name string, googlecloudrecaptchaenterprisev1addipoverriderequest *GoogleCloudRecaptchaenterpriseV1AddIpOverrideRequest) *ProjectsKeysAddIpOverrideCall {
	c := &ProjectsKeysAddIpOverrideCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1addipoverriderequest = googlecloudrecaptchaenterprisev1addipoverriderequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysAddIpOverrideCall) Fields(s ...googleapi.Field) *ProjectsKeysAddIpOverrideCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysAddIpOverrideCall) Context(ctx context.Context) *ProjectsKeysAddIpOverrideCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysAddIpOverrideCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysAddIpOverrideCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1addipoverriderequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:addIpOverride")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.addIpOverride", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.addIpOverride" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1AddIpOverrideResponse.ServerResponse.Header
// or (if a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysAddIpOverrideCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1AddIpOverrideResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1AddIpOverrideResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.addIpOverride", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysCreateCall struct {
	s                                   *Service
	parent                              string
	googlecloudrecaptchaenterprisev1key *GoogleCloudRecaptchaenterpriseV1Key
	urlParams_                          gensupport.URLParams
	ctx_                                context.Context
	header_                             http.Header
}

// Create: Creates a new reCAPTCHA Enterprise key.
//
//   - parent: The name of the project in which the key is created, in the format
//     `projects/{project}`.
func (r *ProjectsKeysService) Create(parent string, googlecloudrecaptchaenterprisev1key *GoogleCloudRecaptchaenterpriseV1Key) *ProjectsKeysCreateCall {
	c := &ProjectsKeysCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecaptchaenterprisev1key = googlecloudrecaptchaenterprisev1key
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysCreateCall) Fields(s ...googleapi.Field) *ProjectsKeysCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysCreateCall) Context(ctx context.Context) *ProjectsKeysCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1key)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/keys")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Key.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Key, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Key{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes the specified key.
//
//   - name: The name of the key to be deleted, in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) Delete(name string) *ProjectsKeysDeleteCall {
	c := &ProjectsKeysDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysDeleteCall) Fields(s ...googleapi.Field) *ProjectsKeysDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysDeleteCall) Context(ctx context.Context) *ProjectsKeysDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleProtobufEmpty.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsKeysDeleteCall) Do(opts ...googleapi.CallOption) (*GoogleProtobufEmpty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleProtobufEmpty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Returns the specified key.
//
//   - name: The name of the requested key, in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) Get(name string) *ProjectsKeysGetCall {
	c := &ProjectsKeysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysGetCall) Fields(s ...googleapi.Field) *ProjectsKeysGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysGetCall) IfNoneMatch(entityTag string) *ProjectsKeysGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysGetCall) Context(ctx context.Context) *ProjectsKeysGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Key.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysGetCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Key, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Key{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysGetMetricsCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetMetrics: Get some aggregated metrics for a Key. This data can be used to
// build dashboards.
//
//   - name: The name of the requested metrics, in the format
//     `projects/{project}/keys/{key}/metrics`.
func (r *ProjectsKeysService) GetMetrics(name string) *ProjectsKeysGetMetricsCall {
	c := &ProjectsKeysGetMetricsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysGetMetricsCall) Fields(s ...googleapi.Field) *ProjectsKeysGetMetricsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysGetMetricsCall) IfNoneMatch(entityTag string) *ProjectsKeysGetMetricsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysGetMetricsCall) Context(ctx context.Context) *ProjectsKeysGetMetricsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysGetMetricsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysGetMetricsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.getMetrics", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.getMetrics" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Metrics.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysGetMetricsCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Metrics, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Metrics{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.getMetrics", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysGetPolicyCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetPolicy: Get the policy for a key.
//
//   - name: The name of the policy to get, in the format
//     `projects/{project}/keys/{key}/policy`.
func (r *ProjectsKeysService) GetPolicy(name string) *ProjectsKeysGetPolicyCall {
	c := &ProjectsKeysGetPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysGetPolicyCall) Fields(s ...googleapi.Field) *ProjectsKeysGetPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysGetPolicyCall) IfNoneMatch(entityTag string) *ProjectsKeysGetPolicyCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysGetPolicyCall) Context(ctx context.Context) *ProjectsKeysGetPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysGetPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysGetPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.getPolicy", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.getPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Policy.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysGetPolicyCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.getPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Returns the list of all keys that belong to a project.
//
//   - parent: The name of the project that contains the keys that is listed, in
//     the format `projects/{project}`.
func (r *ProjectsKeysService) List(parent string) *ProjectsKeysListCall {
	c := &ProjectsKeysListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of keys
// to return. Default is 10. Max limit is 1000.
func (c *ProjectsKeysListCall) PageSize(pageSize int64) *ProjectsKeysListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The next_page_token value
// returned from a previous. ListKeysRequest, if any.
func (c *ProjectsKeysListCall) PageToken(pageToken string) *ProjectsKeysListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysListCall) Fields(s ...googleapi.Field) *ProjectsKeysListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysListCall) IfNoneMatch(entityTag string) *ProjectsKeysListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysListCall) Context(ctx context.Context) *ProjectsKeysListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/keys")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ListKeysResponse.ServerResponse.Header or
// (if a response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ListKeysResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ListKeysResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsKeysListCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1ListKeysResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsKeysListIpOverridesCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// ListIpOverrides: Lists all IP overrides for a key.
//
//   - parent: The parent key for which the IP overrides are listed, in the
//     format `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) ListIpOverrides(parent string) *ProjectsKeysListIpOverridesCall {
	c := &ProjectsKeysListIpOverridesCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// overrides to return. Default is 10. Max limit is 100. If the number of
// overrides is less than the page_size, all overrides are returned. If the
// page size is more than 100, it is coerced to 100.
func (c *ProjectsKeysListIpOverridesCall) PageSize(pageSize int64) *ProjectsKeysListIpOverridesCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The next_page_token value
// returned from a previous ListIpOverridesRequest, if any.
func (c *ProjectsKeysListIpOverridesCall) PageToken(pageToken string) *ProjectsKeysListIpOverridesCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysListIpOverridesCall) Fields(s ...googleapi.Field) *ProjectsKeysListIpOverridesCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysListIpOverridesCall) IfNoneMatch(entityTag string) *ProjectsKeysListIpOverridesCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysListIpOverridesCall) Context(ctx context.Context) *ProjectsKeysListIpOverridesCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysListIpOverridesCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysListIpOverridesCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}:listIpOverrides")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.listIpOverrides", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.listIpOverrides" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse.ServerResponse.Heade
// r or (if a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysListIpOverridesCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.listIpOverrides", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsKeysListIpOverridesCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1ListIpOverridesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsKeysMigrateCall struct {
	s                                                 *Service
	name                                              string
	googlecloudrecaptchaenterprisev1migratekeyrequest *GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest
	urlParams_                                        gensupport.URLParams
	ctx_                                              context.Context
	header_                                           http.Header
}

// Migrate: Migrates an existing key from reCAPTCHA to reCAPTCHA Enterprise.
// Once a key is migrated, it can be used from either product. SiteVerify
// requests are billed as CreateAssessment calls. You must be authenticated as
// one of the current owners of the reCAPTCHA Key, and your user must have the
// reCAPTCHA Enterprise Admin IAM role in the destination project.
//
//   - name: The name of the key to be migrated, in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) Migrate(name string, googlecloudrecaptchaenterprisev1migratekeyrequest *GoogleCloudRecaptchaenterpriseV1MigrateKeyRequest) *ProjectsKeysMigrateCall {
	c := &ProjectsKeysMigrateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1migratekeyrequest = googlecloudrecaptchaenterprisev1migratekeyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysMigrateCall) Fields(s ...googleapi.Field) *ProjectsKeysMigrateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysMigrateCall) Context(ctx context.Context) *ProjectsKeysMigrateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysMigrateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysMigrateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1migratekeyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:migrate")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.migrate", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.migrate" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Key.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysMigrateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Key, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Key{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.migrate", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysPatchCall struct {
	s                                   *Service
	name                                string
	googlecloudrecaptchaenterprisev1key *GoogleCloudRecaptchaenterpriseV1Key
	urlParams_                          gensupport.URLParams
	ctx_                                context.Context
	header_                             http.Header
}

// Patch: Updates the specified key.
//
//   - name: Identifier. The resource name for the Key in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) Patch(name string, googlecloudrecaptchaenterprisev1key *GoogleCloudRecaptchaenterpriseV1Key) *ProjectsKeysPatchCall {
	c := &ProjectsKeysPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1key = googlecloudrecaptchaenterprisev1key
	return c
}

// UpdateMask sets the optional parameter "updateMask": The mask to control
// which fields of the key get updated. If the mask is not present, all fields
// are updated.
func (c *ProjectsKeysPatchCall) UpdateMask(updateMask string) *ProjectsKeysPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysPatchCall) Fields(s ...googleapi.Field) *ProjectsKeysPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysPatchCall) Context(ctx context.Context) *ProjectsKeysPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1key)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Key.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysPatchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Key, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Key{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysRemoveIpOverrideCall struct {
	s                                                       *Service
	name                                                    string
	googlecloudrecaptchaenterprisev1removeipoverriderequest *GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest
	urlParams_                                              gensupport.URLParams
	ctx_                                                    context.Context
	header_                                                 http.Header
}

// RemoveIpOverride: Removes an IP override from a key. The following
// restrictions hold: * If the IP isn't found in an existing IP override, a
// `NOT_FOUND` error is returned. * If the IP is found in an existing IP
// override, but the override type does not match, a `NOT_FOUND` error is
// returned.
//
//   - name: The name of the key from which the IP override is removed, in the
//     format `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) RemoveIpOverride(name string, googlecloudrecaptchaenterprisev1removeipoverriderequest *GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideRequest) *ProjectsKeysRemoveIpOverrideCall {
	c := &ProjectsKeysRemoveIpOverrideCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1removeipoverriderequest = googlecloudrecaptchaenterprisev1removeipoverriderequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysRemoveIpOverrideCall) Fields(s ...googleapi.Field) *ProjectsKeysRemoveIpOverrideCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysRemoveIpOverrideCall) Context(ctx context.Context) *ProjectsKeysRemoveIpOverrideCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysRemoveIpOverrideCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysRemoveIpOverrideCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1removeipoverriderequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:removeIpOverride")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.removeIpOverride", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.removeIpOverride" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideResponse.ServerResponse.Head
// er or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsKeysRemoveIpOverrideCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1RemoveIpOverrideResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.removeIpOverride", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysRetrieveLegacySecretKeyCall struct {
	s            *Service
	key          string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// RetrieveLegacySecretKey: Returns the secret key related to the specified
// public key. You must use the legacy secret key only in a 3rd party
// integration with legacy reCAPTCHA.
//
//   - key: The public key name linked to the requested secret key in the format
//     `projects/{project}/keys/{key}`.
func (r *ProjectsKeysService) RetrieveLegacySecretKey(key string) *ProjectsKeysRetrieveLegacySecretKeyCall {
	c := &ProjectsKeysRetrieveLegacySecretKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.key = key
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysRetrieveLegacySecretKeyCall) Fields(s ...googleapi.Field) *ProjectsKeysRetrieveLegacySecretKeyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsKeysRetrieveLegacySecretKeyCall) IfNoneMatch(entityTag string) *ProjectsKeysRetrieveLegacySecretKeyCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysRetrieveLegacySecretKeyCall) Context(ctx context.Context) *ProjectsKeysRetrieveLegacySecretKeyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysRetrieveLegacySecretKeyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysRetrieveLegacySecretKeyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+key}:retrieveLegacySecretKey")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"key": c.key,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.retrieveLegacySecretKey", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.retrieveLegacySecretKey" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse.ServerRespon
// se.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsKeysRetrieveLegacySecretKeyCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1RetrieveLegacySecretKeyResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.retrieveLegacySecretKey", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsKeysUpdatePolicyCall struct {
	s                                      *Service
	name                                   string
	googlecloudrecaptchaenterprisev1policy *GoogleCloudRecaptchaenterpriseV1Policy
	urlParams_                             gensupport.URLParams
	ctx_                                   context.Context
	header_                                http.Header
}

// UpdatePolicy: Updates the policy for a key.
//
//   - name: Identifier. Resource name for this policy. Format:
//     "projects/{project}/keys/{key}/policy" for a policy under a key.
func (r *ProjectsKeysService) UpdatePolicy(name string, googlecloudrecaptchaenterprisev1policy *GoogleCloudRecaptchaenterpriseV1Policy) *ProjectsKeysUpdatePolicyCall {
	c := &ProjectsKeysUpdatePolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecaptchaenterprisev1policy = googlecloudrecaptchaenterprisev1policy
	return c
}

// UpdateMask sets the optional parameter "updateMask": The mask to control
// which fields of the policy get updated. If the mask is not present, all
// fields are updated.
func (c *ProjectsKeysUpdatePolicyCall) UpdateMask(updateMask string) *ProjectsKeysUpdatePolicyCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsKeysUpdatePolicyCall) Fields(s ...googleapi.Field) *ProjectsKeysUpdatePolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsKeysUpdatePolicyCall) Context(ctx context.Context) *ProjectsKeysUpdatePolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsKeysUpdatePolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsKeysUpdatePolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1policy)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.updatePolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.keys.updatePolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1Policy.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsKeysUpdatePolicyCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.keys.updatePolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsRelatedaccountgroupmembershipsSearchCall struct {
	s                                                                           *Service
	project                                                                     string
	googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest *GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest
	urlParams_                                                                  gensupport.URLParams
	ctx_                                                                        context.Context
	header_                                                                     http.Header
}

// Search: Search group memberships related to a given account.
//
//   - project: The name of the project to search related account group
//     memberships from. Specify the project name in the following format:
//     `projects/{project}`.
func (r *ProjectsRelatedaccountgroupmembershipsService) Search(project string, googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest *GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsRequest) *ProjectsRelatedaccountgroupmembershipsSearchCall {
	c := &ProjectsRelatedaccountgroupmembershipsSearchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.project = project
	c.googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest = googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) Fields(s ...googleapi.Field) *ProjectsRelatedaccountgroupmembershipsSearchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) Context(ctx context.Context) *ProjectsRelatedaccountgroupmembershipsSearchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+project}/relatedaccountgroupmemberships:search")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"project": c.project,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroupmemberships.search", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.relatedaccountgroupmemberships.search" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse
// .ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroupmemberships.search", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsRelatedaccountgroupmembershipsSearchCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1SearchRelatedAccountGroupMembershipsResponse) error) error {
	c.ctx_ = ctx
	defer func(pt string) {
		c.googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest.PageToken = pt
	}(c.googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest.PageToken)
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.googlecloudrecaptchaenterprisev1searchrelatedaccountgroupmembershipsrequest.PageToken = x.NextPageToken
	}
}

type ProjectsRelatedaccountgroupsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: List groups of related accounts.
//
//   - parent: The name of the project to list related account groups from, in
//     the format `projects/{project}`.
func (r *ProjectsRelatedaccountgroupsService) List(parent string) *ProjectsRelatedaccountgroupsListCall {
	c := &ProjectsRelatedaccountgroupsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// groups to return. The service might return fewer than this value. If
// unspecified, at most 50 groups are returned. The maximum value is 1000;
// values above 1000 are coerced to 1000.
func (c *ProjectsRelatedaccountgroupsListCall) PageSize(pageSize int64) *ProjectsRelatedaccountgroupsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListRelatedAccountGroups` call. Provide this to retrieve
// the subsequent page. When paginating, all other parameters provided to
// `ListRelatedAccountGroups` must match the call that provided the page token.
func (c *ProjectsRelatedaccountgroupsListCall) PageToken(pageToken string) *ProjectsRelatedaccountgroupsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsRelatedaccountgroupsListCall) Fields(s ...googleapi.Field) *ProjectsRelatedaccountgroupsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsRelatedaccountgroupsListCall) IfNoneMatch(entityTag string) *ProjectsRelatedaccountgroupsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsRelatedaccountgroupsListCall) Context(ctx context.Context) *ProjectsRelatedaccountgroupsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsRelatedaccountgroupsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsRelatedaccountgroupsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/relatedaccountgroups")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroups.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.relatedaccountgroups.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse.ServerRespo
// nse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsRelatedaccountgroupsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroups.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsRelatedaccountgroupsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsRelatedaccountgroupsMembershipsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Get memberships in a group of related accounts.
//
//   - parent: The resource name for the related account group in the format
//     `projects/{project}/relatedaccountgroups/{relatedaccountgroup}`.
func (r *ProjectsRelatedaccountgroupsMembershipsService) List(parent string) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c := &ProjectsRelatedaccountgroupsMembershipsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// accounts to return. The service might return fewer than this value. If
// unspecified, at most 50 accounts are returned. The maximum value is 1000;
// values above 1000 are coerced to 1000.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) PageSize(pageSize int64) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListRelatedAccountGroupMemberships` call. When paginating,
// all other parameters provided to `ListRelatedAccountGroupMemberships` must
// match the call that provided the page token.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) PageToken(pageToken string) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) Fields(s ...googleapi.Field) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) IfNoneMatch(entityTag string) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) Context(ctx context.Context) *ProjectsRelatedaccountgroupsMembershipsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsRelatedaccountgroupsMembershipsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/memberships")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroups.memberships.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recaptchaenterprise.projects.relatedaccountgroups.memberships.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse.S
// erverResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "recaptchaenterprise.projects.relatedaccountgroups.memberships.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsRelatedaccountgroupsMembershipsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecaptchaenterpriseV1ListRelatedAccountGroupMembershipsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}
