// 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 merchantapi provides access to the Merchant API.
//
// For product documentation, see: https://developers.google.com/merchant/api
//
// # 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/merchantapi/accounts/v1"
//	...
//	ctx := context.Background()
//	merchantapiService, err := merchantapi.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]:
//
//	merchantapiService, err := merchantapi.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, ...)
//	merchantapiService, err := merchantapi.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See [google.golang.org/api/option.ClientOption] for details on options.
package merchantapi // import "google.golang.org/api/merchantapi/accounts/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 = "merchantapi:accounts_v1"
const apiName = "merchantapi"
const apiVersion = "accounts_v1"
const basePath = "https://merchantapi.googleapis.com/"
const basePathTemplate = "https://merchantapi.UNIVERSE_DOMAIN/"
const mtlsBasePath = "https://merchantapi.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// Manage your product listings and accounts for Google Shopping
	ContentScope = "https://www.googleapis.com/auth/content"
)

// NewService creates a new APIService.
func NewService(ctx context.Context, opts ...option.ClientOption) (*APIService, error) {
	scopesOption := internaloption.WithDefaultScopes(
		"https://www.googleapis.com/auth/content",
	)
	// 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 := &APIService{client: client, BasePath: basePath, logger: internaloption.GetLogger(opts)}
	s.Accounts = NewAccountsService(s)
	s.TermsOfService = NewTermsOfServiceService(s)
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new APIService. 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) (*APIService, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	return NewService(context.TODO(), option.WithHTTPClient(client))
}

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

	Accounts *AccountsService

	TermsOfService *TermsOfServiceService
}

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

func NewAccountsService(s *APIService) *AccountsService {
	rs := &AccountsService{s: s}
	rs.AutofeedSettings = NewAccountsAutofeedSettingsService(s)
	rs.AutomaticImprovements = NewAccountsAutomaticImprovementsService(s)
	rs.BusinessIdentity = NewAccountsBusinessIdentityService(s)
	rs.BusinessInfo = NewAccountsBusinessInfoService(s)
	rs.DeveloperRegistration = NewAccountsDeveloperRegistrationService(s)
	rs.EmailPreferences = NewAccountsEmailPreferencesService(s)
	rs.GbpAccounts = NewAccountsGbpAccountsService(s)
	rs.Homepage = NewAccountsHomepageService(s)
	rs.Issues = NewAccountsIssuesService(s)
	rs.OmnichannelSettings = NewAccountsOmnichannelSettingsService(s)
	rs.OnlineReturnPolicies = NewAccountsOnlineReturnPoliciesService(s)
	rs.Programs = NewAccountsProgramsService(s)
	rs.Regions = NewAccountsRegionsService(s)
	rs.Relationships = NewAccountsRelationshipsService(s)
	rs.Services = NewAccountsServicesService(s)
	rs.ShippingSettings = NewAccountsShippingSettingsService(s)
	rs.TermsOfServiceAgreementStates = NewAccountsTermsOfServiceAgreementStatesService(s)
	rs.Users = NewAccountsUsersService(s)
	return rs
}

type AccountsService struct {
	s *APIService

	AutofeedSettings *AccountsAutofeedSettingsService

	AutomaticImprovements *AccountsAutomaticImprovementsService

	BusinessIdentity *AccountsBusinessIdentityService

	BusinessInfo *AccountsBusinessInfoService

	DeveloperRegistration *AccountsDeveloperRegistrationService

	EmailPreferences *AccountsEmailPreferencesService

	GbpAccounts *AccountsGbpAccountsService

	Homepage *AccountsHomepageService

	Issues *AccountsIssuesService

	OmnichannelSettings *AccountsOmnichannelSettingsService

	OnlineReturnPolicies *AccountsOnlineReturnPoliciesService

	Programs *AccountsProgramsService

	Regions *AccountsRegionsService

	Relationships *AccountsRelationshipsService

	Services *AccountsServicesService

	ShippingSettings *AccountsShippingSettingsService

	TermsOfServiceAgreementStates *AccountsTermsOfServiceAgreementStatesService

	Users *AccountsUsersService
}

func NewAccountsAutofeedSettingsService(s *APIService) *AccountsAutofeedSettingsService {
	rs := &AccountsAutofeedSettingsService{s: s}
	return rs
}

type AccountsAutofeedSettingsService struct {
	s *APIService
}

func NewAccountsAutomaticImprovementsService(s *APIService) *AccountsAutomaticImprovementsService {
	rs := &AccountsAutomaticImprovementsService{s: s}
	return rs
}

type AccountsAutomaticImprovementsService struct {
	s *APIService
}

func NewAccountsBusinessIdentityService(s *APIService) *AccountsBusinessIdentityService {
	rs := &AccountsBusinessIdentityService{s: s}
	return rs
}

type AccountsBusinessIdentityService struct {
	s *APIService
}

func NewAccountsBusinessInfoService(s *APIService) *AccountsBusinessInfoService {
	rs := &AccountsBusinessInfoService{s: s}
	return rs
}

type AccountsBusinessInfoService struct {
	s *APIService
}

func NewAccountsDeveloperRegistrationService(s *APIService) *AccountsDeveloperRegistrationService {
	rs := &AccountsDeveloperRegistrationService{s: s}
	return rs
}

type AccountsDeveloperRegistrationService struct {
	s *APIService
}

func NewAccountsEmailPreferencesService(s *APIService) *AccountsEmailPreferencesService {
	rs := &AccountsEmailPreferencesService{s: s}
	return rs
}

type AccountsEmailPreferencesService struct {
	s *APIService
}

func NewAccountsGbpAccountsService(s *APIService) *AccountsGbpAccountsService {
	rs := &AccountsGbpAccountsService{s: s}
	return rs
}

type AccountsGbpAccountsService struct {
	s *APIService
}

func NewAccountsHomepageService(s *APIService) *AccountsHomepageService {
	rs := &AccountsHomepageService{s: s}
	return rs
}

type AccountsHomepageService struct {
	s *APIService
}

func NewAccountsIssuesService(s *APIService) *AccountsIssuesService {
	rs := &AccountsIssuesService{s: s}
	return rs
}

type AccountsIssuesService struct {
	s *APIService
}

func NewAccountsOmnichannelSettingsService(s *APIService) *AccountsOmnichannelSettingsService {
	rs := &AccountsOmnichannelSettingsService{s: s}
	rs.LfpProviders = NewAccountsOmnichannelSettingsLfpProvidersService(s)
	return rs
}

type AccountsOmnichannelSettingsService struct {
	s *APIService

	LfpProviders *AccountsOmnichannelSettingsLfpProvidersService
}

func NewAccountsOmnichannelSettingsLfpProvidersService(s *APIService) *AccountsOmnichannelSettingsLfpProvidersService {
	rs := &AccountsOmnichannelSettingsLfpProvidersService{s: s}
	return rs
}

type AccountsOmnichannelSettingsLfpProvidersService struct {
	s *APIService
}

func NewAccountsOnlineReturnPoliciesService(s *APIService) *AccountsOnlineReturnPoliciesService {
	rs := &AccountsOnlineReturnPoliciesService{s: s}
	return rs
}

type AccountsOnlineReturnPoliciesService struct {
	s *APIService
}

func NewAccountsProgramsService(s *APIService) *AccountsProgramsService {
	rs := &AccountsProgramsService{s: s}
	rs.CheckoutSettings = NewAccountsProgramsCheckoutSettingsService(s)
	return rs
}

type AccountsProgramsService struct {
	s *APIService

	CheckoutSettings *AccountsProgramsCheckoutSettingsService
}

func NewAccountsProgramsCheckoutSettingsService(s *APIService) *AccountsProgramsCheckoutSettingsService {
	rs := &AccountsProgramsCheckoutSettingsService{s: s}
	return rs
}

type AccountsProgramsCheckoutSettingsService struct {
	s *APIService
}

func NewAccountsRegionsService(s *APIService) *AccountsRegionsService {
	rs := &AccountsRegionsService{s: s}
	return rs
}

type AccountsRegionsService struct {
	s *APIService
}

func NewAccountsRelationshipsService(s *APIService) *AccountsRelationshipsService {
	rs := &AccountsRelationshipsService{s: s}
	return rs
}

type AccountsRelationshipsService struct {
	s *APIService
}

func NewAccountsServicesService(s *APIService) *AccountsServicesService {
	rs := &AccountsServicesService{s: s}
	return rs
}

type AccountsServicesService struct {
	s *APIService
}

func NewAccountsShippingSettingsService(s *APIService) *AccountsShippingSettingsService {
	rs := &AccountsShippingSettingsService{s: s}
	return rs
}

type AccountsShippingSettingsService struct {
	s *APIService
}

func NewAccountsTermsOfServiceAgreementStatesService(s *APIService) *AccountsTermsOfServiceAgreementStatesService {
	rs := &AccountsTermsOfServiceAgreementStatesService{s: s}
	return rs
}

type AccountsTermsOfServiceAgreementStatesService struct {
	s *APIService
}

func NewAccountsUsersService(s *APIService) *AccountsUsersService {
	rs := &AccountsUsersService{s: s}
	rs.Me = NewAccountsUsersMeService(s)
	return rs
}

type AccountsUsersService struct {
	s *APIService

	Me *AccountsUsersMeService
}

func NewAccountsUsersMeService(s *APIService) *AccountsUsersMeService {
	rs := &AccountsUsersMeService{s: s}
	return rs
}

type AccountsUsersMeService struct {
	s *APIService
}

func NewTermsOfServiceService(s *APIService) *TermsOfServiceService {
	rs := &TermsOfServiceService{s: s}
	return rs
}

type TermsOfServiceService struct {
	s *APIService
}

// About: Collection of information related to the about page (impressum
// (https://support.google.com/merchants/answer/14675634?ref_topic=15145634&sjid=6892280366904591178-NC)).
type About struct {
	// State: Output only. The state of the URI.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	State string `json:"state,omitempty"`
	// Uri: Required. The about page URI.
	Uri string `json:"uri,omitempty"`
	// ForceSendFields is a list of field names (e.g. "State") 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. "State") 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 About) MarshalJSON() ([]byte, error) {
	type NoMethod About
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AcceptTermsOfServiceResponse: Response message for the
// `AcceptTermsOfService` method.
type AcceptTermsOfServiceResponse struct {
	// TermsOfServiceAgreementState: The agreement state after accepting the ToS.
	TermsOfServiceAgreementState *TermsOfServiceAgreementState `json:"termsOfServiceAgreementState,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g.
	// "TermsOfServiceAgreementState") 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. "TermsOfServiceAgreementState") 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 AcceptTermsOfServiceResponse) MarshalJSON() ([]byte, error) {
	type NoMethod AcceptTermsOfServiceResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Accepted: Describes the accepted terms of service
// (https://developers.google.com/merchant/api/guides/accounts/create-and-configure#accept_the_merchant_center_terms_of_service).
type Accepted struct {
	// AcceptedBy: Required. The account where the acceptance was recorded. This
	// can be the account itself or, in the case of subaccounts, the advanced
	// account.
	AcceptedBy string `json:"acceptedBy,omitempty"`
	// TermsOfService: Required. The accepted termsOfService.
	TermsOfService string `json:"termsOfService,omitempty"`
	// ValidUntil: Optional. When set, it states that the accepted `TermsOfService`
	// is only valid until the end of this date (in UTC). A new one must be
	// accepted before then. The information of the required `TermsOfService` is
	// found in the `Required` message.
	ValidUntil *Date `json:"validUntil,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AcceptedBy") 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. "AcceptedBy") 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 Accepted) MarshalJSON() ([]byte, error) {
	type NoMethod Accepted
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Account: The `Account` message represents a business's account within
// Shopping Ads. It's the primary entity for managing product data, settings,
// and interactions with Google's services and external providers. Accounts can
// operate as standalone entities or be part of a advanced account structure.
// In an advanced account setup the parent account manages multiple
// sub-accounts. Establishing an account involves configuring attributes like
// the account name, time zone, and language preferences. The `Account` message
// is the parent entity for many other resources, for example,
// `AccountRelationship`, `Homepage`, `BusinessInfo` and so on.
type Account struct {
	// AccountId: Output only. The ID of the account.
	AccountId int64 `json:"accountId,omitempty,string"`
	// AccountName: Required. A human-readable name of the account. Don't use
	// punctuation, capitalization, or non-alphanumeric symbols such as the "/" or
	// "_" symbols. See Adding a business name
	// (https://support.google.com/merchants/answer/12159159) for more information.
	AccountName string `json:"accountName,omitempty"`
	// AdultContent: Optional. Whether this account contains adult content.
	AdultContent bool `json:"adultContent,omitempty"`
	// LanguageCode: Required. The account's BCP-47 language code
	// (https://tools.ietf.org/html/bcp47), such as `en-US` or `sr-Latn`.
	LanguageCode string `json:"languageCode,omitempty"`
	// Name: Identifier. The resource name of the account. Format:
	// `accounts/{account}`
	Name string `json:"name,omitempty"`
	// TestAccount: Output only. Whether this is a test account.
	TestAccount bool `json:"testAccount,omitempty"`
	// TimeZone: Required. The time zone of the account. On writes, `time_zone`
	// sets both the `reporting_time_zone` and the `display_time_zone`. For reads,
	// `time_zone` always returns the `display_time_zone`. If `display_time_zone`
	// doesn't exist for your account, `time_zone` is empty. The `version` field is
	// not supported, won't be set in responses and will be silently ignored if
	// specified in requests.
	TimeZone *TimeZone `json:"timeZone,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// 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 Account) MarshalJSON() ([]byte, error) {
	type NoMethod Account
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AccountAggregation: `AccountAggregation` payload.
type AccountAggregation struct {
}

// AccountIssue: Issues with your Merchant Center account that can impact all
// your products. For more information, see Account-level issues in Merchant
// Center
// (https://support.google.com/merchants/answer/12153802?sjid=17798438912526418908-EU#account).
type AccountIssue struct {
	// Detail: Further localized details about the issue.
	Detail string `json:"detail,omitempty"`
	// DocumentationUri: Link to Merchant Center Help Center providing further
	// information about the issue and how to fix it.
	DocumentationUri string `json:"documentationUri,omitempty"`
	// ImpactedDestinations: The impact this issue has on various destinations.
	ImpactedDestinations []*ImpactedDestination `json:"impactedDestinations,omitempty"`
	// Name: Identifier. The resource name of the account issue. Format:
	// `accounts/{account}/issues/{id}`. For example,
	// `accounts/123456/issues/misrepresentation-of-self-or-products-unacceptable-bu
	// siness-practice-policy`.
	Name string `json:"name,omitempty"`
	// Severity: The overall severity of the issue.
	//
	// Possible values:
	//   "SEVERITY_UNSPECIFIED" - The severity is unknown.
	//   "CRITICAL" - The issue causes offers to not serve.
	//   "ERROR" - The issue might affect offers (in the future) or might be an
	// indicator of issues with offers.
	//   "SUGGESTION" - The issue is a suggestion for improvement.
	Severity string `json:"severity,omitempty"`
	// Title: The localized title of the issue.
	Title string `json:"title,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Detail") 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. "Detail") 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 AccountIssue) MarshalJSON() ([]byte, error) {
	type NoMethod AccountIssue
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AccountManagement: `AccountManagement` payload.
type AccountManagement struct {
}

// AccountRelationship: The `AccountRelationship` message defines a formal
// connection between a merchant's account and a service provider's account.
// This relationship enables the provider to offer specific services to the
// business, such as product management or campaign management. It specifies
// the access rights and permissions to the business's data relevant to those
// services. Establishing an account relationship involves linking the
// merchant's account with a provider's account. The provider could be another
// Google account (like Google Ads or Google My Business) or a third-party
// platform (such as Shopify or WooCommerce).
type AccountRelationship struct {
	// AccountIdAlias: Optional. An optional alias you can assign to this account
	// relationship. This alias acts as a convenient identifier for your own
	// reference and management. It must be unique among all your account
	// relationships with the same provider. For example, you might use
	// `account_id_alias` to assign a friendly name to this relationship for easier
	// identification in your systems.
	AccountIdAlias string `json:"accountIdAlias,omitempty"`
	// Name: Identifier. The resource name of the account relationship. Format:
	// `accounts/{account}/relationships/{relationship}`. For example,
	// `accounts/123456/relationships/567890`.
	Name string `json:"name,omitempty"`
	// Provider: Immutable. The provider of the service. Either the reference to an
	// account such as `providers/123` or a well-known service provider (one of
	// `providers/GOOGLE_ADS` or `providers/GOOGLE_BUSINESS_PROFILE`).
	Provider string `json:"provider,omitempty"`
	// ProviderDisplayName: Output only. The human-readable display name of the
	// provider account.
	ProviderDisplayName string `json:"providerDisplayName,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AccountIdAlias") 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. "AccountIdAlias") 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 AccountRelationship) MarshalJSON() ([]byte, error) {
	type NoMethod AccountRelationship
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AccountService: The `AccountService` message represents a specific service
// that a provider account offers to a Merchant Center account.
// `AccountService` defines the permissions and capabilities granted to the
// provider, allowing for operations such as product management or campaign
// management. The lifecycle of an `AccountService` involves a proposal phase,
// where one party suggests the service, and an approval phase, where the other
// party accepts or rejects it. This handshake mechanism ensures mutual consent
// before any access is granted. This mechanism safeguards both parties by
// ensuring that access rights are granted appropriately and that both the
// business and provider are aware of the services enabled. In scenarios where
// a user is an admin of both accounts, the approval can happen automatically.
// The mutability of a service is also managed through `AccountService`. Some
// services might be immutable, for example, if they were established through
// other systems or APIs, and you cannot alter them through this API.
type AccountService struct {
	// AccountAggregation: Service type for account aggregation. This enables the
	// provider, which is an advanced account, to manage multiple sub-accounts
	// (client accounts). Through this service, the advanced account provider can
	// perform administrative and operational tasks across all linked sub-accounts.
	// This is useful for agencies, aggregators, or large retailers that need
	// centralized control over many Merchant Center accounts.
	AccountAggregation *AccountAggregation `json:"accountAggregation,omitempty"`
	// AccountManagement: Service type for account management. Enables the provider
	// to perform administrative actions on the business's account, such as
	// configuring account settings, managing users, or updating business
	// information.
	AccountManagement *AccountManagement `json:"accountManagement,omitempty"`
	// CampaignsManagement: Service type for managing advertising campaigns. Grants
	// the provider access to create and manage the business's ad campaigns,
	// including setting up campaigns, adjusting bids, and optimizing performance.
	CampaignsManagement *CampaignsManagement `json:"campaignsManagement,omitempty"`
	// ComparisonShopping: Service type for comparison shopping. The provider is a
	// CSS (Comparison Shopping Service) managing the account. See
	// https://support.google.com/merchants/answer/12653197
	ComparisonShopping *ComparisonShopping `json:"comparisonShopping,omitempty"`
	// ExternalAccountId: Immutable. An optional, immutable identifier that Google
	// uses to refer to this account when communicating with the provider. This
	// should be the unique account ID within the provider's system (for example,
	// your shop ID in Shopify). If you have multiple accounts with the same
	// provider - for instance, different accounts for various regions — the
	// `external_account_id` differentiates between them, ensuring accurate linking
	// and integration between Google and the provider.
	ExternalAccountId string `json:"externalAccountId,omitempty"`
	// Handshake: Output only. Information about the state of the service in terms
	// of establishing it (e.g. is it pending approval or approved).
	Handshake *Handshake `json:"handshake,omitempty"`
	// LocalListingManagement: Service type for local listings management. The
	// business group associated with the external account id will be used to
	// provide local inventory to this Merchant Center account.
	LocalListingManagement *LocalListingManagement `json:"localListingManagement,omitempty"`
	// Mutability: Output only. Whether the service is mutable (e.g. through
	// Approve / Reject RPCs). A service that was created through another system or
	// API might be immutable.
	//
	// Possible values:
	//   "MUTABILITY_UNSPECIFIED" - Unused default value
	//   "MUTABLE" - The service can be mutated without restrictions.
	//   "IMMUTABLE" - The service is read-only and must not be mutated.
	Mutability string `json:"mutability,omitempty"`
	// Name: Identifier. The resource name of the account service. Format:
	// `accounts/{account}/services/{service}`
	Name string `json:"name,omitempty"`
	// ProductsManagement: Service type for managing products. This allows the
	// provider to handle product data on behalf of the business, including reading
	// and writing product listings. It's commonly used when the provider offers
	// inventory management or catalog synchronization services to keep the
	// business's product information up-to-date across platforms.
	ProductsManagement *ProductsManagement `json:"productsManagement,omitempty"`
	// Provider: Output only. The provider of the service. Either the reference to
	// an account such as `providers/123` or a well-known service provider (one of
	// `providers/GOOGLE_ADS` or `providers/GOOGLE_BUSINESS_PROFILE`).
	Provider string `json:"provider,omitempty"`
	// ProviderDisplayName: Output only. The human-readable display name of the
	// provider account.
	ProviderDisplayName string `json:"providerDisplayName,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AccountAggregation") 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. "AccountAggregation") 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 AccountService) MarshalJSON() ([]byte, error) {
	type NoMethod AccountService
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AddAccountService: Additional instructions to add account services during
// creation of the account.
type AddAccountService struct {
	// AccountAggregation: The provider is an aggregator
	// (https://support.google.com/merchants/answer/188487) for the account.
	// Payload for service type Account Aggregation.
	AccountAggregation *AccountAggregation `json:"accountAggregation,omitempty"`
	// AccountManagement: The provider manages this account. Payload for service
	// type Account Management.
	AccountManagement *AccountManagement `json:"accountManagement,omitempty"`
	// CampaignsManagement: The provider manages campaigns for this account.
	// Payload for service type campaigns management.
	CampaignsManagement *CampaignsManagement `json:"campaignsManagement,omitempty"`
	// ComparisonShopping: The provider is a CSS (Comparison Shopping Service) of
	// this account. Payload for service type Comparison Shopping.
	ComparisonShopping *ComparisonShopping `json:"comparisonShopping,omitempty"`
	// ExternalAccountId: Immutable. An optional, immutable identifier that Google
	// uses to refer to this account when communicating with the provider. This
	// should be the unique account ID within the provider's system (for example,
	// your shop ID in Shopify). If you have multiple accounts with the same
	// provider - for instance, different accounts for various regions — the
	// `external_account_id` differentiates between them, ensuring accurate linking
	// and integration between Google and the provider. The external account ID
	// must be specified for the campaigns management service type. The external
	// account ID must not be specified for the account aggregation service type.
	// The external account ID is optional / may be specified for all other service
	// types.
	ExternalAccountId string `json:"externalAccountId,omitempty"`
	// ProductsManagement: The provider manages products for this account. Payload
	// for service type products management.
	ProductsManagement *ProductsManagement `json:"productsManagement,omitempty"`
	// Provider: Required. The provider of the service. Either the reference to an
	// account such as `providers/123` or a well-known service provider (one of
	// `providers/GOOGLE_ADS` or `providers/GOOGLE_BUSINESS_PROFILE`).
	Provider string `json:"provider,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountAggregation") 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. "AccountAggregation") 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 AddAccountService) MarshalJSON() ([]byte, error) {
	type NoMethod AddAccountService
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AddUser: Instruction for adding a user to the account during creation.
type AddUser struct {
	// User: Optional. Details about the user to be added. At the moment, only
	// access rights may be specified.
	User *User `json:"user,omitempty"`
	// UserId: Required. The email address of the user (for example,
	// `john.doe@gmail.com`).
	UserId string `json:"userId,omitempty"`
	// VerificationMailSettings: Optional. Settings related to configuring the
	// verification email that is sent after adding a user.
	VerificationMailSettings *VerificationMailSettings `json:"verificationMailSettings,omitempty"`
	// ForceSendFields is a list of field names (e.g. "User") 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. "User") 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 AddUser) MarshalJSON() ([]byte, error) {
	type NoMethod AddUser
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Address: Shipping address of the warehouse.
type Address struct {
	// AdministrativeArea: Required. Top-level administrative subdivision of the
	// country. For example, a state like California ("CA") or a province like
	// Quebec ("QC").
	AdministrativeArea string `json:"administrativeArea,omitempty"`
	// City: Required. City, town or commune. May also include dependent localities
	// or sublocalities (For example neighborhoods or suburbs).
	City string `json:"city,omitempty"`
	// PostalCode: Required. Postal code or ZIP (For example "94043").
	PostalCode string `json:"postalCode,omitempty"`
	// RegionCode: Required. CLDR country code
	// (http://www.unicode.org/repos/cldr/tags/latest/common/main/en.xml) (For
	// example "US").
	RegionCode string `json:"regionCode,omitempty"`
	// StreetAddress: Street-level part of the address. For example: `111w 31st
	// Street`.
	StreetAddress string `json:"streetAddress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AdministrativeArea") 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. "AdministrativeArea") 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 Address) MarshalJSON() ([]byte, error) {
	type NoMethod Address
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ApproveAccountServiceRequest: Request to approve an account service.
type ApproveAccountServiceRequest struct {
}

// AutofeedSettings: Collection of information related to the autofeed
// (https://support.google.com/merchants/answer/7538732) settings.
type AutofeedSettings struct {
	// Eligible: Output only. Determines whether the business is eligible for being
	// enrolled into an autofeed.
	Eligible bool `json:"eligible,omitempty"`
	// EnableProducts: Required. Enables or disables product crawling through the
	// autofeed for the given account. Autofeed accounts must meet certain
	// conditions
	// (https://support.google.com/merchants/answer/7538732#Configure_automated_feeds_Standard_Experience),
	// which can be checked through the `eligible` field. The account must **not**
	// be a marketplace. When the autofeed is enabled for the first time, the
	// products usually appear instantly. When re-enabling, it might take up to 24
	// hours for products to appear.
	EnableProducts bool `json:"enableProducts,omitempty"`
	// Name: Identifier. The resource name of the autofeed settings. Format:
	// `accounts/{account}/autofeedSettings`.
	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. "Eligible") 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. "Eligible") 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 AutofeedSettings) MarshalJSON() ([]byte, error) {
	type NoMethod AutofeedSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutomaticImageImprovements: This improvement will attempt to automatically
// correct submitted images if they don't meet the image requirements
// (https://support.google.com/merchants/answer/6324350), for example, removing
// overlays. If successful, the image will be replaced and approved. This
// improvement is only applied to images of disapproved offers. For more
// information see: Automatic image improvements
// (https://support.google.com/merchants/answer/9242973)
type AutomaticImageImprovements struct {
	// AccountImageImprovementsSettings: Optional. Determines how the images should
	// be automatically updated. If this field is not present and provided in the
	// update mask, then the settings will be deleted. If there are no settings for
	// subaccount, they are inherited from aggregator.
	AccountImageImprovementsSettings *ImageImprovementsAccountLevelSettings `json:"accountImageImprovementsSettings,omitempty"`
	// EffectiveAllowAutomaticImageImprovements: Output only. The effective value
	// of allow_automatic_image_improvements. If
	// account_image_improvements_settings is present, then this value is the same.
	// Otherwise, it represents the inherited value of the parent account.
	// Read-only.
	EffectiveAllowAutomaticImageImprovements bool `json:"effectiveAllowAutomaticImageImprovements,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "AccountImageImprovementsSettings") 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.
	// "AccountImageImprovementsSettings") 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 AutomaticImageImprovements) MarshalJSON() ([]byte, error) {
	type NoMethod AutomaticImageImprovements
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutomaticImprovements: Collection of information related to the automatic
// improvements
// (https://developers.google.com/shopping-content/guides/automatic-improvements)
// of an account.
type AutomaticImprovements struct {
	// ImageImprovements: This improvement will attempt to automatically correct
	// submitted images if they don't meet the image requirements
	// (https://support.google.com/merchants/answer/6324350), for example, removing
	// overlays. If successful, the image will be replaced and approved. This
	// improvement is only applied to images of disapproved offers. For more
	// information see: Automatic image improvements
	// (https://support.google.com/merchants/answer/9242973) This field is only
	// updated (cleared) if provided in the update mask.
	ImageImprovements *AutomaticImageImprovements `json:"imageImprovements,omitempty"`
	// ItemUpdates: Turning on item updates
	// (https://support.google.com/merchants/answer/3246284) allows Google to
	// automatically update items for you. When item updates are on, Google uses
	// the structured data markup on the website and advanced data extractors to
	// update the price and availability of the items. When the item updates are
	// off, items with mismatched data aren't shown. This field is only updated
	// (cleared) if provided in the update mask.
	ItemUpdates *AutomaticItemUpdates `json:"itemUpdates,omitempty"`
	// Name: Identifier. The resource name of the automatic improvements. Format:
	// `accounts/{account}/automaticImprovements`.
	Name string `json:"name,omitempty"`
	// ShippingImprovements: Not available for advanced accounts
	// (https://support.google.com/merchants/answer/188487). By turning on
	// automatic shipping improvements
	// (https://support.google.com/merchants/answer/10027038), you are allowing
	// Google to improve the accuracy of your delivery times shown to shoppers
	// using Google. More accurate delivery times, especially when faster,
	// typically lead to better conversion rates. Google will improve your
	// estimated delivery times based on various factors: * Delivery address of an
	// order * Current handling time and shipping time settings * Estimated
	// weekdays or business days * Parcel tracking data This field is only updated
	// (cleared) if provided in the update mask.
	ShippingImprovements *AutomaticShippingImprovements `json:"shippingImprovements,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ImageImprovements") 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. "ImageImprovements") 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 AutomaticImprovements) MarshalJSON() ([]byte, error) {
	type NoMethod AutomaticImprovements
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutomaticItemUpdates: Turning on item updates
// (https://support.google.com/merchants/answer/3246284) allows Google to
// automatically update items for you. When item updates are on, Google uses
// the structured data markup on the website and advanced data extractors to
// update the price and availability of the items. When the item updates are
// off, items with mismatched data aren't shown.
type AutomaticItemUpdates struct {
	// AccountItemUpdatesSettings: Optional. Determines which attributes of the
	// items should be automatically updated. If this field is not present and
	// provided in the update mask, then the settings will be deleted. If there are
	// no settings for subaccount, they are inherited from aggregator.
	AccountItemUpdatesSettings *ItemUpdatesAccountLevelSettings `json:"accountItemUpdatesSettings,omitempty"`
	// EffectiveAllowAvailabilityUpdates: Output only. The effective value of
	// allow_availability_updates. If account_item_updates_settings is present,
	// then this value is the same. Otherwise, it represents the inherited value of
	// the parent account. The default value is true if no settings are present.
	// Read-only.
	EffectiveAllowAvailabilityUpdates bool `json:"effectiveAllowAvailabilityUpdates,omitempty"`
	// EffectiveAllowConditionUpdates: Output only. The effective value of
	// allow_condition_updates. If account_item_updates_settings is present, then
	// this value is the same. Otherwise, it represents the inherited value of the
	// parent account. The default value is true if no settings are present.
	// Read-only.
	EffectiveAllowConditionUpdates bool `json:"effectiveAllowConditionUpdates,omitempty"`
	// EffectiveAllowPriceUpdates: Output only. The effective value of
	// allow_price_updates. If account_item_updates_settings is present, then this
	// value is the same. Otherwise, it represents the inherited value of the
	// parent account. The default value is true if no settings are present.
	// Read-only.
	EffectiveAllowPriceUpdates bool `json:"effectiveAllowPriceUpdates,omitempty"`
	// EffectiveAllowStrictAvailabilityUpdates: Output only. The effective value of
	// allow_strict_availability_updates. If account_item_updates_settings is
	// present, then this value is the same. Otherwise, it represents the inherited
	// value of the parent account. The default value is true if no settings are
	// present. Read-only.
	EffectiveAllowStrictAvailabilityUpdates bool `json:"effectiveAllowStrictAvailabilityUpdates,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountItemUpdatesSettings")
	// 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. "AccountItemUpdatesSettings") 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 AutomaticItemUpdates) MarshalJSON() ([]byte, error) {
	type NoMethod AutomaticItemUpdates
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutomaticShippingImprovements: Not available for advanced accounts
// (https://support.google.com/merchants/answer/188487). By turning on
// automatic shipping improvements
// (https://support.google.com/merchants/answer/10027038), you are allowing
// Google to improve the accuracy of your delivery times shown to shoppers
// using Google. More accurate delivery times, especially when faster,
// typically lead to better conversion rates. Google will improve your
// estimated delivery times based on various factors: * Delivery address of an
// order * Current handling time and shipping time settings * Estimated
// weekdays or business days * Parcel tracking data
type AutomaticShippingImprovements struct {
	// AllowShippingImprovements: Enables automatic shipping improvements.
	AllowShippingImprovements bool `json:"allowShippingImprovements,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowShippingImprovements")
	// 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. "AllowShippingImprovements") 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 AutomaticShippingImprovements) MarshalJSON() ([]byte, error) {
	type NoMethod AutomaticShippingImprovements
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchCreateRegionsRequest: Request message for the `BatchCreateRegions`
// method.
type BatchCreateRegionsRequest struct {
	// Requests: Required. The region(s) to create. The maximum number of regions
	// that can be created in a batch is 100.
	Requests []*CreateRegionRequest `json:"requests,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Requests") 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. "Requests") 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 BatchCreateRegionsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BatchCreateRegionsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchCreateRegionsResponse: Response message for the `BatchCreateRegions`
// method.
type BatchCreateRegionsResponse struct {
	// Regions: The created region(s).
	Regions []*Region `json:"regions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Regions") 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. "Regions") 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 BatchCreateRegionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod BatchCreateRegionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchDeleteRegionsRequest: Request message for the `BatchDeleteRegions`
// method.
type BatchDeleteRegionsRequest struct {
	// Requests: Required. The names of the regions to delete. A maximum of 100
	// regions can be deleted in a batch.
	Requests []*DeleteRegionRequest `json:"requests,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Requests") 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. "Requests") 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 BatchDeleteRegionsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BatchDeleteRegionsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchUpdateRegionsRequest: Request message for the `BatchUpdateRegions`
// method.
type BatchUpdateRegionsRequest struct {
	// Requests: Required. The region(s) to update. The maximum number of regions
	// that can be updated in a batch is 100.
	Requests []*UpdateRegionRequest `json:"requests,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Requests") 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. "Requests") 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 BatchUpdateRegionsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BatchUpdateRegionsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchUpdateRegionsResponse: Response message for the `BatchUpdateRegions`
// method.
type BatchUpdateRegionsResponse struct {
	// Regions: The updated region(s).
	Regions []*Region `json:"regions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Regions") 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. "Regions") 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 BatchUpdateRegionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod BatchUpdateRegionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BusinessDayConfig: Business days of the warehouse.
type BusinessDayConfig struct {
	// BusinessDays: Required. Regular business days. May not be empty.
	//
	// Possible values:
	//   "WEEKDAY_UNSPECIFIED"
	//   "MONDAY"
	//   "TUESDAY"
	//   "WEDNESDAY"
	//   "THURSDAY"
	//   "FRIDAY"
	//   "SATURDAY"
	//   "SUNDAY"
	BusinessDays []string `json:"businessDays,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BusinessDays") 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. "BusinessDays") 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 BusinessDayConfig) MarshalJSON() ([]byte, error) {
	type NoMethod BusinessDayConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BusinessIdentity: Collection of information related to the identity of a
// business (https://support.google.com/merchants/answer/12564247).
type BusinessIdentity struct {
	// BlackOwned: Optional. Specifies whether the business identifies itself as
	// being black-owned. This optional field will only be available for businesses
	// with the business country set to `US`. It is also not applicable for
	// marketplaces or marketplace sellers.
	BlackOwned *IdentityAttribute `json:"blackOwned,omitempty"`
	// LatinoOwned: Optional. Specifies whether the business identifies itself as
	// being latino-owned. This optional field will only be available for
	// businesses with the business country set to `US`. It is also not applicable
	// for marketplaces or marketplace sellers.
	LatinoOwned *IdentityAttribute `json:"latinoOwned,omitempty"`
	// Name: Identifier. The resource name of the business identity. Format:
	// `accounts/{account}/businessIdentity`
	Name string `json:"name,omitempty"`
	// PromotionsConsent: Required. Whether the identity attributes may be used for
	// promotions.
	//
	// Possible values:
	//   "PROMOTIONS_CONSENT_UNSPECIFIED" - Default value indicating that no
	// selection was made.
	//   "PROMOTIONS_CONSENT_GIVEN" - Indicates that the account consented to
	// having their business identity used for promotions.
	//   "PROMOTIONS_CONSENT_DENIED" - Indicates that the account did not consent
	// to having their business identity used for promotions.
	PromotionsConsent string `json:"promotionsConsent,omitempty"`
	// SmallBusiness: Optional. Specifies whether the business identifies itself as
	// a small business. This optional field will only be available for businesses
	// with a business country set to `US`. It is also not applicable for
	// marketplaces.
	SmallBusiness *IdentityAttribute `json:"smallBusiness,omitempty"`
	// VeteranOwned: Optional. Specifies whether the business identifies itself as
	// being veteran-owned. This optional field will only be available for
	// businesses with a business country set to `US`. It is also not applicable
	// for marketplaces or marketplace sellers.
	VeteranOwned *IdentityAttribute `json:"veteranOwned,omitempty"`
	// WomenOwned: Optional. Specifies whether the business identifies itself as
	// being women-owned. This optional field will only be available for businesses
	// with a business country set to `US`. It is also not applicable for
	// marketplaces or marketplace sellers.
	WomenOwned *IdentityAttribute `json:"womenOwned,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "BlackOwned") 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. "BlackOwned") 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 BusinessIdentity) MarshalJSON() ([]byte, error) {
	type NoMethod BusinessIdentity
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BusinessInfo: The `BusinessInfo` message contains essential information
// about a business. This message captures key business details such as
// physical address, customer service contacts, and region-specific
// identifiers.
type BusinessInfo struct {
	// Address: Optional. The address of the business. Only `region_code`,
	// `address_lines`, `postal_code`, `administrative_area` and `locality` fields
	// are supported. All other fields are ignored.
	Address *PostalAddress `json:"address,omitempty"`
	// CustomerService: Optional. The customer service of the business.
	CustomerService *CustomerService `json:"customerService,omitempty"`
	// KoreanBusinessRegistrationNumber: Optional. The 10-digit Korean business
	// registration number (https://support.google.com/merchants/answer/9037766)
	// separated with dashes in the format: XXX-XX-XXXXX.
	KoreanBusinessRegistrationNumber string `json:"koreanBusinessRegistrationNumber,omitempty"`
	// Name: Identifier. The resource name of the business info. Format:
	// `accounts/{account}/businessInfo`
	Name string `json:"name,omitempty"`
	// Phone: Output only. The phone number of the business.
	Phone *PhoneNumber `json:"phone,omitempty"`
	// PhoneVerificationState: Output only. The phone verification state of the
	// business.
	//
	// Possible values:
	//   "PHONE_VERIFICATION_STATE_UNSPECIFIED" - Default value. This value is
	// unused.
	//   "PHONE_VERIFICATION_STATE_VERIFIED" - The phone is verified.
	//   "PHONE_VERIFICATION_STATE_UNVERIFIED" - The phone is unverified.
	PhoneVerificationState string `json:"phoneVerificationState,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// 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 BusinessInfo) MarshalJSON() ([]byte, error) {
	type NoMethod BusinessInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CampaignsManagement: `CampaignManagement` payload.
type CampaignsManagement struct {
}

// CarrierRate: A list of carrier rates that can be referred to by `main_table`
// or `single_value`. Supported carrier services are defined in
// https://support.google.com/merchants/answer/12577710?ref_topic=12570808&sjid=10662598224319463032-NC#zippy=%2Cdelivery-cost-rate-type%2Ccarrier-rate-au-de-uk-and-us-only.
type CarrierRate struct {
	// Carrier: Required. Carrier service, such as "UPS" or "Fedex".
	Carrier string `json:"carrier,omitempty"`
	// CarrierService: Required. Carrier service, such as "ground" or "2 days".
	CarrierService string `json:"carrierService,omitempty"`
	// FlatAdjustment: Optional. Additive shipping rate modifier. Can be negative.
	// For example `{ "amount_micros": 1, "currency_code" : "USD" }` adds $1 to the
	// rate, `{ "amount_micros": -3, "currency_code" : "USD" }` removes $3 from the
	// rate.
	FlatAdjustment *Price `json:"flatAdjustment,omitempty"`
	// Name: Required. Name of the carrier rate. Must be unique per rate group.
	Name string `json:"name,omitempty"`
	// OriginPostalCode: Required. Shipping origin for this carrier rate.
	OriginPostalCode string `json:"originPostalCode,omitempty"`
	// PercentageAdjustment: Optional. Multiplicative shipping rate modifier as a
	// number in decimal notation. Can be negative. For example "5.4" increases
	// the rate by 5.4%, "-3" decreases the rate by 3%.
	PercentageAdjustment string `json:"percentageAdjustment,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Carrier") 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. "Carrier") 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 CarrierRate) MarshalJSON() ([]byte, error) {
	type NoMethod CarrierRate
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CheckoutSettings: CheckoutSettings
// (https://support.google.com/merchants/answer/13945960) for a specific
// merchant.
type CheckoutSettings struct {
	// EffectiveEnrollmentState: Output only. The effective value of
	// enrollment_state for a given merchant ID. If account level settings are
	// present then this value will be a copy of the account level settings.
	// Otherwise, it will have the value of the parent account (for only
	// marketplace sellers).
	//
	// Possible values:
	//   "CHECKOUT_ENROLLMENT_STATE_UNSPECIFIED" - Default enrollment state when
	// enrollment state is not specified.
	//   "INACTIVE" - Merchant has not enrolled into the program.
	//   "ENROLLED" - Merchant has enrolled into the program by providing either an
	// account level URL or checkout URLs as part of their feed.
	//   "OPTED_OUT" - Merchant has previously enrolled but opted out of the
	// program.
	EffectiveEnrollmentState string `json:"effectiveEnrollmentState,omitempty"`
	// EffectiveReviewState: Output only. The effective value of `review_state` for
	// a given merchant ID. If account level settings are present then this value
	// will be a copy of the account level settings. Otherwise, it will have the
	// value of the parent account (for only marketplace sellers).
	//
	// Possible values:
	//   "CHECKOUT_REVIEW_STATE_UNSPECIFIED" - Default review state when review
	// state is not specified.
	//   "IN_REVIEW" - Merchant provided URLs are being reviewed for data quality
	// issues.
	//   "APPROVED" - Merchant account has been approved. Indicates the data
	// quality checks have passed.
	//   "DISAPPROVED" - Merchant account has been disapproved due to data quality
	// issues.
	EffectiveReviewState string `json:"effectiveReviewState,omitempty"`
	// EffectiveUriSettings: Output only. The effective value of `uri_settings` for
	// a given merchant. If account level settings are present then this value will
	// be a copy of url settings. Otherwise, it will have the value of the parent
	// account (for only marketplace sellers).
	EffectiveUriSettings *UriSettings `json:"effectiveUriSettings,omitempty"`
	// EligibleDestinations: Optional. Required for the create operation. The
	// destinations (also known as Marketing methods
	// (https://support.google.com/merchants/answer/15130232)) to which the
	// checkout program applies. Valid destination values are `SHOPPING_ADS` and
	// `FREE_LISTINGS`.
	//
	// Possible values:
	//   "DESTINATION_ENUM_UNSPECIFIED" - Not specified.
	//   "SHOPPING_ADS" - [Shopping
	// ads](https://support.google.com/google-ads/answer/2454022).
	//   "DISPLAY_ADS" - [Display
	// ads](https://support.google.com/merchants/answer/6069387).
	//   "LOCAL_INVENTORY_ADS" - [Local inventory
	// ads](https://support.google.com/merchants/answer/3057972).
	//   "FREE_LISTINGS" - [Free
	// listings](https://support.google.com/merchants/answer/9199328).
	//   "FREE_LOCAL_LISTINGS" - [Free local product
	// listings](https://support.google.com/merchants/answer/9825611).
	//   "YOUTUBE_SHOPPING" - [YouTube
	// Shopping](https://support.google.com/merchants/answer/12362804).
	//   "YOUTUBE_SHOPPING_CHECKOUT" - Youtube shopping checkout.
	//   "YOUTUBE_AFFILIATE" - [Youtube
	// Affiliate](https://support.google.com/youtube/answer/13376398).
	//   "FREE_VEHICLE_LISTINGS" - [Free vehicle
	// listings](https://support.google.com/merchants/answer/11189169).
	//   "VEHICLE_ADS" - [Vehicle
	// ads](https://support.google.com/merchants/answer/11189169).
	//   "CLOUD_RETAIL" - [Cloud
	// retail](https://cloud.google.com/solutions/retail).
	//   "LOCAL_CLOUD_RETAIL" - [Local cloud
	// retail](https://cloud.google.com/solutions/retail).
	EligibleDestinations []string `json:"eligibleDestinations,omitempty"`
	// EnrollmentState: Output only. Reflects the merchant enrollment state in
	// `Checkout` program.
	//
	// Possible values:
	//   "CHECKOUT_ENROLLMENT_STATE_UNSPECIFIED" - Default enrollment state when
	// enrollment state is not specified.
	//   "INACTIVE" - Merchant has not enrolled into the program.
	//   "ENROLLED" - Merchant has enrolled into the program by providing either an
	// account level URL or checkout URLs as part of their feed.
	//   "OPTED_OUT" - Merchant has previously enrolled but opted out of the
	// program.
	EnrollmentState string `json:"enrollmentState,omitempty"`
	// Name: Identifier. The resource name of the program configuration settings.
	// Format: `accounts/{account}/programs/{program}/checkoutSettings`
	Name string `json:"name,omitempty"`
	// ReviewState: Output only. Reflects the merchant review state in `Checkout`
	// program. This is set based on the data quality reviews of the URL provided
	// by the merchant. A merchant with enrollment state as `ENROLLED` can be in
	// the following review states: `IN_REVIEW`, `APPROVED` or `DISAPPROVED`. A
	// merchant must be in an `enrollment_state` of `ENROLLED` before a review can
	// begin for the merchant.For more details, check the help center doc.
	//
	// Possible values:
	//   "CHECKOUT_REVIEW_STATE_UNSPECIFIED" - Default review state when review
	// state is not specified.
	//   "IN_REVIEW" - Merchant provided URLs are being reviewed for data quality
	// issues.
	//   "APPROVED" - Merchant account has been approved. Indicates the data
	// quality checks have passed.
	//   "DISAPPROVED" - Merchant account has been disapproved due to data quality
	// issues.
	ReviewState string `json:"reviewState,omitempty"`
	// UriSettings: URI settings for cart or checkout URL.
	UriSettings *UriSettings `json:"uriSettings,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "EffectiveEnrollmentState")
	// 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. "EffectiveEnrollmentState") 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 CheckoutSettings) MarshalJSON() ([]byte, error) {
	type NoMethod CheckoutSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ClaimHomepageRequest: Request message for the `ClaimHomepage` method.
type ClaimHomepageRequest struct {
	// Overwrite: Optional. When set to `true`, this option removes any existing
	// claim on the requested website from any other account to the account making
	// the request, effectively replacing the previous claim.
	Overwrite bool `json:"overwrite,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Overwrite") 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. "Overwrite") 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 ClaimHomepageRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ClaimHomepageRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ComparisonShopping: `ComparisonShopping` payload.
type ComparisonShopping struct {
}

// CreateAndConfigureAccountRequest: Request message for the
// `CreateAndConfigureAccount` method.
type CreateAndConfigureAccountRequest struct {
	// Account: Required. The account to be created.
	Account *Account `json:"account,omitempty"`
	// Service: Required. An account service between the account to be created and
	// the provider account is initialized as part of the creation. At least one
	// such service needs to be provided. Currently exactly one of these needs to
	// be `account_aggregation` and `accounts.createAndConfigure` method can be
	// used to create a sub-account under an existing advanced account through this
	// method. Additional `account_management` or `products_management` services
	// may be provided.
	Service []*AddAccountService `json:"service,omitempty"`
	// SetAlias: Optional. If a relationship is created with a provider, you can
	// set an alias for it with this field. The calling user must be an admin on
	// the provider to be able to set an alias.
	SetAlias []*SetAliasForRelationship `json:"setAlias,omitempty"`
	// User: Optional. Users to be added to the account.
	User []*AddUser `json:"user,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Account") 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. "Account") 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 CreateAndConfigureAccountRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateAndConfigureAccountRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateRegionRequest: Request message for the `CreateRegion` method.
type CreateRegionRequest struct {
	// Parent: Required. The account to create a region for. Format:
	// `accounts/{account}`
	Parent string `json:"parent,omitempty"`
	// Region: Required. The region to create.
	Region *Region `json:"region,omitempty"`
	// RegionId: Required. The identifier for the region, unique over all regions
	// of the same account.
	RegionId string `json:"regionId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Parent") 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. "Parent") 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 CreateRegionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateRegionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CustomerService: Customer service information.
type CustomerService struct {
	// Email: Optional. The email address where customer service may be reached.
	Email string `json:"email,omitempty"`
	// Phone: Optional. The phone number where customer service may be called.
	Phone *PhoneNumber `json:"phone,omitempty"`
	// Uri: Optional. The URI where customer service may be found.
	Uri string `json:"uri,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 CustomerService) MarshalJSON() ([]byte, error) {
	type NoMethod CustomerService
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CutoffConfig: Configs related to local delivery ends for the day.
type CutoffConfig struct {
	// LocalCutoffTime: Time that local delivery ends for the day.
	LocalCutoffTime *LocalCutoffTime `json:"localCutoffTime,omitempty"`
	// NoDeliveryPostCutoff: Businesses can opt-out of showing n+1 day local
	// delivery when they have a shipping service configured to n day local
	// delivery. For example, if the shipping service defines same-day delivery,
	// and it's past the cut-off, setting this field to `true` results in the
	// calculated shipping service rate returning `NO_DELIVERY_POST_CUTOFF`. In the
	// same example, setting this field to `false` results in the calculated
	// shipping time being one day. This is only for local delivery.
	NoDeliveryPostCutoff bool `json:"noDeliveryPostCutoff,omitempty"`
	// StoreCloseOffsetHours: Only valid with local delivery fulfillment.
	// Represents cutoff time as the number of hours before store closing. Mutually
	// exclusive with `local_cutoff_time`.
	StoreCloseOffsetHours int64 `json:"storeCloseOffsetHours,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "LocalCutoffTime") 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. "LocalCutoffTime") 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 CutoffConfig) MarshalJSON() ([]byte, error) {
	type NoMethod CutoffConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CutoffTime: Business days cutoff time definition.
type CutoffTime struct {
	// Hour: Required. Hour of the cutoff time until which an order has to be
	// placed to be processed in the same day.
	Hour int64 `json:"hour,omitempty"`
	// Minute: Required. Minute of the cutoff time until which an order has to be
	// placed to be processed in the same day.
	Minute int64 `json:"minute,omitempty"`
	// TimeZone: Required. Timezone identifier
	// (https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids)
	// For example "Europe/Zurich".
	TimeZone string `json:"timeZone,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Hour") 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. "Hour") 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 CutoffTime) MarshalJSON() ([]byte, error) {
	type NoMethod CutoffTime
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Date: Represents a whole or partial calendar date, such as a birthday. The
// time of day and time zone are either specified elsewhere or are
// insignificant. The date is relative to the Gregorian Calendar. This can
// represent one of the following: * A full date, with non-zero year, month,
// and day values. * A month and day, with a zero year (for example, an
// anniversary). * A year on its own, with a zero month and a zero day. * A
// year and month, with a zero day (for example, a credit card expiration
// date). Related types: * google.type.TimeOfDay * google.type.DateTime *
// google.protobuf.Timestamp
type Date struct {
	// Day: Day of a month. Must be from 1 to 31 and valid for the year and month,
	// or 0 to specify a year by itself or a year and month where the day isn't
	// significant.
	Day int64 `json:"day,omitempty"`
	// Month: Month of a year. Must be from 1 to 12, or 0 to specify a year without
	// a month and day.
	Month int64 `json:"month,omitempty"`
	// Year: Year of the date. Must be from 1 to 9999, or 0 to specify a date
	// without a year.
	Year int64 `json:"year,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Day") 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. "Day") 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 Date) MarshalJSON() ([]byte, error) {
	type NoMethod Date
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DeleteRegionRequest: Request message for the `DeleteRegion` method.
type DeleteRegionRequest struct {
	// Name: Required. The name of the region to delete. Format:
	// `accounts/{account}/regions/{region}`
	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 DeleteRegionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod DeleteRegionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DeliveryTime: Time spent in various aspects from order to the delivery of
// the product.
type DeliveryTime struct {
	// CutoffTime: Business days cutoff time definition. If not configured the
	// cutoff time will be defaulted to 8AM PST.
	CutoffTime *CutoffTime `json:"cutoffTime,omitempty"`
	// HandlingBusinessDayConfig: The business days during which orders can be
	// handled. If not provided, Monday to Friday business days will be assumed.
	HandlingBusinessDayConfig *BusinessDayConfig `json:"handlingBusinessDayConfig,omitempty"`
	// MaxHandlingDays: Maximum number of business days spent before an order is
	// shipped. 0 means same day shipped, 1 means next day shipped. Must be greater
	// than or equal to `min_handling_days`. 'min_handling_days' and
	// 'max_handling_days' should be either set or not set at the same time.
	MaxHandlingDays int64 `json:"maxHandlingDays,omitempty"`
	// MaxTransitDays: Maximum number of business days that is spent in transit. 0
	// means same day delivery, 1 means next day delivery. Must be greater than or
	// equal to `min_transit_days`.
	MaxTransitDays int64 `json:"maxTransitDays,omitempty"`
	// MinHandlingDays: Minimum number of business days spent before an order is
	// shipped. 0 means same day shipped, 1 means next day shipped.
	// 'min_handling_days' and 'max_handling_days' should be either set or not set
	// at the same time.
	MinHandlingDays int64 `json:"minHandlingDays,omitempty"`
	// MinTransitDays: Minimum number of business days that is spent in transit. 0
	// means same day delivery, 1 means next day delivery. Either
	// `min_transit_days`, `max_transit_days` or `transit_time_table` must be set,
	// but not both.
	MinTransitDays int64 `json:"minTransitDays,omitempty"`
	// TransitBusinessDayConfig: The business days during which orders can be
	// in-transit. If not provided, Monday to Friday business days will be assumed.
	TransitBusinessDayConfig *BusinessDayConfig `json:"transitBusinessDayConfig,omitempty"`
	// TransitTimeTable: Transit time table, number of business days spent in
	// transit based on row and column dimensions. Either `min_transit_days`,
	// `max_transit_days` or `transit_time_table` can be set, but not both.
	TransitTimeTable *TransitTable `json:"transitTimeTable,omitempty"`
	// WarehouseBasedDeliveryTimes: Optional. Indicates that the delivery time
	// should be calculated per warehouse (shipping origin location) based on the
	// settings of the selected carrier. When set, no other transit time related
	// field in delivery time should be set.
	WarehouseBasedDeliveryTimes []*WarehouseBasedDeliveryTime `json:"warehouseBasedDeliveryTimes,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CutoffTime") 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. "CutoffTime") 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 DeliveryTime) MarshalJSON() ([]byte, error) {
	type NoMethod DeliveryTime
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DeveloperRegistration: Represents a developer registration owned by a
// Merchant account.
type DeveloperRegistration struct {
	// GcpIds: Output only. The GCP ids attached to this developer registration
	GcpIds []string `json:"gcpIds,omitempty"`
	// Name: Identifier. The `name` (ID) of the developer registration. Generated
	// by the Content API upon creation of a new `DeveloperRegistration`. The
	// `account` represents the merchant ID of the merchant that owns the
	// registration.
	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. "GcpIds") 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. "GcpIds") 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 DeveloperRegistration) MarshalJSON() ([]byte, error) {
	type NoMethod DeveloperRegistration
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DisableProgramRequest: Request message for the DisableProgram method.
type DisableProgramRequest struct {
}

// Distance: Maximum delivery radius. This is only required for the local
// delivery shipment type.
type Distance struct {
	// Unit: Unit can differ based on country, it is parameterized to include miles
	// and kilometers.
	//
	// Possible values:
	//   "UNIT_UNSPECIFIED" - Unit unspecified
	//   "MILES" - Unit in miles
	//   "KILOMETERS" - Unit in kilometers
	Unit string `json:"unit,omitempty"`
	// Value: Integer value of distance.
	Value int64 `json:"value,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "Unit") 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. "Unit") 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 Distance) MarshalJSON() ([]byte, error) {
	type NoMethod Distance
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// EmailPreferences: The categories of notifications the user opted into /
// opted out of. The email preferences do not include mandatory announcements
// as users can't opt out of them.
type EmailPreferences struct {
	// Name: Identifier. The name of the EmailPreferences. The endpoint is only
	// supported for the authenticated user.
	Name string `json:"name,omitempty"`
	// NewsAndTips: Optional. Updates on new features, tips and best practices.
	//
	// Possible values:
	//   "OPT_IN_STATE_UNSPECIFIED" - Opt-in status is not specified.
	//   "OPTED_OUT" - User has opted out of receiving this type of email.
	//   "OPTED_IN" - User has opted in to receiving this type of email.
	//   "UNCONFIRMED" - User has opted in to receiving this type of email and the
	// confirmation email has been sent, but user has not yet confirmed the opt in
	// (applies only to certain countries).
	NewsAndTips string `json:"newsAndTips,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// 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 EmailPreferences) MarshalJSON() ([]byte, error) {
	type NoMethod EmailPreferences
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Empty: 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 Empty struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// EnableProgramRequest: Request message for the EnableProgram method.
type EnableProgramRequest struct {
}

// FindLfpProvidersResponse: Response message for the FindLfpProviders method.
type FindLfpProvidersResponse struct {
	// LfpProviders: The LFP providers from the specified merchant in the specified
	// country.
	LfpProviders []*LfpProvider `json:"lfpProviders,omitempty"`
	// 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"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "LfpProviders") 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. "LfpProviders") 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 FindLfpProvidersResponse) MarshalJSON() ([]byte, error) {
	type NoMethod FindLfpProvidersResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GbpAccount: Collection of information related to a Google Business Profile
// (GBP) account.
type GbpAccount struct {
	// GbpAccountId: The id of the GBP account.
	GbpAccountId string `json:"gbpAccountId,omitempty"`
	// GbpAccountName: The name of the Business Profile. For personal accounts:
	// Email id of the owner. For Business accounts: Name of the Business Account.
	GbpAccountName string `json:"gbpAccountName,omitempty"`
	// ListingCount: Number of listings under this account.
	ListingCount int64 `json:"listingCount,omitempty,string"`
	// Name: Identifier. The resource name of the GBP account. Format:
	// `accounts/{account}/gbpAccount/{gbp_account}`
	Name string `json:"name,omitempty"`
	// Type: The type of the Business Profile.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Default value. This value is unused.
	//   "USER" - The GBP account is a user account.
	//   "BUSINESS_ACCOUNT" - The GBP account is a business account.
	Type string `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "GbpAccountId") 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. "GbpAccountId") 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 GbpAccount) MarshalJSON() ([]byte, error) {
	type NoMethod GbpAccount
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GeoTargetArea: A list of geotargets that defines the region area.
type GeoTargetArea struct {
	// GeotargetCriteriaIds: Required. A non-empty list of location IDs
	// (https://developers.google.com/adwords/api/docs/appendix/geotargeting). They
	// must all be of the same location type (for example, state).
	GeotargetCriteriaIds googleapi.Int64s `json:"geotargetCriteriaIds,omitempty"`
	// ForceSendFields is a list of field names (e.g. "GeotargetCriteriaIds") 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. "GeotargetCriteriaIds") 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 GeoTargetArea) MarshalJSON() ([]byte, error) {
	type NoMethod GeoTargetArea
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GetAccountForGcpRegistrationResponse: Response message for the
// GetAccountForGcpRegistration method.
type GetAccountForGcpRegistrationResponse struct {
	// Name: The name of the merchant account id that the GCP is registered with.
	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. "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 GetAccountForGcpRegistrationResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GetAccountForGcpRegistrationResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Handshake: The current status of establishing of the service. (for example,
// pending approval or approved).
type Handshake struct {
	// Actor: Output only. The most recent account to modify the account service's
	// `approval_status`.
	//
	// Possible values:
	//   "ACTOR_UNSPECIFIED" - Unspecified actor.
	//   "ACCOUNT" - The last change was done by the account who has this service.
	//   "OTHER_PARTY" - The last change was done by the other party who this
	// service points to.
	Actor string `json:"actor,omitempty"`
	// ApprovalState: Output only. The approval state of this handshake.
	//
	// Possible values:
	//   "APPROVAL_STATE_UNSPECIFIED" - Unspecified approval status.
	//   "PENDING" - The service was proposed and is waiting to be confirmed.
	//   "ESTABLISHED" - Both parties have confirmed the service.
	//   "REJECTED" - The service proposal was rejected.
	ApprovalState string `json:"approvalState,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Actor") 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. "Actor") 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 Handshake) MarshalJSON() ([]byte, error) {
	type NoMethod Handshake
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Headers: A non-empty list of row or column headers for a table. Exactly one
// of `prices`, `weights`, `num_items`, `postal_code_group_names`, or
// `location` must be set.
type Headers struct {
	// Locations: Required. A list of location ID sets. Must be non-empty. Can only
	// be set if all other fields are not set.
	Locations []*LocationIdSet `json:"locations,omitempty"`
	// NumberOfItems: Required. A list of inclusive number of items upper bounds.
	// The last value can be "infinity". For example `["10", "50", "infinity"]`
	// represents the headers "<= 10 items", "<= 50 items", and "> 50 items". Must
	// be non-empty. Can only be set if all other fields are not set.
	NumberOfItems []string `json:"numberOfItems,omitempty"`
	// PostalCodeGroupNames: Required. A list of postal group names. The last value
	// can be "all other locations". Example: `["zone 1", "zone 2", "all other
	// locations"]`. The referred postal code groups must match the delivery
	// country of the service. Must be non-empty. Can only be set if all other
	// fields are not set.
	PostalCodeGroupNames []string `json:"postalCodeGroupNames,omitempty"`
	// Prices: Required. A list of inclusive order price upper bounds. The last
	// price's value can be infinity by setting price amount_micros = -1. For
	// example `[{"amount_micros": 10000000, "currency_code": "USD"},
	// {"amount_micros": 500000000, "currency_code": "USD"}, {"amount_micros": -1,
	// "currency_code": "USD"}]` represents the headers "<= $10", "<= $500", and ">
	// $500". All prices within a service must have the same currency. Must be
	// non-empty. Must be positive except -1. Can only be set if all other fields
	// are not set.
	Prices []*Price `json:"prices,omitempty"`
	// Weights: Required. A list of inclusive order weight upper bounds. The last
	// weight's value can be infinity by setting price amount_micros = -1. For
	// example `[{"amount_micros": 10000000, "unit": "kg"}, {"amount_micros":
	// 50000000, "unit": "kg"}, {"amount_micros": -1, "unit": "kg"}]` represents
	// the headers "<= 10kg", "<= 50kg", and "> 50kg". All weights within a service
	// must have the same unit. Must be non-empty. Must be positive except -1. Can
	// only be set if all other fields are not set.
	Weights []*Weight `json:"weights,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Locations") 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. "Locations") 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 Headers) MarshalJSON() ([]byte, error) {
	type NoMethod Headers
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Homepage: The `Homepage` message represents a business's store homepage
// within the system. A business's homepage is the primary domain where
// customers interact with their store. The homepage can be claimed and
// verified as a proof of ownership and allows the business to unlock features
// that require a verified website. For more information, see Understanding
// online store URL verification
// (//support.google.com/merchants/answer/176793).
type Homepage struct {
	// Claimed: Output only. Whether the homepage is claimed. See
	// https://support.google.com/merchants/answer/176793.
	Claimed bool `json:"claimed,omitempty"`
	// Name: Identifier. The resource name of the store's homepage. Format:
	// `accounts/{account}/homepage`
	Name string `json:"name,omitempty"`
	// Uri: Required. The URI (typically a URL) of the store's homepage.
	Uri string `json:"uri,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Claimed") 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. "Claimed") 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 Homepage) MarshalJSON() ([]byte, error) {
	type NoMethod Homepage
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// IdentityAttribute: All information related to an identity attribute.
type IdentityAttribute struct {
	// IdentityDeclaration: Required. The declaration of identity for this
	// attribute.
	//
	// Possible values:
	//   "IDENTITY_DECLARATION_UNSPECIFIED" - Default value indicating that no
	// selection was made.
	//   "SELF_IDENTIFIES_AS" - Indicates that the account identifies with the
	// attribute.
	//   "DOES_NOT_SELF_IDENTIFY_AS" - Indicates that the account does not identify
	// with the attribute.
	IdentityDeclaration string `json:"identityDeclaration,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IdentityDeclaration") 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. "IdentityDeclaration") 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 IdentityAttribute) MarshalJSON() ([]byte, error) {
	type NoMethod IdentityAttribute
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ImageImprovementsAccountLevelSettings: Settings for the Automatic Image
// Improvements.
type ImageImprovementsAccountLevelSettings struct {
	// AllowAutomaticImageImprovements: Enables automatic image improvements.
	AllowAutomaticImageImprovements bool `json:"allowAutomaticImageImprovements,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "AllowAutomaticImageImprovements") 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. "AllowAutomaticImageImprovements")
	// 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 ImageImprovementsAccountLevelSettings) MarshalJSON() ([]byte, error) {
	type NoMethod ImageImprovementsAccountLevelSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Impact: The impact of the issue on a region.
type Impact struct {
	// RegionCode: The CLDR region code (https://cldr.unicode.org/) where this
	// issue applies.
	RegionCode string `json:"regionCode,omitempty"`
	// Severity: The severity of the issue on the destination and region.
	//
	// Possible values:
	//   "SEVERITY_UNSPECIFIED" - The severity is unknown.
	//   "CRITICAL" - The issue causes offers to not serve.
	//   "ERROR" - The issue might affect offers (in the future) or might be an
	// indicator of issues with offers.
	//   "SUGGESTION" - The issue is a suggestion for improvement.
	Severity string `json:"severity,omitempty"`
	// ForceSendFields is a list of field names (e.g. "RegionCode") 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. "RegionCode") 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 Impact) MarshalJSON() ([]byte, error) {
	type NoMethod Impact
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ImpactedDestination: The impact of the issue on a destination.
type ImpactedDestination struct {
	// Impacts: The (negative) impact for various regions on the given destination.
	Impacts []*Impact `json:"impacts,omitempty"`
	// ReportingContext: The impacted reporting context.
	//
	// Possible values:
	//   "REPORTING_CONTEXT_ENUM_UNSPECIFIED" - Not specified.
	//   "SHOPPING_ADS" - [Shopping
	// ads](https://support.google.com/merchants/answer/6149970).
	//   "DISCOVERY_ADS" - Deprecated: Use `DEMAND_GEN_ADS` instead. [Discovery and
	// Demand Gen ads](https://support.google.com/merchants/answer/13389785).
	//   "DEMAND_GEN_ADS" - [Demand Gen
	// ads](https://support.google.com/merchants/answer/13389785).
	//   "DEMAND_GEN_ADS_DISCOVER_SURFACE" - [Demand Gen ads on Discover
	// surface](https://support.google.com/merchants/answer/13389785).
	//   "VIDEO_ADS" - [Video
	// ads](https://support.google.com/google-ads/answer/6340491).
	//   "DISPLAY_ADS" - [Display
	// ads](https://support.google.com/merchants/answer/6069387).
	//   "LOCAL_INVENTORY_ADS" - [Local inventory
	// ads](https://support.google.com/merchants/answer/3271956).
	//   "VEHICLE_INVENTORY_ADS" - [Vehicle inventory
	// ads](https://support.google.com/merchants/answer/11544533).
	//   "FREE_LISTINGS" - [Free product
	// listings](https://support.google.com/merchants/answer/9199328).
	//   "FREE_LISTINGS_UCP_CHECKOUT" - [Free product listings on UCP
	// checkout](https://developers.google.com/merchant/ucp).
	//   "FREE_LOCAL_LISTINGS" - [Free local product
	// listings](https://support.google.com/merchants/answer/9825611).
	//   "FREE_LOCAL_VEHICLE_LISTINGS" - [Free local vehicle
	// listings](https://support.google.com/merchants/answer/11544533).
	//   "YOUTUBE_AFFILIATE" - [Youtube
	// Affiliate](https://support.google.com/youtube/answer/13376398).
	//   "YOUTUBE_SHOPPING" - [YouTube
	// Shopping](https://support.google.com/merchants/answer/13478370).
	//   "CLOUD_RETAIL" - [Cloud
	// retail](https://cloud.google.com/solutions/retail).
	//   "LOCAL_CLOUD_RETAIL" - [Local cloud
	// retail](https://cloud.google.com/solutions/retail).
	//   "PRODUCT_REVIEWS" - [Product
	// Reviews](https://support.google.com/merchants/answer/14620732).
	//   "MERCHANT_REVIEWS" - [Merchant
	// Reviews](https://developers.google.com/merchant-review-feeds).
	//   "YOUTUBE_CHECKOUT" - YouTube Checkout .
	ReportingContext string `json:"reportingContext,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Impacts") 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. "Impacts") 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 ImpactedDestination) MarshalJSON() ([]byte, error) {
	type NoMethod ImpactedDestination
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InStock: Collection of information related to InStock.
type InStock struct {
	// State: Output only. The state of the in-stock serving.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	State string `json:"state,omitempty"`
	// Uri: Optional. Product landing page URI. It is only used for the review of
	// MHLSF in-stock serving. This URI domain should match with the business's
	// homepage. Required to be empty if the lsf_type is GHLSF, and required when
	// the lsf_type is MHLSF_FULL or MHLSF_BASIC.
	Uri string `json:"uri,omitempty"`
	// ForceSendFields is a list of field names (e.g. "State") 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. "State") 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 InStock) MarshalJSON() ([]byte, error) {
	type NoMethod InStock
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InventoryVerification: Collection of information related to inventory
// verification
// (https://support.google.com/merchants/answer/14684499?ref_topic=15145634&sjid=6892280366904591178-NC).
type InventoryVerification struct {
	// Contact: Required. The name of the contact for the inventory verification
	// process.
	Contact string `json:"contact,omitempty"`
	// ContactEmail: Required. The email address of the contact for the inventory
	// verification process.
	ContactEmail string `json:"contactEmail,omitempty"`
	// ContactState: Output only. The state of the contact verification.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	ContactState string `json:"contactState,omitempty"`
	// State: Output only. The state of the inventory verification process.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTION_REQUIRED" - When the merchant needs to initiate the inventory
	// verification process. The next state is INACTIVE.
	//   "INACTIVE" - When the merchant is ready to request inventory verification.
	//   "RUNNING" - The inventory verification process is running. If the merchant
	// is rejected, the next state is INACTIVE.
	//   "SUCCEEDED" - The inventory verification process succeeded.
	//   "SUSPENDED" - When merchant fails the inventory verification process and
	// all attempts are exhausted.
	State string `json:"state,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Contact") 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. "Contact") 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 InventoryVerification) MarshalJSON() ([]byte, error) {
	type NoMethod InventoryVerification
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ItemUpdatesAccountLevelSettings: Settings for the Automatic Item Updates.
type ItemUpdatesAccountLevelSettings struct {
	// AllowAvailabilityUpdates: If availability updates are enabled, any previous
	// availability values get overwritten if Google finds an out-of-stock
	// annotation on the offer's page. If additionally
	// `allow_strict_availability_updates` field is set to true, values get
	// overwritten if Google finds an in-stock annotation on the offer’s page.
	AllowAvailabilityUpdates bool `json:"allowAvailabilityUpdates,omitempty"`
	// AllowConditionUpdates: If condition updates are enabled, Google always
	// updates item condition with the condition detected from the details of your
	// product.
	AllowConditionUpdates bool `json:"allowConditionUpdates,omitempty"`
	// AllowPriceUpdates: If price updates are enabled, Google always updates the
	// active price with the crawled information.
	AllowPriceUpdates bool `json:"allowPriceUpdates,omitempty"`
	// AllowStrictAvailabilityUpdates: If `allow_availability_updates` is enabled,
	// items are automatically updated in all your Shopping target countries. By
	// default, availability updates will only be applied to items that are 'out of
	// stock' on your website but 'in stock' on Shopping. Set this to true to also
	// update items that are 'in stock' on your website, but 'out of stock' on
	// Google Shopping. In order for this field to have an effect, you must also
	// set `allow_availability_updates`.
	AllowStrictAvailabilityUpdates bool `json:"allowStrictAvailabilityUpdates,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AllowAvailabilityUpdates")
	// 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. "AllowAvailabilityUpdates") 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 ItemUpdatesAccountLevelSettings) MarshalJSON() ([]byte, error) {
	type NoMethod ItemUpdatesAccountLevelSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LatLng: An object that represents a latitude/longitude pair. This is
// expressed as a pair of doubles to represent degrees latitude and degrees
// longitude. Unless specified otherwise, this object must conform to the WGS84
// standard. Values must be within normalized ranges.
type LatLng struct {
	// Latitude: The latitude in degrees. It must be in the range [-90.0, +90.0].
	Latitude float64 `json:"latitude,omitempty"`
	// Longitude: The longitude in degrees. It must be in the range [-180.0,
	// +180.0].
	Longitude float64 `json:"longitude,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Latitude") 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. "Latitude") 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 LatLng) MarshalJSON() ([]byte, error) {
	type NoMethod LatLng
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

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

// LfpLink: Collection of information related to the LFP link.
type LfpLink struct {
	// ExternalAccountId: Required. The account ID by which this merchant is known
	// to the LFP provider.
	ExternalAccountId string `json:"externalAccountId,omitempty"`
	// LfpProvider: Required. The resource name of the LFP provider. Format:
	// `lfpProviders/{lfp_provider}`
	LfpProvider string `json:"lfpProvider,omitempty"`
	// State: Output only. The state of the LFP link.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	State string `json:"state,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExternalAccountId") 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. "ExternalAccountId") 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 LfpLink) MarshalJSON() ([]byte, error) {
	type NoMethod LfpLink
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LfpProvider: Collection of information related to a Local Feed Partnership
// (LFP) provider.
type LfpProvider struct {
	// DisplayName: The display name of the LFP provider.
	DisplayName string `json:"displayName,omitempty"`
	// Name: Identifier. The resource name of the LFP provider. Format:
	// `accounts/{account}/omnichannelSettings/{omnichannel_setting}/lfpProviders/{l
	// fp_provider}`
	Name string `json:"name,omitempty"`
	// RegionCode: Output only. Region code defined by CLDR
	// (https://cldr.unicode.org/).
	RegionCode string `json:"regionCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DisplayName") 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. "DisplayName") 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 LfpProvider) MarshalJSON() ([]byte, error) {
	type NoMethod LfpProvider
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LinkGbpAccountRequest: Request message for the LinkGbpAccount method.
type LinkGbpAccountRequest struct {
	// GbpEmail: Required. The email address of the Business Profile account.
	GbpEmail string `json:"gbpEmail,omitempty"`
	// ForceSendFields is a list of field names (e.g. "GbpEmail") 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. "GbpEmail") 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 LinkGbpAccountRequest) MarshalJSON() ([]byte, error) {
	type NoMethod LinkGbpAccountRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LinkGbpAccountResponse: Response message for the LinkGbpAccount method.
type LinkGbpAccountResponse struct {
	// Response: Empty response.
	Response *Empty `json:"response,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Response") 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. "Response") 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 LinkGbpAccountResponse) MarshalJSON() ([]byte, error) {
	type NoMethod LinkGbpAccountResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LinkLfpProviderRequest: Request message for the LinkLfpProvider method.
type LinkLfpProviderRequest struct {
	// ExternalAccountId: Required. The external account ID by which this merchant
	// is known to the LFP provider.
	ExternalAccountId string `json:"externalAccountId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExternalAccountId") 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. "ExternalAccountId") 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 LinkLfpProviderRequest) MarshalJSON() ([]byte, error) {
	type NoMethod LinkLfpProviderRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LinkLfpProviderResponse: Response message for the LinkLfpProvider method.
type LinkLfpProviderResponse struct {
	// Response: Empty response.
	Response *Empty `json:"response,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Response") 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. "Response") 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 LinkLfpProviderResponse) MarshalJSON() ([]byte, error) {
	type NoMethod LinkLfpProviderResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListAccountIssuesResponse: Response message for the `ListAccountIssues`
// method.
type ListAccountIssuesResponse struct {
	// AccountIssues: The issues from the specified account.
	AccountIssues []*AccountIssue `json:"accountIssues,omitempty"`
	// 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"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AccountIssues") 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. "AccountIssues") 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 ListAccountIssuesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListAccountIssuesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListAccountRelationshipsResponse: Response after trying to list account
// relationships.
type ListAccountRelationshipsResponse struct {
	// AccountRelationships: The account relationships that match your filter.
	AccountRelationships []*AccountRelationship `json:"accountRelationships,omitempty"`
	// NextPageToken: A page token. You can send the `page_token` to get the next
	// page. Only included in the `list` response if there are more pages.
	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. "AccountRelationships") 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. "AccountRelationships") 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 ListAccountRelationshipsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListAccountRelationshipsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListAccountServicesResponse: Response after trying to list account services.
type ListAccountServicesResponse struct {
	// AccountServices: The account services that match your filter.
	AccountServices []*AccountService `json:"accountServices,omitempty"`
	// NextPageToken: A page token. You can send the `page_token` to get the next
	// page. Only included in the `list` response if there are more pages.
	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. "AccountServices") 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. "AccountServices") 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 ListAccountServicesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListAccountServicesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListAccountsResponse: Response message for the `accounts.list` method.
type ListAccountsResponse struct {
	// Accounts: The accounts matching the `ListAccountsRequest`.
	Accounts []*Account `json:"accounts,omitempty"`
	// 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"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Accounts") 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. "Accounts") 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 ListAccountsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListAccountsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListGbpAccountsResponse: Response message for the ListGbpAccounts method.
type ListGbpAccountsResponse struct {
	// GbpAccounts: The GBP accounts from the specified merchant in the specified
	// country.
	GbpAccounts []*GbpAccount `json:"gbpAccounts,omitempty"`
	// 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"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "GbpAccounts") 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. "GbpAccounts") 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 ListGbpAccountsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListGbpAccountsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListOmnichannelSettingsResponse: Response message for the
// ListOmnichannelSettings method.
type ListOmnichannelSettingsResponse 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"`
	// OmnichannelSettings: The omnichannel settings from the specified merchant.
	OmnichannelSettings []*OmnichannelSetting `json:"omnichannelSettings,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 ListOmnichannelSettingsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListOmnichannelSettingsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListOnlineReturnPoliciesResponse: Response message for the
// `ListOnlineReturnPolicies` method.
type ListOnlineReturnPoliciesResponse struct {
	// NextPageToken: A token, which can be sent as `pageToken` to retrieve the
	// next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// OnlineReturnPolicies: The retrieved return policies.
	OnlineReturnPolicies []*OnlineReturnPolicy `json:"onlineReturnPolicies,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 ListOnlineReturnPoliciesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListOnlineReturnPoliciesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListProgramsResponse: Response message for the ListPrograms method.
type ListProgramsResponse struct {
	// NextPageToken: A token that 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"`
	// Programs: The programs for the given account.
	Programs []*Program `json:"programs,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 ListProgramsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListProgramsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListRegionsResponse: Response message for the `ListRegions` method.
type ListRegionsResponse 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"`
	// Regions: The regions from the specified business.
	Regions []*Region `json:"regions,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 ListRegionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListRegionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListSubAccountsResponse: Response message for the `ListSubAccounts` method.
type ListSubAccountsResponse struct {
	// Accounts: The accounts for which the given parent account is an aggregator.
	Accounts []*Account `json:"accounts,omitempty"`
	// 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"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Accounts") 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. "Accounts") 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 ListSubAccountsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListSubAccountsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListUsersResponse: Response message for the `ListUsers` method.
type ListUsersResponse 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"`
	// Users: The users from the specified account.
	Users []*User `json:"users,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 ListUsersResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListUsersResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LocalCutoffTime: Time that local delivery ends for the day.
type LocalCutoffTime struct {
	// Hour: Hour local delivery orders must be placed by to process the same day.
	Hour int64 `json:"hour,omitempty,string"`
	// Minute: Minute local delivery orders must be placed by to process the same
	// day.
	Minute int64 `json:"minute,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "Hour") 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. "Hour") 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 LocalCutoffTime) MarshalJSON() ([]byte, error) {
	type NoMethod LocalCutoffTime
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LocalListingManagement: `LocalListingManagement` payload.
type LocalListingManagement struct {
}

// LocationIdSet: A list of location ID sets. Must be non-empty. Can only be
// set if all other fields are not set.
type LocationIdSet struct {
	// LocationIds: Required. A non-empty list of location IDs
	// (https://developers.google.com/adwords/api/docs/appendix/geotargeting). They
	// must all be of the same location type (For example, state).
	LocationIds []string `json:"locationIds,omitempty"`
	// ForceSendFields is a list of field names (e.g. "LocationIds") 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. "LocationIds") 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 LocationIdSet) MarshalJSON() ([]byte, error) {
	type NoMethod LocationIdSet
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LoyaltyProgram: Loyalty program
// (https://support.google.com/merchants/answer/12922446) provided by a
// business.
type LoyaltyProgram struct {
	// LoyaltyProgramTiers: Optional. Loyalty program tier of this shipping
	// service.
	LoyaltyProgramTiers []*LoyaltyProgramTiers `json:"loyaltyProgramTiers,omitempty"`
	// ProgramLabel: This is the loyalty program label set in your loyalty program
	// settings in Merchant Center. This sub-attribute allows Google to map your
	// loyalty program to eligible offers.
	ProgramLabel string `json:"programLabel,omitempty"`
	// ForceSendFields is a list of field names (e.g. "LoyaltyProgramTiers") 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. "LoyaltyProgramTiers") 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 LoyaltyProgram) MarshalJSON() ([]byte, error) {
	type NoMethod LoyaltyProgram
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LoyaltyProgramTiers: Subset of a business's loyalty program.
type LoyaltyProgramTiers struct {
	// TierLabel: The tier label [tier_label] sub-attribute differentiates offer
	// level benefits between each tier. This value is also set in your program
	// settings in Merchant Center, and is required for data source changes even if
	// your loyalty program only has 1 tier.
	TierLabel string `json:"tierLabel,omitempty"`
	// ForceSendFields is a list of field names (e.g. "TierLabel") 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. "TierLabel") 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 LoyaltyProgramTiers) MarshalJSON() ([]byte, error) {
	type NoMethod LoyaltyProgramTiers
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MinimumOrderValueTable: Table of per store minimum order values for the
// pickup fulfillment type.
type MinimumOrderValueTable struct {
	// StoreCodeSetWithMovs: Required. A list of store code sets sharing the same
	// minimum order value (MOV). At least two sets are required and the last one
	// must be empty, which signifies 'MOV for all other stores'. Each store code
	// can only appear once across all the sets. All prices within a service must
	// have the same currency.
	StoreCodeSetWithMovs []*StoreCodeSetWithMov `json:"storeCodeSetWithMovs,omitempty"`
	// ForceSendFields is a list of field names (e.g. "StoreCodeSetWithMovs") 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. "StoreCodeSetWithMovs") 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 MinimumOrderValueTable) MarshalJSON() ([]byte, error) {
	type NoMethod MinimumOrderValueTable
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// OmnichannelSetting: Collection of information related to the omnichannel
// settings of a merchant.
type OmnichannelSetting struct {
	// About: Optional. The about page URI and state for this country.
	About *About `json:"about,omitempty"`
	// InStock: Optional. The InStock URI and state for this country.
	InStock *InStock `json:"inStock,omitempty"`
	// InventoryVerification: Optional. The inventory verification contact and
	// state for this country.
	InventoryVerification *InventoryVerification `json:"inventoryVerification,omitempty"`
	// LfpLink: Output only. The established link to a LFP provider.
	LfpLink *LfpLink `json:"lfpLink,omitempty"`
	// LsfType: Required. The Local Store Front type for this country.
	//
	// Possible values:
	//   "LSF_TYPE_UNSPECIFIED" - Default value. This value is unused.
	//   "GHLSF" - Google-Hosted Local Store Front. Check the [HC
	// article](https://support.google.com/merchants/answer/14869424) for more
	// details.
	//   "MHLSF_BASIC" - Merchant-Hosted Local Store Front Basic. Check the [HC
	// article](https://support.google.com/merchants/answer/14615867) for more
	// details.
	//   "MHLSF_FULL" - Merchant-Hosted Local Store Front Full. Check the [HC
	// article](https://support.google.com/merchants/answer/14617076) for more
	// details.
	LsfType string `json:"lsfType,omitempty"`
	// Name: Identifier. The resource name of the omnichannel setting. Format:
	// `accounts/{account}/omnichannelSettings/{omnichannel_setting}`
	Name string `json:"name,omitempty"`
	// Odo: Optional. The On Display to Order (ODO) policy URI and state for this
	// country.
	Odo *OnDisplayToOrder `json:"odo,omitempty"`
	// Pickup: Optional. The Pickup URI and state for this country.
	Pickup *Pickup `json:"pickup,omitempty"`
	// RegionCode: Required. Immutable. Region code defined by CLDR
	// (https://cldr.unicode.org/). Must be provided in the Create method, and is
	// immutable.
	RegionCode string `json:"regionCode,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "About") 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. "About") 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 OmnichannelSetting) MarshalJSON() ([]byte, error) {
	type NoMethod OmnichannelSetting
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// OnDisplayToOrder: Collection of information related to the on display to
// order (ODO
// (https://support.google.com/merchants/answer/14615056?ref_topic=15145747&sjid=6892280366904591178-NC)).
type OnDisplayToOrder struct {
	// State: Output only. The state of the URI.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	State string `json:"state,omitempty"`
	// Uri: Required. The on display to order (ODO) policy URI.
	Uri string `json:"uri,omitempty"`
	// ForceSendFields is a list of field names (e.g. "State") 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. "State") 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 OnDisplayToOrder) MarshalJSON() ([]byte, error) {
	type NoMethod OnDisplayToOrder
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// OnlineReturnPolicy: Online return policy
// (https://support.google.com/merchants/answer/10220642) object. This is
// currently used to represent return policies for ads and free listings
// programs.
type OnlineReturnPolicy struct {
	// AcceptDefectiveOnly: Optional. This field specifies if business only accepts
	// defective products for returns.
	AcceptDefectiveOnly bool `json:"acceptDefectiveOnly,omitempty"`
	// AcceptExchange: Optional. This field specifies if business allows customers
	// to exchange products.
	AcceptExchange bool `json:"acceptExchange,omitempty"`
	// Countries: Required. Immutable. The countries of sale where the return
	// policy applies. The values must be a valid 2 letter ISO 3166 code.
	Countries []string `json:"countries,omitempty"`
	// ItemConditions: Optional. The item conditions accepted for returns must not
	// be empty unless the type of return policy is 'noReturns'.
	//
	// Possible values:
	//   "ITEM_CONDITION_UNSPECIFIED" - Default value. This value is unused.
	//   "NEW" - New.
	//   "USED" - Used.
	ItemConditions []string `json:"itemConditions,omitempty"`
	// Label: Optional. Immutable. This field represents the unique user-defined
	// label of the return policy for the given country. It is important to note
	// that the same label cannot be used in different return policies for the same
	// country. If not given, policies will be automatically treated as the
	// 'default' for the country. When using label, you are creating an exception
	// policy in that country to assign a custom return policy to certain product
	// groups, follow the instructions provided in the [Return policy label]
	// (https://support.google.com/merchants/answer/9445425). The label can contain
	// up to 50 characters.
	Label string `json:"label,omitempty"`
	// Name: Identifier. The name of the `OnlineReturnPolicy` resource. Format:
	// `accounts/{account}/onlineReturnPolicies/{return_policy}`
	Name string `json:"name,omitempty"`
	// Policy: Optional. The return policy.
	Policy *Policy `json:"policy,omitempty"`
	// ProcessRefundDays: Optional. The field specifies the number of days it takes
	// for business to process refunds.
	ProcessRefundDays int64 `json:"processRefundDays,omitempty"`
	// RestockingFee: Optional. The restocking fee that applies to all return
	// reason categories. This would be treated as a free restocking fee if the
	// value is not set.
	RestockingFee *RestockingFee `json:"restockingFee,omitempty"`
	// ReturnLabelSource: Optional. The field specifies the return label source.
	//
	// Possible values:
	//   "RETURN_LABEL_SOURCE_UNSPECIFIED" - Default value. This value is unused.
	//   "DOWNLOAD_AND_PRINT" - Download and print.
	//   "IN_THE_PACKAGE" - Label include in the package.
	//   "CUSTOMER_RESPONSIBILITY" - Customer to provide.
	ReturnLabelSource string `json:"returnLabelSource,omitempty"`
	// ReturnMethods: Optional. The return methods of how customers can return an
	// item. This value is required to not be empty unless the type of return
	// policy is noReturns.
	//
	// Possible values:
	//   "RETURN_METHOD_UNSPECIFIED" - Default value. This value is unused.
	//   "BY_MAIL" - Return by mail.
	//   "IN_STORE" - Return in store.
	//   "AT_A_KIOSK" - Return at a kiosk.
	ReturnMethods []string `json:"returnMethods,omitempty"`
	// ReturnPolicyId: Output only. Return policy ID generated by Google.
	ReturnPolicyId string `json:"returnPolicyId,omitempty"`
	// ReturnPolicyUri: Required. The return policy uri. This can used by Google to
	// do a sanity check for the policy. It must be a valid URL.
	ReturnPolicyUri string `json:"returnPolicyUri,omitempty"`
	// ReturnShippingFee: Optional. The return shipping fee. Should be set only
	// when customer need to download and print the return label.
	ReturnShippingFee *ReturnShippingFee `json:"returnShippingFee,omitempty"`
	// SeasonalOverrides: Optional. Overrides to the general policy for orders
	// placed during a specific set of time intervals.
	SeasonalOverrides []*SeasonalOverride `json:"seasonalOverrides,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AcceptDefectiveOnly") 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. "AcceptDefectiveOnly") 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 OnlineReturnPolicy) MarshalJSON() ([]byte, error) {
	type NoMethod OnlineReturnPolicy
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PhoneNumber: An object representing a phone number, suitable as an API wire
// format. This representation: - should not be used for locale-specific
// formatting of a phone number, such as "+1 (650) 253-0000 ext. 123" - is not
// designed for efficient storage - may not be suitable for dialing -
// specialized libraries (see references) should be used to parse the number
// for that purpose To do something meaningful with this number, such as format
// it for various use-cases, convert it to an `i18n.phonenumbers.PhoneNumber`
// object first. For instance, in Java this would be:
// com.google.type.PhoneNumber wireProto =
// com.google.type.PhoneNumber.newBuilder().build();
// com.google.i18n.phonenumbers.Phonenumber.PhoneNumber phoneNumber =
// PhoneNumberUtil.getInstance().parse(wireProto.getE164Number(), "ZZ"); if
// (!wireProto.getExtension().isEmpty()) {
// phoneNumber.setExtension(wireProto.getExtension()); } Reference(s): -
// https://github.com/google/libphonenumber
type PhoneNumber struct {
	// E164Number: The phone number, represented as a leading plus sign ('+'),
	// followed by a phone number that uses a relaxed ITU E.164 format consisting
	// of the country calling code (1 to 3 digits) and the subscriber number, with
	// no additional spaces or formatting. For example: - correct: "+15552220123" -
	// incorrect: "+1 (555) 222-01234 x123" The ITU E.164 format limits the latter
	// to 12 digits, but in practice not all countries respect that, so we relax
	// that restriction here. National-only numbers are not allowed. References: -
	// https://www.itu.int/rec/T-REC-E.164-201011-I -
	// https://en.wikipedia.org/wiki/E.164. -
	// https://en.wikipedia.org/wiki/List_of_country_calling_codes
	E164Number string `json:"e164Number,omitempty"`
	// Extension: The phone number's extension. The extension is not standardized
	// in ITU recommendations, except for being defined as a series of numbers with
	// a maximum length of 40 digits. Other than digits, some other dialing
	// characters such as ',' (indicating a wait) or '#' may be stored here. Note
	// that no regions currently use extensions with short codes, so this field is
	// normally only set in conjunction with an E.164 number. It is held separately
	// from the E.164 number to allow for short code extensions in the future.
	Extension string `json:"extension,omitempty"`
	// ShortCode: A short code. Reference(s): -
	// https://wikipedia.org/wiki/Short_code
	ShortCode *ShortCode `json:"shortCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "E164Number") 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. "E164Number") 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 PhoneNumber) MarshalJSON() ([]byte, error) {
	type NoMethod PhoneNumber
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Pickup: Collection of information related to Pickup.
type Pickup struct {
	// State: Output only. The state of the pickup serving.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "ACTIVE" - The review process has concluded successfully. The reviewed
	// item is active.
	//   "FAILED" - The review process failed.
	//   "RUNNING" - The review process is running.
	//   "ACTION_REQUIRED" - The review process is waiting for the merchant to take
	// action.
	State string `json:"state,omitempty"`
	// Uri: Required. Pickup product page URI. It is only used for the review of
	// pickup serving. This URI domain should match with the business's homepage.
	Uri string `json:"uri,omitempty"`
	// ForceSendFields is a list of field names (e.g. "State") 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. "State") 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 Pickup) MarshalJSON() ([]byte, error) {
	type NoMethod Pickup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Policy: The available policies.
type Policy struct {
	// Days: The number of days items can be returned after delivery, where one day
	// is defined as 24 hours after the delivery timestamp. Required for
	// `NUMBER_OF_DAYS_AFTER_DELIVERY` returns.
	Days int64 `json:"days,omitempty,string"`
	// Type: Policy type.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Default value. This value is unused.
	//   "NUMBER_OF_DAYS_AFTER_DELIVERY" - The number of days within which a return
	// is valid after delivery.
	//   "NO_RETURNS" - No returns.
	//   "LIFETIME_RETURNS" - Life time returns.
	Type string `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Days") 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. "Days") 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 Policy) MarshalJSON() ([]byte, error) {
	type NoMethod Policy
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PostalAddress: Represents a postal address, such as for postal delivery or
// payments addresses. With a postal address, a postal service can deliver
// items to a premise, P.O. box, or similar. A postal address is not intended
// to model geographical locations like roads, towns, or mountains. In typical
// usage, an address would be created by user input or from importing existing
// data, depending on the type of process. Advice on address input or editing:
// - Use an internationalization-ready address widget such as
// https://github.com/google/libaddressinput. - Users should not be presented
// with UI elements for input or editing of fields outside countries where that
// field is used. For more guidance on how to use this schema, see:
// https://support.google.com/business/answer/6397478.
type PostalAddress struct {
	// AddressLines: Unstructured address lines describing the lower levels of an
	// address. Because values in `address_lines` do not have type information and
	// may sometimes contain multiple values in a single field (for example,
	// "Austin, TX"), it is important that the line order is clear. The order of
	// address lines should be "envelope order" for the country or region of the
	// address. In places where this can vary (for example, Japan),
	// `address_language` is used to make it explicit (for example, "ja" for
	// large-to-small ordering and "ja-Latn" or "en" for small-to-large). In this
	// way, the most specific line of an address can be selected based on the
	// language. The minimum permitted structural representation of an address
	// consists of a `region_code` with all remaining information placed in the
	// `address_lines`. It would be possible to format such an address very
	// approximately without geocoding, but no semantic reasoning could be made
	// about any of the address components until it was at least partially
	// resolved. Creating an address only containing a `region_code` and
	// `address_lines` and then geocoding is the recommended way to handle
	// completely unstructured addresses (as opposed to guessing which parts of the
	// address should be localities or administrative areas).
	AddressLines []string `json:"addressLines,omitempty"`
	// AdministrativeArea: Optional. Highest administrative subdivision which is
	// used for postal addresses of a country or region. For example, this can be a
	// state, a province, an oblast, or a prefecture. For Spain, this is the
	// province and not the autonomous community (for example, "Barcelona" and not
	// "Catalonia"). Many countries don't use an administrative area in postal
	// addresses. For example, in Switzerland, this should be left unpopulated.
	AdministrativeArea string `json:"administrativeArea,omitempty"`
	// LanguageCode: Optional. BCP-47 language code of the contents of this address
	// (if known). This is often the UI language of the input form or is expected
	// to match one of the languages used in the address' country/region, or their
	// transliterated equivalents. This can affect formatting in certain countries,
	// but is not critical to the correctness of the data and will never affect any
	// validation or other non-formatting related operations. If this value is not
	// known, it should be omitted (rather than specifying a possibly incorrect
	// default). Examples: "zh-Hant", "ja", "ja-Latn", "en".
	LanguageCode string `json:"languageCode,omitempty"`
	// Locality: Optional. Generally refers to the city or town portion of the
	// address. Examples: US city, IT comune, UK post town. In regions of the world
	// where localities are not well defined or do not fit into this structure
	// well, leave `locality` empty and use `address_lines`.
	Locality string `json:"locality,omitempty"`
	// Organization: Optional. The name of the organization at the address.
	Organization string `json:"organization,omitempty"`
	// PostalCode: Optional. Postal code of the address. Not all countries use or
	// require postal codes to be present, but where they are used, they may
	// trigger additional validation with other parts of the address (for example,
	// state or zip code validation in the United States).
	PostalCode string `json:"postalCode,omitempty"`
	// Recipients: Optional. The recipient at the address. This field may, under
	// certain circumstances, contain multiline information. For example, it might
	// contain "care of" information.
	Recipients []string `json:"recipients,omitempty"`
	// RegionCode: Required. CLDR region code of the country/region of the address.
	// This is never inferred and it is up to the user to ensure the value is
	// correct. See https://cldr.unicode.org/ and
	// https://www.unicode.org/cldr/charts/30/supplemental/territory_information.html
	// for details. Example: "CH" for Switzerland.
	RegionCode string `json:"regionCode,omitempty"`
	// Revision: The schema revision of the `PostalAddress`. This must be set to 0,
	// which is the latest revision. All new revisions **must** be backward
	// compatible with old revisions.
	Revision int64 `json:"revision,omitempty"`
	// SortingCode: Optional. Additional, country-specific, sorting code. This is
	// not used in most regions. Where it is used, the value is either a string
	// like "CEDEX", optionally followed by a number (for example, "CEDEX 7"), or
	// just a number alone, representing the "sector code" (Jamaica), "delivery
	// area indicator" (Malawi) or "post office indicator" (Côte d'Ivoire).
	SortingCode string `json:"sortingCode,omitempty"`
	// Sublocality: Optional. Sublocality of the address. For example, this can be
	// a neighborhood, borough, or district.
	Sublocality string `json:"sublocality,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AddressLines") 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. "AddressLines") 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 PostalAddress) MarshalJSON() ([]byte, error) {
	type NoMethod PostalAddress
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PostalCodeArea: A list of postal codes that defines the region area. Note:
// All regions defined using postal codes are accessible through the account's
// `ShippingSettings.postalCodeGroups` resource.
type PostalCodeArea struct {
	// PostalCodes: Required. A range of postal codes.
	PostalCodes []*PostalCodeRange `json:"postalCodes,omitempty"`
	// RegionCode: Required. CLDR territory code
	// (http://www.unicode.org/repos/cldr/tags/latest/common/main/en.xml) or the
	// country the postal code group applies to.
	RegionCode string `json:"regionCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PostalCodes") 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. "PostalCodes") 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 PostalCodeArea) MarshalJSON() ([]byte, error) {
	type NoMethod PostalCodeArea
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PostalCodeRange: A range of postal codes that defines the region area.
type PostalCodeRange struct {
	// Begin: Required. A postal code or a pattern of the form prefix* denoting the
	// inclusive lower bound of the range defining the area. Examples values:
	// `94108`, `9410*`, `9*`.
	Begin string `json:"begin,omitempty"`
	// End: Optional. A postal code or a pattern of the form `prefix*` denoting the
	// inclusive upper bound of the range defining the area. It must have the same
	// length as postalCodeRangeBegin: if postalCodeRangeBegin is a postal code
	// then postalCodeRangeEnd must be a postal code too; if postalCodeRangeBegin
	// is a pattern then postalCodeRangeEnd must be a pattern with the same prefix
	// length. Optional: if not set, then the area is defined as being all the
	// postal codes matching postalCodeRangeBegin.
	End string `json:"end,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Begin") 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. "Begin") 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 PostalCodeRange) MarshalJSON() ([]byte, error) {
	type NoMethod PostalCodeRange
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Price: The price represented as a number and currency.
type Price struct {
	// AmountMicros: The price represented as a number in micros (1 million micros
	// is an equivalent to one's currency standard unit, for example, 1 USD =
	// 1000000 micros).
	AmountMicros int64 `json:"amountMicros,omitempty,string"`
	// CurrencyCode: The currency of the price using three-letter acronyms
	// according to ISO 4217 (http://en.wikipedia.org/wiki/ISO_4217).
	CurrencyCode string `json:"currencyCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AmountMicros") 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. "AmountMicros") 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 Price) MarshalJSON() ([]byte, error) {
	type NoMethod Price
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ProductChange: The change that happened to the product including old value,
// new value, country code as the region code and reporting context.
type ProductChange struct {
	// NewValue: The new value of the changed resource or attribute. If empty, it
	// means that the product was deleted. Will have one of these values :
	// (`approved`, `pending`, `disapproved`, ``)
	NewValue string `json:"newValue,omitempty"`
	// OldValue: The old value of the changed resource or attribute. If empty, it
	// means that the product was created. Will have one of these values :
	// (`approved`, `pending`, `disapproved`, ``)
	OldValue string `json:"oldValue,omitempty"`
	// RegionCode: Countries that have the change (if applicable). Represented in
	// the ISO 3166 format.
	RegionCode string `json:"regionCode,omitempty"`
	// ReportingContext: Reporting contexts that have the change (if applicable).
	// Currently this field supports only (`SHOPPING_ADS`, `LOCAL_INVENTORY_ADS`,
	// `YOUTUBE_SHOPPING`, `YOUTUBE_CHECKOUT`, `YOUTUBE_AFFILIATE`) from the enum
	// value ReportingContextEnum
	// (/merchant/api/reference/rest/Shared.Types/ReportingContextEnum)
	//
	// Possible values:
	//   "REPORTING_CONTEXT_ENUM_UNSPECIFIED" - Not specified.
	//   "SHOPPING_ADS" - [Shopping
	// ads](https://support.google.com/merchants/answer/6149970).
	//   "DISCOVERY_ADS" - Deprecated: Use `DEMAND_GEN_ADS` instead. [Discovery and
	// Demand Gen ads](https://support.google.com/merchants/answer/13389785).
	//   "DEMAND_GEN_ADS" - [Demand Gen
	// ads](https://support.google.com/merchants/answer/13389785).
	//   "DEMAND_GEN_ADS_DISCOVER_SURFACE" - [Demand Gen ads on Discover
	// surface](https://support.google.com/merchants/answer/13389785).
	//   "VIDEO_ADS" - [Video
	// ads](https://support.google.com/google-ads/answer/6340491).
	//   "DISPLAY_ADS" - [Display
	// ads](https://support.google.com/merchants/answer/6069387).
	//   "LOCAL_INVENTORY_ADS" - [Local inventory
	// ads](https://support.google.com/merchants/answer/3271956).
	//   "VEHICLE_INVENTORY_ADS" - [Vehicle inventory
	// ads](https://support.google.com/merchants/answer/11544533).
	//   "FREE_LISTINGS" - [Free product
	// listings](https://support.google.com/merchants/answer/9199328).
	//   "FREE_LISTINGS_UCP_CHECKOUT" - [Free product listings on UCP
	// checkout](https://developers.google.com/merchant/ucp).
	//   "FREE_LOCAL_LISTINGS" - [Free local product
	// listings](https://support.google.com/merchants/answer/9825611).
	//   "FREE_LOCAL_VEHICLE_LISTINGS" - [Free local vehicle
	// listings](https://support.google.com/merchants/answer/11544533).
	//   "YOUTUBE_AFFILIATE" - [Youtube
	// Affiliate](https://support.google.com/youtube/answer/13376398).
	//   "YOUTUBE_SHOPPING" - [YouTube
	// Shopping](https://support.google.com/merchants/answer/13478370).
	//   "CLOUD_RETAIL" - [Cloud
	// retail](https://cloud.google.com/solutions/retail).
	//   "LOCAL_CLOUD_RETAIL" - [Local cloud
	// retail](https://cloud.google.com/solutions/retail).
	//   "PRODUCT_REVIEWS" - [Product
	// Reviews](https://support.google.com/merchants/answer/14620732).
	//   "MERCHANT_REVIEWS" - [Merchant
	// Reviews](https://developers.google.com/merchant-review-feeds).
	//   "YOUTUBE_CHECKOUT" - YouTube Checkout .
	ReportingContext string `json:"reportingContext,omitempty"`
	// ForceSendFields is a list of field names (e.g. "NewValue") 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. "NewValue") 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 ProductChange) MarshalJSON() ([]byte, error) {
	type NoMethod ProductChange
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ProductStatusChangeMessage: The message that the merchant will receive to
// notify about product status change event
type ProductStatusChangeMessage struct {
	// Account: The target account that owns the entity that changed. Format :
	// `accounts/{merchant_id}`
	Account string `json:"account,omitempty"`
	// Attribute: The attribute in the resource that changed, in this case it will
	// be always `Status`.
	//
	// Possible values:
	//   "ATTRIBUTE_UNSPECIFIED" - Unspecified attribute
	//   "STATUS" - Status of the changed entity
	Attribute string `json:"attribute,omitempty"`
	// Changes: A message to describe the change that happened to the product
	Changes []*ProductChange `json:"changes,omitempty"`
	// EventTime: The time at which the event was generated. If you want to order
	// the notification messages you receive you should rely on this field not on
	// the order of receiving the notifications.
	EventTime string `json:"eventTime,omitempty"`
	// ExpirationTime: Optional. The product expiration time. This field will not
	// be set if the notification is sent for a product deletion event.
	ExpirationTime string `json:"expirationTime,omitempty"`
	// ManagingAccount: The account that manages the merchant's account. can be the
	// same as merchant id if it is standalone account. Format :
	// `accounts/{service_provider_id}`
	ManagingAccount string `json:"managingAccount,omitempty"`
	// Resource: The product name. Format: `accounts/{account}/products/{product}`
	Resource string `json:"resource,omitempty"`
	// ResourceId: The product id.
	ResourceId string `json:"resourceId,omitempty"`
	// ResourceType: The resource that changed, in this case it will always be
	// `Product`.
	//
	// Possible values:
	//   "RESOURCE_UNSPECIFIED" - Unspecified resource
	//   "PRODUCT" - Resource type : product
	ResourceType string `json:"resourceType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Account") 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. "Account") 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 ProductStatusChangeMessage) MarshalJSON() ([]byte, error) {
	type NoMethod ProductStatusChangeMessage
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ProductsManagement: `ProductsManagement` payload.
type ProductsManagement struct {
}

// Program: Defines participation in a given program for the specified account.
// Programs provide a mechanism for adding functionality to a Merchant Center
// accounts. A typical example of this is the Free product listings
// (https://support.google.com/merchants/answer/13889434) program, which
// enables products from a business's store to be shown across Google for free.
// The following list is the available set of program resource IDs accessible
// through the API: * `checkout` * `free-listings` * `product-ratings` *
// `shopping-ads` * `youtube-shopping-checkout`
type Program struct {
	// ActiveRegionCodes: Output only. The regions in which the account is actively
	// participating in the program. Active regions are defined as those where all
	// program requirements affecting the regions have been met. Region codes are
	// defined by CLDR (https://cldr.unicode.org/). This is either a country where
	// the program applies specifically to that country or `001` when the program
	// applies globally.
	ActiveRegionCodes []string `json:"activeRegionCodes,omitempty"`
	// DocumentationUri: Output only. The URL of a Merchant Center help page
	// describing the program.
	DocumentationUri string `json:"documentationUri,omitempty"`
	// Name: Identifier. The resource name of the program. Format:
	// `accounts/{account}/programs/{program}`
	Name string `json:"name,omitempty"`
	// State: Output only. The participation state of the account in the program.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "NOT_ELIGIBLE" - The account is not eligible to participate in the
	// program.
	//   "ELIGIBLE" - The account is eligible to participate in the program.
	//   "ENABLED" - The program is enabled for the account.
	State string `json:"state,omitempty"`
	// UnmetRequirements: Output only. The requirements that the account has not
	// yet satisfied that are affecting participation in the program.
	UnmetRequirements []*Requirement `json:"unmetRequirements,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ActiveRegionCodes") 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. "ActiveRegionCodes") 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 Program) MarshalJSON() ([]byte, error) {
	type NoMethod Program
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ProposeAccountServiceRequest: Request to propose an account service.
type ProposeAccountServiceRequest struct {
	// AccountService: Required. The account service to propose.
	AccountService *AccountService `json:"accountService,omitempty"`
	// Provider: Required. The provider of the service. Either the reference to an
	// account such as `providers/123` or a well-known service provider (one of
	// `providers/GOOGLE_ADS` or `providers/GOOGLE_BUSINESS_PROFILE`).
	Provider string `json:"provider,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountService") 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. "AccountService") 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 ProposeAccountServiceRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ProposeAccountServiceRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RadiusArea: A radius area that defines the region area.
type RadiusArea struct {
	// LatLng: Required. The center of the radius area. It represents a
	// latitude/longitude pair in decimal degrees format.
	LatLng *LatLng `json:"latLng,omitempty"`
	// Radius: Required. The radius distance of the area.
	Radius float64 `json:"radius,omitempty"`
	// RadiusUnits: Optional. The unit of the radius.
	//
	// Possible values:
	//   "RADIUS_UNITS_UNSPECIFIED" - Unused default value
	//   "MILES" - The distance is measured in miles.
	//   "KILOMETERS" - The distance is measured in kilometers.
	RadiusUnits string `json:"radiusUnits,omitempty"`
	// RegionCode: Required. CLDR territory code
	// (http://www.unicode.org/repos/cldr/tags/latest/common/main/en.xml) or the
	// country the radius area applies to.
	RegionCode string `json:"regionCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "LatLng") 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. "LatLng") 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 RadiusArea) MarshalJSON() ([]byte, error) {
	type NoMethod RadiusArea
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

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

// RateGroup: Shipping rate group definitions. Only the last one is allowed to
// have an empty `applicable_shipping_labels`, which means "everything else".
// The other `applicable_shipping_labels` must not overlap.
type RateGroup struct {
	// ApplicableShippingLabels: Required. A list of shipping labels
	// (https://support.google.com/merchants/answer/6324504) defining the products
	// to which this rate group applies to. This is a disjunction: only one of the
	// labels has to match for the rate group to apply. May only be empty for the
	// last rate group of a service.
	ApplicableShippingLabels []string `json:"applicableShippingLabels,omitempty"`
	// CarrierRates: Optional. A list of carrier rates that can be referred to by
	// `main_table` or `single_value`.
	CarrierRates []*CarrierRate `json:"carrierRates,omitempty"`
	// MainTable: A table defining the rate group, when `single_value` is not
	// expressive enough. Can only be set if `single_value` is not set.
	MainTable *Table `json:"mainTable,omitempty"`
	// Name: Optional. Name of the rate group. If set has to be unique within
	// shipping service.
	Name string `json:"name,omitempty"`
	// SingleValue: The value of the rate group (For example flat rate $10). Can
	// only be set if `main_table` and `subtables` are not set.
	SingleValue *Value `json:"singleValue,omitempty"`
	// Subtables: Optional. A list of subtables referred to by `main_table`. Can
	// only be set if `main_table` is set.
	Subtables []*Table `json:"subtables,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ApplicableShippingLabels")
	// 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. "ApplicableShippingLabels") 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 RateGroup) MarshalJSON() ([]byte, error) {
	type NoMethod RateGroup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Region: Represents a geographic region that you can use as a target with
// both the `RegionalInventory` and `ShippingSettings` services. You can define
// regions as collections of either postal codes, radius areas or, in some
// countries, using predefined geotargets. A region must be defined by
// specifying exactly one of `postal_code_area`, `geotarget_area`, or
// `radius_area`. For more information, see Set up regions
// (https://support.google.com/merchants/answer/7410946#zippy=%2Ccreate-a-new-region)
// for more information.
type Region struct {
	// DisplayName: Optional. The display name of the region.
	DisplayName string `json:"displayName,omitempty"`
	// GeotargetArea: Optional. A list of geotargets that defines the region area.
	GeotargetArea *GeoTargetArea `json:"geotargetArea,omitempty"`
	// Name: Identifier. The resource name of the region. Format:
	// `accounts/{account}/regions/{region}`
	Name string `json:"name,omitempty"`
	// PostalCodeArea: Optional. A list of postal codes that defines the region
	// area.
	PostalCodeArea *PostalCodeArea `json:"postalCodeArea,omitempty"`
	// RadiusArea: Optional. A radius area that defines the region area.
	RadiusArea *RadiusArea `json:"radiusArea,omitempty"`
	// RegionalInventoryEligible: Output only. Indicates if the region is eligible
	// for use in the Regional Inventory configuration.
	RegionalInventoryEligible bool `json:"regionalInventoryEligible,omitempty"`
	// ShippingEligible: Output only. Indicates if the region is eligible for use
	// in the Shipping Services configuration.
	ShippingEligible bool `json:"shippingEligible,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "DisplayName") 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. "DisplayName") 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 Region) MarshalJSON() ([]byte, error) {
	type NoMethod Region
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RegisterGcpRequest: Request message for the RegisterGCP method.
type RegisterGcpRequest struct {
	// DeveloperEmail: Immutable. Optional field. Developer role can be also added
	// by using `users.update` method. If the developer email provided is
	// associated with a user in the provided merchant account, the user will be
	// updated to have `API_DEVELOPER` `access_rights` and the email preference
	// corresponding to that user will be updated to have the new API notifications
	// preference. If the developer email provided is not associated with any user,
	// it is added as a contact. The email preference corresponding to that contact
	// will have the new API notifications preference. Make sure the email used is
	// associated with a Google Account and is not a service account as service
	// accounts can't receive emails.
	DeveloperEmail string `json:"developerEmail,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DeveloperEmail") 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. "DeveloperEmail") 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 RegisterGcpRequest) MarshalJSON() ([]byte, error) {
	type NoMethod RegisterGcpRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RejectAccountServiceRequest: Request to reject an account service.
type RejectAccountServiceRequest struct {
}

// RequestInventoryVerificationRequest: Request message for the
// RequestInventoryVerification method.
type RequestInventoryVerificationRequest struct {
}

// RequestInventoryVerificationResponse: Response message for the
// RequestInventoryVerification method.
type RequestInventoryVerificationResponse struct {
	// OmnichannelSetting: The omnichannel setting that was updated.
	OmnichannelSetting *OmnichannelSetting `json:"omnichannelSetting,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "OmnichannelSetting") 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. "OmnichannelSetting") 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 RequestInventoryVerificationResponse) MarshalJSON() ([]byte, error) {
	type NoMethod RequestInventoryVerificationResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Required: Describes the terms of service which are required to be accepted.
type Required struct {
	// TermsOfService: Required. The `TermsOfService` that need to be accepted.
	TermsOfService string `json:"termsOfService,omitempty"`
	// TosFileUri: Required. Full URL to the terms of service file. This field is
	// the same as `TermsOfService.file_uri`, it is added here for convenience
	// only.
	TosFileUri string `json:"tosFileUri,omitempty"`
	// ForceSendFields is a list of field names (e.g. "TermsOfService") 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. "TermsOfService") 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 Required) MarshalJSON() ([]byte, error) {
	type NoMethod Required
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Requirement: Defines a requirement specified for participation in the
// program.
type Requirement struct {
	// AffectedRegionCodes: Output only. The regions that are currently affected by
	// this requirement not being met. Region codes are defined by CLDR
	// (https://cldr.unicode.org/). This is either a country where the program
	// applies specifically to that country or `001` when the program applies
	// globally.
	AffectedRegionCodes []string `json:"affectedRegionCodes,omitempty"`
	// DocumentationUri: Output only. The URL of a help page describing the
	// requirement.
	DocumentationUri string `json:"documentationUri,omitempty"`
	// Title: Output only. Name of the requirement.
	Title string `json:"title,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AffectedRegionCodes") 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. "AffectedRegionCodes") 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 Requirement) MarshalJSON() ([]byte, error) {
	type NoMethod Requirement
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RestockingFee: The restocking fee. This can be a flat fee or a micro
// percent.
type RestockingFee struct {
	// FixedFee: Fixed restocking fee.
	FixedFee *Price `json:"fixedFee,omitempty"`
	// MicroPercent: Percent of total price in micros. 15,000,000 means 15% of the
	// total price would be charged.
	MicroPercent int64 `json:"microPercent,omitempty"`
	// ForceSendFields is a list of field names (e.g. "FixedFee") 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. "FixedFee") 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 RestockingFee) MarshalJSON() ([]byte, error) {
	type NoMethod RestockingFee
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReturnShippingFee: The return shipping fee. This can either be a fixed fee
// or a boolean to indicate that the customer pays the actual shipping cost.
type ReturnShippingFee struct {
	// FixedFee: Fixed return shipping fee amount. This value is only applicable
	// when type is `FIXED`. We will treat the return shipping fee as free if type
	// is `FIXED` and this value is not set.
	FixedFee *Price `json:"fixedFee,omitempty"`
	// Type: Required. Type of return shipping fee.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Default value. This value is unused.
	//   "FIXED" - The return shipping fee is a fixed value.
	//   "CUSTOMER_PAYING_ACTUAL_FEE" - Customers will pay the actual return
	// shipping fee.
	Type string `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "FixedFee") 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. "FixedFee") 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 ReturnShippingFee) MarshalJSON() ([]byte, error) {
	type NoMethod ReturnShippingFee
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Row: Include a list of cells.
type Row struct {
	// Cells: Required. The list of cells that constitute the row. Must have the
	// same length as `columnHeaders` for two-dimensional tables, a length of 1 for
	// one-dimensional tables.
	Cells []*Value `json:"cells,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Cells") 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. "Cells") 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 Row) MarshalJSON() ([]byte, error) {
	type NoMethod Row
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type SeasonalOverride struct {
	// EndDate: Required. seasonal override end date (inclusive).
	EndDate *Date `json:"endDate,omitempty"`
	// Label: Required. Display name of this seasonal override in Merchant Center.
	Label string `json:"label,omitempty"`
	// ReturnDays: Number of days (from the delivery date) that the product can be
	// returned.
	ReturnDays int64 `json:"returnDays,omitempty"`
	// ReturnUntilDate: Fixed end date until which the product can be returned.
	ReturnUntilDate *Date `json:"returnUntilDate,omitempty"`
	// StartDate: Required. Defines the date range when this seasonal override
	// applies. Both start_date and end_date are inclusive. The dates of the
	// seasonal overrides should not overlap.
	StartDate *Date `json:"startDate,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndDate") 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. "EndDate") 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 SeasonalOverride) MarshalJSON() ([]byte, error) {
	type NoMethod SeasonalOverride
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Service: Shipping service.
type Service struct {
	// Active: Required. A boolean exposing the active status of the shipping
	// service.
	Active bool `json:"active,omitempty"`
	// CurrencyCode: Required. The CLDR code of the currency to which this service
	// applies. Must match that of the prices in rate groups.
	CurrencyCode string `json:"currencyCode,omitempty"`
	// DeliveryCountries: Required. The CLDR territory code of the countries to
	// which the service applies.
	DeliveryCountries []string `json:"deliveryCountries,omitempty"`
	// DeliveryTime: Required. Time spent in various aspects from order to the
	// delivery of the product.
	DeliveryTime *DeliveryTime `json:"deliveryTime,omitempty"`
	// LoyaltyPrograms: Optional. Loyalty programs that this shipping service is
	// limited to.
	LoyaltyPrograms []*LoyaltyProgram `json:"loyaltyPrograms,omitempty"`
	// MinimumOrderValue: Optional. Minimum order value for this service. If set,
	// indicates that customers will have to spend at least this amount. All prices
	// within a service must have the same currency. Cannot be set together with
	// `minimum_order_value_table`.
	MinimumOrderValue *Price `json:"minimumOrderValue,omitempty"`
	// MinimumOrderValueTable: Optional. Table of per store minimum order values
	// for the pickup fulfillment type. Cannot be set together with
	// `minimum_order_value`.
	MinimumOrderValueTable *MinimumOrderValueTable `json:"minimumOrderValueTable,omitempty"`
	// RateGroups: Optional. Shipping rate group definitions. Only the last one is
	// allowed to have an empty `applicable_shipping_labels`, which means
	// "everything else". The other `applicable_shipping_labels` must not overlap.
	RateGroups []*RateGroup `json:"rateGroups,omitempty"`
	// ServiceName: Required. Free-form name of the service. Must be unique within
	// target account.
	ServiceName string `json:"serviceName,omitempty"`
	// ShipmentType: Optional. Type of locations this service ships orders to.
	//
	// Possible values:
	//   "SHIPMENT_TYPE_UNSPECIFIED" - This service did not specify shipment type.
	//   "DELIVERY" - This service ships orders to an address chosen by the
	// customer.
	//   "LOCAL_DELIVERY" - This service ships orders to an address chosen by the
	// customer. The order is shipped from a local store near by.
	//   "COLLECTION_POINT" - This service ships orders to an address chosen by the
	// customer. The order is shipped from a collection point.
	ShipmentType string `json:"shipmentType,omitempty"`
	// StoreConfig: A list of stores your products are delivered from. This is only
	// valid for the local delivery shipment type.
	StoreConfig *StoreConfig `json:"storeConfig,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Active") 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. "Active") 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 Service) MarshalJSON() ([]byte, error) {
	type NoMethod Service
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// SetAliasForRelationship: Set an alias for a relationship between a provider
// and the account to be created.
type SetAliasForRelationship struct {
	// AccountIdAlias: Required. The unique ID of this account in the provider's
	// system. The value must be unique across all accounts on the platform for
	// this provider.
	AccountIdAlias string `json:"accountIdAlias,omitempty"`
	// Provider: Required. The provider of the service. This is a reference to an
	// account such as `providers/123` or `accounts/123`. The same provider must be
	// specified in at least one of the `service` fields.
	Provider string `json:"provider,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AccountIdAlias") 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. "AccountIdAlias") 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 SetAliasForRelationship) MarshalJSON() ([]byte, error) {
	type NoMethod SetAliasForRelationship
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ShippingSettings: The Merchant Center account's shipping settings
// (https://support.google.com/merchants/answer/6069284). The
// `ShippingSettings` resource lets you retrieve and update the shipping
// settings of your advanced account and all its associated sub-accounts.
type ShippingSettings struct {
	// Etag: Required. This field helps avoid async issues. It ensures that the
	// shipping setting data doesn't change between the `get` call and the `insert`
	// call. The user should follow these steps: 1. Set the etag field as an empty
	// string for the initial shipping setting creation. 2. After the initial
	// creation, call the `get` method to obtain an etag and the current shipping
	// setting data before calling `insert`. 3. Modify the shipping setting
	// information. 4. Call the `insert` method with the shipping setting
	// information and the etag obtained in step 2. 5. If the shipping setting data
	// changes between step 2 and step 4, the insert request will fail because the
	// etag changes every time the shipping setting data changes. In this case, the
	// user should repeat steps 2-4 with the new etag.
	Etag string `json:"etag,omitempty"`
	// Name: Identifier. The resource name of the shipping settings. Format:
	// `accounts/{account}/shippingSettings`. For example,
	// `accounts/123456/shippingSettings`.
	Name string `json:"name,omitempty"`
	// Services: Optional. The target account's list of services.
	Services []*Service `json:"services,omitempty"`
	// Warehouses: Optional. A list of warehouses which can be referred to in
	// `services`.
	Warehouses []*Warehouse `json:"warehouses,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Etag") 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. "Etag") 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 ShippingSettings) MarshalJSON() ([]byte, error) {
	type NoMethod ShippingSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ShortCode: An object representing a short code, which is a phone number that
// is typically much shorter than regular phone numbers and can be used to
// address messages in MMS and SMS systems, as well as for abbreviated dialing
// (For example "Text 611 to see how many minutes you have remaining on your
// plan."). Short codes are restricted to a region and are not internationally
// dialable, which means the same short code can exist in different regions,
// with different usage and pricing, even if those regions share the same
// country calling code (For example: US and CA).
type ShortCode struct {
	// Number: Required. The short code digits, without a leading plus ('+') or
	// country calling code. For example "611".
	Number string `json:"number,omitempty"`
	// RegionCode: Required. The BCP-47 region code of the location where calls to
	// this short code can be made, such as "US" and "BB". Reference(s): -
	// http://www.unicode.org/reports/tr35/#unicode_region_subtag
	RegionCode string `json:"regionCode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Number") 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. "Number") 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 ShortCode) MarshalJSON() ([]byte, error) {
	type NoMethod ShortCode
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// StoreCodeSetWithMov: A list of store code sets sharing the same minimum
// order value. At least two sets are required and the last one must be empty,
// which signifies 'MOV for all other stores'. Each store code can only appear
// once across all the sets. All prices within a service must have the same
// currency.
type StoreCodeSetWithMov struct {
	// StoreCodes: Optional. A list of unique store codes or empty for the catch
	// all.
	StoreCodes []string `json:"storeCodes,omitempty"`
	// Value: The minimum order value for the given stores.
	Value *Price `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "StoreCodes") 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. "StoreCodes") 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 StoreCodeSetWithMov) MarshalJSON() ([]byte, error) {
	type NoMethod StoreCodeSetWithMov
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// StoreConfig: A list of stores your products are delivered from. This is only
// valid for the local delivery shipment type.
type StoreConfig struct {
	// CutoffConfig: Configs related to local delivery ends for the day.
	CutoffConfig *CutoffConfig `json:"cutoffConfig,omitempty"`
	// ServiceRadius: Maximum delivery radius. This is only required for the local
	// delivery shipment type.
	ServiceRadius *Distance `json:"serviceRadius,omitempty"`
	// StoreCodes: Optional. A list of store codes that provide local delivery. If
	// empty, then `all_stores` must be true.
	StoreCodes []string `json:"storeCodes,omitempty"`
	// StoreServiceType: Indicates whether all stores, or selected stores, listed
	// by this business provide local delivery.
	//
	// Possible values:
	//   "STORE_SERVICE_TYPE_UNSPECIFIED" - Did not specify store service type.
	//   "ALL_STORES" - Indicates whether all stores, current and future, listed by
	// this business provide local delivery.
	//   "SELECTED_STORES" - Indicates that only the stores listed in `store_codes`
	// are eligible for local delivery.
	StoreServiceType string `json:"storeServiceType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CutoffConfig") 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. "CutoffConfig") 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 StoreConfig) MarshalJSON() ([]byte, error) {
	type NoMethod StoreConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Table: A table defining the rate group, when `single_value` is not
// expressive enough.
type Table struct {
	// ColumnHeaders: Headers of the table's columns. Optional: if not set then the
	// table has only one dimension.
	ColumnHeaders *Headers `json:"columnHeaders,omitempty"`
	// Name: Name of the table. Required for subtables, ignored for the main table.
	Name string `json:"name,omitempty"`
	// RowHeaders: Required. Headers of the table's rows.
	RowHeaders *Headers `json:"rowHeaders,omitempty"`
	// Rows: Required. The list of rows that constitute the table. Must have the
	// same length as `row_headers`.
	Rows []*Row `json:"rows,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ColumnHeaders") 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. "ColumnHeaders") 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 Table) MarshalJSON() ([]byte, error) {
	type NoMethod Table
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TermsOfService: The `TermsOfService` message represents a specific version
// of the terms of service that merchants must accept to access certain
// features or services. For more information, see Terms of Service
// (https://support.google.com/merchants/answer/160173). This message is
// important for the onboarding process, ensuring that merchants agree to the
// necessary legal agreements for using the service. Merchants can retrieve the
// latest terms of service for a given `kind` and `region` through
// `RetrieveLatestTermsOfService`, and accept them as required through
// `AcceptTermsOfService`.
type TermsOfService struct {
	// External: Whether this terms of service version is external. External terms
	// of service versions can only be agreed through external processes and not
	// directly by the merchant through UI or API.
	External bool `json:"external,omitempty"`
	// FileUri: URI for terms of service file that needs to be displayed to signing
	// users.
	FileUri string `json:"fileUri,omitempty"`
	// Kind: The Kind this terms of service version applies to.
	//
	// Possible values:
	//   "TERMS_OF_SERVICE_KIND_UNSPECIFIED" - Default value. This value is unused.
	//   "MERCHANT_CENTER" - Terms of service for the Merchant Center application.
	Kind string `json:"kind,omitempty"`
	// Name: Identifier. The resource name of the terms of service version. Format:
	// `termsOfService/{version}`
	Name string `json:"name,omitempty"`
	// RegionCode: Region code as defined by CLDR (https://cldr.unicode.org/). This
	// is either a country where the ToS applies specifically to that country or
	// `001` when the same `TermsOfService` can be signed in any country. However
	// note that when signing a ToS that applies globally we still expect that a
	// specific country is provided (this should be merchant business country or
	// program country of participation).
	RegionCode string `json:"regionCode,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "External") 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. "External") 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 TermsOfService) MarshalJSON() ([]byte, error) {
	type NoMethod TermsOfService
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TermsOfServiceAgreementState: This resource represents the agreement state
// for a given account and terms of service kind. The state is as follows: * If
// the business has accepted a terms of service, `accepted` will be populated,
// otherwise it will be empty * If the business must sign a terms of service,
// `required` will be populated, otherwise it will be empty. Note that both
// `required` and `accepted` can be present. In this case the `accepted` terms
// of services will have an expiration date set in the `valid_until` field. The
// `required` terms of services need to be accepted before `valid_until` in
// order for the account to continue having a valid agreement. When accepting
// new terms of services we expect third-party providers to display the text
// associated with the given terms of service agreement (the url to the file
// containing the text is added in the Required message below as
// `tos_file_uri`). The actual acceptance of the terms of service is done by
// calling accept on the `TermsOfService` resource. `valid_until` field.
type TermsOfServiceAgreementState struct {
	// Accepted: Optional. The accepted terms of service of this kind and for the
	// associated region_code
	Accepted *Accepted `json:"accepted,omitempty"`
	// Name: Identifier. The resource name of the terms of service version. Format:
	// `accounts/{account}/termsOfServiceAgreementState/{identifier}` The
	// identifier format is: `{TermsOfServiceKind}-{country}` For example, an
	// identifier could be: `MERCHANT_CENTER-EU` or `MERCHANT_CENTER-US`.
	Name string `json:"name,omitempty"`
	// RegionCode: Required. Region code as defined by https://cldr.unicode.org/.
	// This is the country the current state applies to.
	RegionCode string `json:"regionCode,omitempty"`
	// Required: Optional. The required terms of service
	Required *Required `json:"required,omitempty"`
	// TermsOfServiceKind: Required. Terms of Service kind associated with the
	// particular version.
	//
	// Possible values:
	//   "TERMS_OF_SERVICE_KIND_UNSPECIFIED" - Default value. This value is unused.
	//   "MERCHANT_CENTER" - Terms of service for the Merchant Center application.
	TermsOfServiceKind string `json:"termsOfServiceKind,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Accepted") 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. "Accepted") 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 TermsOfServiceAgreementState) MarshalJSON() ([]byte, error) {
	type NoMethod TermsOfServiceAgreementState
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TimeZone: Represents a time zone from the IANA Time Zone Database
// (https://www.iana.org/time-zones).
type TimeZone struct {
	// Id: IANA Time Zone Database time zone. For example "America/New_York".
	Id string `json:"id,omitempty"`
	// Version: Optional. IANA Time Zone Database version number. For example
	// "2019a".
	Version string `json:"version,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Id") 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. "Id") 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 TimeZone) MarshalJSON() ([]byte, error) {
	type NoMethod TimeZone
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TransitTable: Transit time table, number of business days spent in transit
// based on row and column dimensions. Either `min_transit_days`,
// `max_transit_days` or `transit_time_table` can be set, but not both.
type TransitTable struct {
	// PostalCodeGroupNames: Required. A list of region names Region.name . The
	// last value can be "all other locations". Example: `["zone 1", "zone 2",
	// "all other locations"]`. The referred postal code groups must match the
	// delivery country of the service.
	PostalCodeGroupNames []string `json:"postalCodeGroupNames,omitempty"`
	// Rows: Required. If there's only one dimension set of
	// `postal_code_group_names` or `transit_time_labels`, there are multiple rows
	// each with one value for that dimension. If there are two dimensions, each
	// row corresponds to a `postal_code_group_names`, and columns (values) to a
	// `transit_time_labels`.
	Rows []*TransitTimeRow `json:"rows,omitempty"`
	// TransitTimeLabels: Required. A list of transit time labels. The last value
	// can be "all other labels". Example: `["food", "electronics", "all other
	// labels"]`.
	TransitTimeLabels []string `json:"transitTimeLabels,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PostalCodeGroupNames") 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. "PostalCodeGroupNames") 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 TransitTable) MarshalJSON() ([]byte, error) {
	type NoMethod TransitTable
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TransitTimeRow: If there's only one dimension set of
// `postal_code_group_names` or `transit_time_labels`, there are multiple rows
// each with one value for that dimension. If there are two dimensions, each
// row corresponds to a `postal_code_group_names`, and columns (values) to a
// `transit_time_labels`.
type TransitTimeRow struct {
	// Values: Required. Transit time range (min-max) in business days.
	Values []*TransitTimeValue `json:"values,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Values") 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. "Values") 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 TransitTimeRow) MarshalJSON() ([]byte, error) {
	type NoMethod TransitTimeRow
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TransitTimeValue: Transit time range (min-max) in business days.
type TransitTimeValue struct {
	// MaxTransitDays: Must be greater than or equal to `min_transit_days`.
	MaxTransitDays int64 `json:"maxTransitDays,omitempty"`
	// MinTransitDays: Minimum transit time range in business days. 0 means same
	// day delivery, 1 means next day delivery.
	MinTransitDays int64 `json:"minTransitDays,omitempty"`
	// ForceSendFields is a list of field names (e.g. "MaxTransitDays") 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. "MaxTransitDays") 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 TransitTimeValue) MarshalJSON() ([]byte, error) {
	type NoMethod TransitTimeValue
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UnclaimHomepageRequest: Request message for the `UnclaimHomepage` method.
type UnclaimHomepageRequest struct {
}

// UnregisterGcpRequest: Request message for the UnregisterGCP method.
type UnregisterGcpRequest struct {
}

// UpdateRegionRequest: Request message for the `UpdateRegion` method.
type UpdateRegionRequest struct {
	// Region: Required. The updated region.
	Region *Region `json:"region,omitempty"`
	// UpdateMask: Optional. The comma-separated field mask indicating the fields
	// to update. Example: "displayName,postalCodeArea.regionCode".
	UpdateMask string `json:"updateMask,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Region") 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. "Region") 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 UpdateRegionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateRegionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UriSettings: URL settings for cart or checkout URL.
type UriSettings struct {
	// CartUriTemplate: Cart URL template. When the placeholders are expanded will
	// redirect the buyer to the cart page on the merchant website with the
	// selected item in cart. For more details, check the help center doc
	// (https://support.google.com/merchants/answer/13945960#method1&zippy=%2Cproduct-level-url-formatting%2Caccount-level-url-formatting)
	CartUriTemplate string `json:"cartUriTemplate,omitempty"`
	// CheckoutUriTemplate: Checkout URL template. When the placeholders are
	// expanded will redirect the buyer to the merchant checkout page with the item
	// in the cart. For more details, check the help center doc
	// (https://support.google.com/merchants/answer/13945960#method1&zippy=%2Cproduct-level-url-formatting%2Caccount-level-url-formatting)
	CheckoutUriTemplate string `json:"checkoutUriTemplate,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CartUriTemplate") 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. "CartUriTemplate") 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 UriSettings) MarshalJSON() ([]byte, error) {
	type NoMethod UriSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// User: The `User` resource represents a user associated with a Merchant
// Center account. It is used to manage user permissions and access rights
// within the account. For more information, see Frequently asked questions
// about people and access levels
// (//support.google.com/merchants/answer/12160472).
type User struct {
	// AccessRights: Required. The access rights
	// (https://support.google.com/merchants/answer/12160472?sjid=6789834943175119429-EU#accesstypes)
	// the user has.
	//
	// Possible values:
	//   "ACCESS_RIGHT_UNSPECIFIED" - Default value. This value is unused.
	//   "STANDARD" - Standard access rights.
	//   "READ_ONLY" - Has access to the same read-only methods as STANDARD, but no
	// access to any mutating methods.
	//   "ADMIN" - Admin access rights.
	//   "PERFORMANCE_REPORTING" - Users with this right have access to performance
	// and insights.
	//   "API_DEVELOPER" - Users with this right have access to Merchant API and
	// its notifications. This role is only accessible to accounts that have a
	// developer registration.
	AccessRights []string `json:"accessRights,omitempty"`
	// Name: Identifier. The resource name of the user. Format:
	// `accounts/{account}/user/{email}` Use `me` to refer to your own email
	// address, for example `accounts/{account}/users/me`.
	Name string `json:"name,omitempty"`
	// State: Output only. The state of the user.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default value. This value is unused.
	//   "PENDING" - The user is pending confirmation. In this state, the user
	// first needs to accept the invitation before performing other actions.
	//   "VERIFIED" - The user is verified.
	State string `json:"state,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AccessRights") 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. "AccessRights") 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 User) MarshalJSON() ([]byte, error) {
	type NoMethod User
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Value: The single value of a rate group or the value of a rate group table's
// cell. Exactly one of `no_shipping`, `flat_rate`, `price_percentage`,
// `carrier_rateName`, `subtable_name` must be set.
type Value struct {
	// CarrierRate: The name of a carrier rate referring to a carrier rate defined
	// in the same rate group. Can only be set if all other fields are not set.
	CarrierRate string `json:"carrierRate,omitempty"`
	// FlatRate: A flat rate. Can only be set if all other fields are not set.
	FlatRate *Price `json:"flatRate,omitempty"`
	// NoShipping: If true, then the product can't be shipped. Must be true when
	// set, can only be set if all other fields are not set.
	NoShipping bool `json:"noShipping,omitempty"`
	// PricePercentage: A percentage of the price represented as a number in
	// decimal notation (For example, "5.4"). Can only be set if all other fields
	// are not set.
	PricePercentage string `json:"pricePercentage,omitempty"`
	// Subtable: The name of a subtable. Can only be set in table cells (For
	// example, not for single values), and only if all other fields are not set.
	Subtable string `json:"subtable,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CarrierRate") 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. "CarrierRate") 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 Value) MarshalJSON() ([]byte, error) {
	type NoMethod Value
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// VerificationMailSettings: Settings related to the verification email that is
// sent after adding a user.
type VerificationMailSettings struct {
	// VerificationMailMode: Optional. Mode of the verification mail. If not set,
	// the default is `SEND_VERIFICATION_MAIL`.
	//
	// Possible values:
	//   "VERIFICATION_MAIL_MODE_UNSPECIFIED" - Default first member of every enum.
	// Do not use.
	//   "SEND_VERIFICATION_MAIL" - An invitation email is sent to the user added
	// shortly after.
	//   "SUPPRESS_VERIFICATION_MAIL" - No invitation email is sent. This can be
	// useful if the user is expected to accept the invitation through the API
	// without needing another notification.
	VerificationMailMode string `json:"verificationMailMode,omitempty"`
	// ForceSendFields is a list of field names (e.g. "VerificationMailMode") 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. "VerificationMailMode") 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 VerificationMailSettings) MarshalJSON() ([]byte, error) {
	type NoMethod VerificationMailSettings
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// VerifySelfRequest: Request message for the `VerifySelf` method.
type VerifySelfRequest struct {
}

// Warehouse: A fulfillment warehouse, which stores and handles inventory.
type Warehouse struct {
	// BusinessDayConfig: Business days of the warehouse. If not set, will be
	// Monday to Friday by default.
	BusinessDayConfig *BusinessDayConfig `json:"businessDayConfig,omitempty"`
	// CutoffTime: Required. The latest time of day that an order can be accepted
	// and begin processing. Later orders will be processed in the next day. The
	// time is based on the warehouse postal code.
	CutoffTime *WarehouseCutoffTime `json:"cutoffTime,omitempty"`
	// HandlingDays: Required. The number of days it takes for this warehouse to
	// pack up and ship an item. This is on the warehouse level, but can be
	// overridden on the offer level based on the attributes of an item.
	HandlingDays int64 `json:"handlingDays,omitempty,string"`
	// Name: Required. The name of the warehouse. Must be unique within account.
	Name string `json:"name,omitempty"`
	// ShippingAddress: Required. Shipping address of the warehouse.
	ShippingAddress *Address `json:"shippingAddress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BusinessDayConfig") 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. "BusinessDayConfig") 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 Warehouse) MarshalJSON() ([]byte, error) {
	type NoMethod Warehouse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// WarehouseBasedDeliveryTime: Indicates that the delivery time should be
// calculated per warehouse (shipping origin location) based on the settings of
// the selected carrier. When set, no other transit time related field in
// `delivery_time` should be set.
type WarehouseBasedDeliveryTime struct {
	// Carrier: Required. Carrier, such as "UPS" or "Fedex". supported carriers
	// (https://support.google.com/merchants/answer/7050921#zippy=%2Ccarrier-rates-au-de-uk-and-us-only)
	Carrier string `json:"carrier,omitempty"`
	// CarrierService: Required. Carrier service, such as "ground" or "2 days".
	// The name of the service must be in the eddSupportedServices list.
	CarrierService string `json:"carrierService,omitempty"`
	// Warehouse: Required. Warehouse name. This should match warehouse.
	Warehouse string `json:"warehouse,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Carrier") 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. "Carrier") 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 WarehouseBasedDeliveryTime) MarshalJSON() ([]byte, error) {
	type NoMethod WarehouseBasedDeliveryTime
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// WarehouseCutoffTime: The latest time of day that an order can be accepted
// and begin processing. Later orders will be processed in the next day. The
// time is based on the warehouse postal code.
type WarehouseCutoffTime struct {
	// Hour: Required. Hour of the cutoff time until which an order has to be
	// placed to be processed in the same day by the warehouse. Hour is based on
	// the timezone of warehouse.
	Hour int64 `json:"hour,omitempty"`
	// Minute: Required. Minute of the cutoff time until which an order has to be
	// placed to be processed in the same day by the warehouse. Minute is based on
	// the timezone of warehouse.
	Minute int64 `json:"minute,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Hour") 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. "Hour") 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 WarehouseCutoffTime) MarshalJSON() ([]byte, error) {
	type NoMethod WarehouseCutoffTime
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Weight: The weight represented as the value in string and the unit.
type Weight struct {
	// AmountMicros: Required. The weight represented as a number in micros (1
	// million micros is an equivalent to one's currency standard unit, for
	// example, 1 kg = 1000000 micros). This field can also be set as infinity by
	// setting to -1. This field only support -1 and positive value.
	AmountMicros int64 `json:"amountMicros,omitempty,string"`
	// Unit: Required. The weight unit. Acceptable values are: kg and lb
	//
	// Possible values:
	//   "WEIGHT_UNIT_UNSPECIFIED" - unit unspecified
	//   "POUND" - lb unit.
	//   "KILOGRAM" - kg unit.
	Unit string `json:"unit,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AmountMicros") 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. "AmountMicros") 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 Weight) MarshalJSON() ([]byte, error) {
	type NoMethod Weight
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type AccountsCreateAndConfigureCall struct {
	s                                *APIService
	createandconfigureaccountrequest *CreateAndConfigureAccountRequest
	urlParams_                       gensupport.URLParams
	ctx_                             context.Context
	header_                          http.Header
}

// CreateAndConfigure: Creates a Merchant Center account with additional
// configuration. Adds the user that makes the request as an admin for the new
// account.
func (r *AccountsService) CreateAndConfigure(createandconfigureaccountrequest *CreateAndConfigureAccountRequest) *AccountsCreateAndConfigureCall {
	c := &AccountsCreateAndConfigureCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.createandconfigureaccountrequest = createandconfigureaccountrequest
	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 *AccountsCreateAndConfigureCall) Fields(s ...googleapi.Field) *AccountsCreateAndConfigureCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsCreateAndConfigureCall) Context(ctx context.Context) *AccountsCreateAndConfigureCall {
	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 *AccountsCreateAndConfigureCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsCreateAndConfigureCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createandconfigureaccountrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/accounts:createAndConfigure")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.createAndConfigure", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.createAndConfigure" call.
// Any non-2xx status code is an error. Response headers are in either
// *Account.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 *AccountsCreateAndConfigureCall) Do(opts ...googleapi.CallOption) (*Account, 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 := &Account{
		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", "merchantapi.accounts.createAndConfigure", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Delete: Deletes the specified account regardless of its type: standalone,
// advanced account or sub-account. Deleting an advanced account leads to the
// deletion of all of its sub-accounts. This also deletes the account's
// developer registration entity
// (/merchant/api/reference/rest/accounts_v1/accounts.developerRegistration)
// and any associated GCP project to the account. Executing this method
// requires admin access. The deletion succeeds only if the account does not
// provide services to any other account and has no processed offers. You can
// use the `force` parameter to override this.
//
// - name: The name of the account to delete. Format: `accounts/{account}`.
func (r *AccountsService) Delete(name string) *AccountsDeleteCall {
	c := &AccountsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Force sets the optional parameter "force": If set to `true`, the account is
// deleted even if it provides services to other accounts or has processed
// offers.
func (c *AccountsDeleteCall) Force(force bool) *AccountsDeleteCall {
	c.urlParams_.Set("force", fmt.Sprint(force))
	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 *AccountsDeleteCall) Fields(s ...googleapi.Field) *AccountsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsDeleteCall) Context(ctx context.Context) *AccountsDeleteCall {
	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 *AccountsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsDeleteCall) 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, "accounts/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", "merchantapi.accounts.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieves an account from your Merchant Center account. After
// inserting, updating, or deleting an account, it may take several minutes
// before changes take effect.
//
// - name: The name of the account to retrieve. Format: `accounts/{account}`.
func (r *AccountsService) Get(name string) *AccountsGetCall {
	c := &AccountsGetCall{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 *AccountsGetCall) Fields(s ...googleapi.Field) *AccountsGetCall {
	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 *AccountsGetCall) IfNoneMatch(entityTag string) *AccountsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsGetCall) Context(ctx context.Context) *AccountsGetCall {
	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 *AccountsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsGetCall) 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, "accounts/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", "merchantapi.accounts.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Account.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 *AccountsGetCall) Do(opts ...googleapi.CallOption) (*Account, 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 := &Account{
		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", "merchantapi.accounts.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsListCall struct {
	s            *APIService
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Note: For the `accounts.list` method, quota and limits usage are
// charged for each user, and not for the Merchant Center ID or the advanced
// account ID. To list several sub-accounts, you should use the
// `accounts.listSubaccounts` method, which is more suitable for advanced
// accounts use case.
func (r *AccountsService) List() *AccountsListCall {
	c := &AccountsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	return c
}

// Filter sets the optional parameter "filter": Returns only accounts that
// match the filter
// (https://developers.google.com/merchant/api/guides/accounts/filter). For
// more details, see the filter syntax reference
// (https://developers.google.com/merchant/api/guides/accounts/filter-syntax).
func (c *AccountsListCall) Filter(filter string) *AccountsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

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

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `accounts.list` call. Provide this to retrieve the
// subsequent page. When paginating, all other parameters provided in the
// `accounts.list` request must match the call that provided the page token.
func (c *AccountsListCall) PageToken(pageToken string) *AccountsListCall {
	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 *AccountsListCall) Fields(s ...googleapi.Field) *AccountsListCall {
	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 *AccountsListCall) IfNoneMatch(entityTag string) *AccountsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsListCall) Context(ctx context.Context) *AccountsListCall {
	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 *AccountsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsListCall) 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, "accounts/v1/accounts")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListAccountsResponse.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 *AccountsListCall) Do(opts ...googleapi.CallOption) (*ListAccountsResponse, 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 := &ListAccountsResponse{
		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", "merchantapi.accounts.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 *AccountsListCall) Pages(ctx context.Context, f func(*ListAccountsResponse) 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 AccountsListSubaccountsCall struct {
	s            *APIService
	provider     string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// ListSubaccounts: List all sub-accounts for a given advanced account. This is
// a convenience wrapper for the more powerful `accounts.list` method. This
// method will produce the same results as calling `ListsAccounts` with the
// following filter: `relationship(providerId={parent} AND
// service(type="ACCOUNT_AGGREGATION"))`
//
// - provider: The aggregation service provider. Format: `accounts/{accountId}`.
func (r *AccountsService) ListSubaccounts(provider string) *AccountsListSubaccountsCall {
	c := &AccountsListSubaccountsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.provider = provider
	return c
}

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

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `accounts.list` call. Provide this to retrieve the
// subsequent page. When paginating, all other parameters provided in the
// `accounts.list` request must match the call that provided the page token.
func (c *AccountsListSubaccountsCall) PageToken(pageToken string) *AccountsListSubaccountsCall {
	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 *AccountsListSubaccountsCall) Fields(s ...googleapi.Field) *AccountsListSubaccountsCall {
	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 *AccountsListSubaccountsCall) IfNoneMatch(entityTag string) *AccountsListSubaccountsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsListSubaccountsCall) Context(ctx context.Context) *AccountsListSubaccountsCall {
	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 *AccountsListSubaccountsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsListSubaccountsCall) 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, "accounts/v1/{+provider}:listSubaccounts")
	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{
		"provider": c.provider,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.listSubaccounts", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.listSubaccounts" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListSubAccountsResponse.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 *AccountsListSubaccountsCall) Do(opts ...googleapi.CallOption) (*ListSubAccountsResponse, 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 := &ListSubAccountsResponse{
		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", "merchantapi.accounts.listSubaccounts", "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 *AccountsListSubaccountsCall) Pages(ctx context.Context, f func(*ListSubAccountsResponse) 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 AccountsPatchCall struct {
	s          *APIService
	name       string
	account    *Account
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Patch: Updates an account regardless of its type: standalone, advanced
// account or sub-account. Executing this method requires admin access.
//
//   - name: Identifier. The resource name of the account. Format:
//     `accounts/{account}`.
func (r *AccountsService) Patch(name string, account *Account) *AccountsPatchCall {
	c := &AccountsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.account = account
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `account_name` - `adult_content` - `language_code` -
// `time_zone`
func (c *AccountsPatchCall) UpdateMask(updateMask string) *AccountsPatchCall {
	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 *AccountsPatchCall) Fields(s ...googleapi.Field) *AccountsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsPatchCall) Context(ctx context.Context) *AccountsPatchCall {
	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 *AccountsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.account)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Account.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 *AccountsPatchCall) Do(opts ...googleapi.CallOption) (*Account, 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 := &Account{
		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", "merchantapi.accounts.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetAutofeedSettings: Retrieves the autofeed settings of an account.
//
//   - name: The resource name of the autofeed settings. Format:
//     `accounts/{account}/autofeedSettings`.
func (r *AccountsAutofeedSettingsService) GetAutofeedSettings(name string) *AccountsAutofeedSettingsGetAutofeedSettingsCall {
	c := &AccountsAutofeedSettingsGetAutofeedSettingsCall{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 *AccountsAutofeedSettingsGetAutofeedSettingsCall) Fields(s ...googleapi.Field) *AccountsAutofeedSettingsGetAutofeedSettingsCall {
	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 *AccountsAutofeedSettingsGetAutofeedSettingsCall) IfNoneMatch(entityTag string) *AccountsAutofeedSettingsGetAutofeedSettingsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsAutofeedSettingsGetAutofeedSettingsCall) Context(ctx context.Context) *AccountsAutofeedSettingsGetAutofeedSettingsCall {
	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 *AccountsAutofeedSettingsGetAutofeedSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsAutofeedSettingsGetAutofeedSettingsCall) 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, "accounts/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", "merchantapi.accounts.autofeedSettings.getAutofeedSettings", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.autofeedSettings.getAutofeedSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *AutofeedSettings.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 *AccountsAutofeedSettingsGetAutofeedSettingsCall) Do(opts ...googleapi.CallOption) (*AutofeedSettings, 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 := &AutofeedSettings{
		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", "merchantapi.accounts.autofeedSettings.getAutofeedSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsAutofeedSettingsUpdateAutofeedSettingsCall struct {
	s                *APIService
	name             string
	autofeedsettings *AutofeedSettings
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// UpdateAutofeedSettings: Updates the autofeed settings of an account.
//
//   - name: Identifier. The resource name of the autofeed settings. Format:
//     `accounts/{account}/autofeedSettings`.
func (r *AccountsAutofeedSettingsService) UpdateAutofeedSettings(name string, autofeedsettings *AutofeedSettings) *AccountsAutofeedSettingsUpdateAutofeedSettingsCall {
	c := &AccountsAutofeedSettingsUpdateAutofeedSettingsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.autofeedsettings = autofeedsettings
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. List of
// fields being updated.
func (c *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) UpdateMask(updateMask string) *AccountsAutofeedSettingsUpdateAutofeedSettingsCall {
	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 *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) Fields(s ...googleapi.Field) *AccountsAutofeedSettingsUpdateAutofeedSettingsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) Context(ctx context.Context) *AccountsAutofeedSettingsUpdateAutofeedSettingsCall {
	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 *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.autofeedsettings)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.autofeedSettings.updateAutofeedSettings", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.autofeedSettings.updateAutofeedSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *AutofeedSettings.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 *AccountsAutofeedSettingsUpdateAutofeedSettingsCall) Do(opts ...googleapi.CallOption) (*AutofeedSettings, 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 := &AutofeedSettings{
		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", "merchantapi.accounts.autofeedSettings.updateAutofeedSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetAutomaticImprovements: Retrieves the automatic improvements of an
// account.
//
//   - name: The resource name of the automatic improvements. Format:
//     `accounts/{account}/automaticImprovements`.
func (r *AccountsAutomaticImprovementsService) GetAutomaticImprovements(name string) *AccountsAutomaticImprovementsGetAutomaticImprovementsCall {
	c := &AccountsAutomaticImprovementsGetAutomaticImprovementsCall{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 *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) Fields(s ...googleapi.Field) *AccountsAutomaticImprovementsGetAutomaticImprovementsCall {
	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 *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) IfNoneMatch(entityTag string) *AccountsAutomaticImprovementsGetAutomaticImprovementsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) Context(ctx context.Context) *AccountsAutomaticImprovementsGetAutomaticImprovementsCall {
	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 *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) 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, "accounts/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", "merchantapi.accounts.automaticImprovements.getAutomaticImprovements", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.automaticImprovements.getAutomaticImprovements" call.
// Any non-2xx status code is an error. Response headers are in either
// *AutomaticImprovements.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 *AccountsAutomaticImprovementsGetAutomaticImprovementsCall) Do(opts ...googleapi.CallOption) (*AutomaticImprovements, 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 := &AutomaticImprovements{
		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", "merchantapi.accounts.automaticImprovements.getAutomaticImprovements", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall struct {
	s                     *APIService
	name                  string
	automaticimprovements *AutomaticImprovements
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// UpdateAutomaticImprovements: Updates the automatic improvements of an
// account.
//
//   - name: Identifier. The resource name of the automatic improvements. Format:
//     `accounts/{account}/automaticImprovements`.
func (r *AccountsAutomaticImprovementsService) UpdateAutomaticImprovements(name string, automaticimprovements *AutomaticImprovements) *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall {
	c := &AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.automaticimprovements = automaticimprovements
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. List of
// fields being updated. The following fields are supported (in both
// `snake_case` and `lowerCamelCase`): - `item_updates` -
// `item_updates.account_level_settings` - `image_improvements` -
// `image_improvements.account_level_settings` - `shipping_improvements` -
// `shipping_improvements.allow_shipping_improvements`
func (c *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) UpdateMask(updateMask string) *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall {
	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 *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) Fields(s ...googleapi.Field) *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) Context(ctx context.Context) *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall {
	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 *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.automaticimprovements)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.automaticImprovements.updateAutomaticImprovements", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.automaticImprovements.updateAutomaticImprovements" call.
// Any non-2xx status code is an error. Response headers are in either
// *AutomaticImprovements.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 *AccountsAutomaticImprovementsUpdateAutomaticImprovementsCall) Do(opts ...googleapi.CallOption) (*AutomaticImprovements, 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 := &AutomaticImprovements{
		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", "merchantapi.accounts.automaticImprovements.updateAutomaticImprovements", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetBusinessIdentity: Retrieves the business identity of an account.
//
//   - name: The resource name of the business identity. Format:
//     `accounts/{account}/businessIdentity`. For example,
//     `accounts/123456/businessIdentity`.
func (r *AccountsBusinessIdentityService) GetBusinessIdentity(name string) *AccountsBusinessIdentityGetBusinessIdentityCall {
	c := &AccountsBusinessIdentityGetBusinessIdentityCall{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 *AccountsBusinessIdentityGetBusinessIdentityCall) Fields(s ...googleapi.Field) *AccountsBusinessIdentityGetBusinessIdentityCall {
	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 *AccountsBusinessIdentityGetBusinessIdentityCall) IfNoneMatch(entityTag string) *AccountsBusinessIdentityGetBusinessIdentityCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsBusinessIdentityGetBusinessIdentityCall) Context(ctx context.Context) *AccountsBusinessIdentityGetBusinessIdentityCall {
	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 *AccountsBusinessIdentityGetBusinessIdentityCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsBusinessIdentityGetBusinessIdentityCall) 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, "accounts/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", "merchantapi.accounts.businessIdentity.getBusinessIdentity", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.businessIdentity.getBusinessIdentity" call.
// Any non-2xx status code is an error. Response headers are in either
// *BusinessIdentity.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 *AccountsBusinessIdentityGetBusinessIdentityCall) Do(opts ...googleapi.CallOption) (*BusinessIdentity, 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 := &BusinessIdentity{
		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", "merchantapi.accounts.businessIdentity.getBusinessIdentity", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsBusinessIdentityUpdateBusinessIdentityCall struct {
	s                *APIService
	name             string
	businessidentity *BusinessIdentity
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// UpdateBusinessIdentity: Updates the business identity of an account.
// Executing this method requires admin access.
//
//   - name: Identifier. The resource name of the business identity. Format:
//     `accounts/{account}/businessIdentity`.
func (r *AccountsBusinessIdentityService) UpdateBusinessIdentity(name string, businessidentity *BusinessIdentity) *AccountsBusinessIdentityUpdateBusinessIdentityCall {
	c := &AccountsBusinessIdentityUpdateBusinessIdentityCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.businessidentity = businessidentity
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `black_owned` - `latino_owned` - `promotions_consent` -
// `small_business` - `veteran_owned` - `women_owned`
func (c *AccountsBusinessIdentityUpdateBusinessIdentityCall) UpdateMask(updateMask string) *AccountsBusinessIdentityUpdateBusinessIdentityCall {
	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 *AccountsBusinessIdentityUpdateBusinessIdentityCall) Fields(s ...googleapi.Field) *AccountsBusinessIdentityUpdateBusinessIdentityCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsBusinessIdentityUpdateBusinessIdentityCall) Context(ctx context.Context) *AccountsBusinessIdentityUpdateBusinessIdentityCall {
	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 *AccountsBusinessIdentityUpdateBusinessIdentityCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsBusinessIdentityUpdateBusinessIdentityCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.businessidentity)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.businessIdentity.updateBusinessIdentity", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.businessIdentity.updateBusinessIdentity" call.
// Any non-2xx status code is an error. Response headers are in either
// *BusinessIdentity.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 *AccountsBusinessIdentityUpdateBusinessIdentityCall) Do(opts ...googleapi.CallOption) (*BusinessIdentity, 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 := &BusinessIdentity{
		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", "merchantapi.accounts.businessIdentity.updateBusinessIdentity", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetBusinessInfo: Retrieves the business info of an account.
//
//   - name: The resource name of the business info. Format:
//     `accounts/{account}/businessInfo`. For example,
//     `accounts/123456/businessInfo`.
func (r *AccountsBusinessInfoService) GetBusinessInfo(name string) *AccountsBusinessInfoGetBusinessInfoCall {
	c := &AccountsBusinessInfoGetBusinessInfoCall{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 *AccountsBusinessInfoGetBusinessInfoCall) Fields(s ...googleapi.Field) *AccountsBusinessInfoGetBusinessInfoCall {
	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 *AccountsBusinessInfoGetBusinessInfoCall) IfNoneMatch(entityTag string) *AccountsBusinessInfoGetBusinessInfoCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsBusinessInfoGetBusinessInfoCall) Context(ctx context.Context) *AccountsBusinessInfoGetBusinessInfoCall {
	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 *AccountsBusinessInfoGetBusinessInfoCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsBusinessInfoGetBusinessInfoCall) 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, "accounts/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", "merchantapi.accounts.businessInfo.getBusinessInfo", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.businessInfo.getBusinessInfo" call.
// Any non-2xx status code is an error. Response headers are in either
// *BusinessInfo.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 *AccountsBusinessInfoGetBusinessInfoCall) Do(opts ...googleapi.CallOption) (*BusinessInfo, 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 := &BusinessInfo{
		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", "merchantapi.accounts.businessInfo.getBusinessInfo", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsBusinessInfoUpdateBusinessInfoCall struct {
	s            *APIService
	name         string
	businessinfo *BusinessInfo
	urlParams_   gensupport.URLParams
	ctx_         context.Context
	header_      http.Header
}

// UpdateBusinessInfo: Updates the business info of an account. Executing this
// method requires admin access.
//
//   - name: Identifier. The resource name of the business info. Format:
//     `accounts/{account}/businessInfo`.
func (r *AccountsBusinessInfoService) UpdateBusinessInfo(name string, businessinfo *BusinessInfo) *AccountsBusinessInfoUpdateBusinessInfoCall {
	c := &AccountsBusinessInfoUpdateBusinessInfoCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.businessinfo = businessinfo
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `address` - `customer_service` -
// `korean_business_registration_number`
func (c *AccountsBusinessInfoUpdateBusinessInfoCall) UpdateMask(updateMask string) *AccountsBusinessInfoUpdateBusinessInfoCall {
	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 *AccountsBusinessInfoUpdateBusinessInfoCall) Fields(s ...googleapi.Field) *AccountsBusinessInfoUpdateBusinessInfoCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsBusinessInfoUpdateBusinessInfoCall) Context(ctx context.Context) *AccountsBusinessInfoUpdateBusinessInfoCall {
	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 *AccountsBusinessInfoUpdateBusinessInfoCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsBusinessInfoUpdateBusinessInfoCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.businessinfo)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.businessInfo.updateBusinessInfo", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.businessInfo.updateBusinessInfo" call.
// Any non-2xx status code is an error. Response headers are in either
// *BusinessInfo.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 *AccountsBusinessInfoUpdateBusinessInfoCall) Do(opts ...googleapi.CallOption) (*BusinessInfo, 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 := &BusinessInfo{
		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", "merchantapi.accounts.businessInfo.updateBusinessInfo", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall struct {
	s            *APIService
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetAccountForGcpRegistration: Retrieves the merchant account that the
// calling GCP is registered with.
func (r *AccountsDeveloperRegistrationService) GetAccountForGcpRegistration() *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall {
	c := &AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	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 *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) Fields(s ...googleapi.Field) *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall {
	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 *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) IfNoneMatch(entityTag string) *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) Context(ctx context.Context) *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall {
	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 *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) 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, "accounts/v1/accounts:getAccountForGcpRegistration")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.developerRegistration.getAccountForGcpRegistration", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.developerRegistration.getAccountForGcpRegistration" call.
// Any non-2xx status code is an error. Response headers are in either
// *GetAccountForGcpRegistrationResponse.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 *AccountsDeveloperRegistrationGetAccountForGcpRegistrationCall) Do(opts ...googleapi.CallOption) (*GetAccountForGcpRegistrationResponse, 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 := &GetAccountForGcpRegistrationResponse{
		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", "merchantapi.accounts.developerRegistration.getAccountForGcpRegistration", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetDeveloperRegistration: Retrieves a developer registration for a merchant.
//
// - name: The `name` (ID) of the developer registration.
func (r *AccountsDeveloperRegistrationService) GetDeveloperRegistration(name string) *AccountsDeveloperRegistrationGetDeveloperRegistrationCall {
	c := &AccountsDeveloperRegistrationGetDeveloperRegistrationCall{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 *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) Fields(s ...googleapi.Field) *AccountsDeveloperRegistrationGetDeveloperRegistrationCall {
	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 *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) IfNoneMatch(entityTag string) *AccountsDeveloperRegistrationGetDeveloperRegistrationCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) Context(ctx context.Context) *AccountsDeveloperRegistrationGetDeveloperRegistrationCall {
	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 *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) 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, "accounts/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", "merchantapi.accounts.developerRegistration.getDeveloperRegistration", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.developerRegistration.getDeveloperRegistration" call.
// Any non-2xx status code is an error. Response headers are in either
// *DeveloperRegistration.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 *AccountsDeveloperRegistrationGetDeveloperRegistrationCall) Do(opts ...googleapi.CallOption) (*DeveloperRegistration, 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 := &DeveloperRegistration{
		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", "merchantapi.accounts.developerRegistration.getDeveloperRegistration", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsDeveloperRegistrationRegisterGcpCall struct {
	s                  *APIService
	name               string
	registergcprequest *RegisterGcpRequest
	urlParams_         gensupport.URLParams
	ctx_               context.Context
	header_            http.Header
}

// RegisterGcp: Registers the GCP used for the API call to the shopping account
// passed in the request. Will create a user with an "API developer" and add
// the "developer_email" as a contact with "API notifications" email preference
// on.
//
//   - name: The name of the developer registration to be created for the
//     merchant account that the GCP will be registered with. Format:
//     `accounts/{account}/developerRegistration`.
func (r *AccountsDeveloperRegistrationService) RegisterGcp(name string, registergcprequest *RegisterGcpRequest) *AccountsDeveloperRegistrationRegisterGcpCall {
	c := &AccountsDeveloperRegistrationRegisterGcpCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.registergcprequest = registergcprequest
	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 *AccountsDeveloperRegistrationRegisterGcpCall) Fields(s ...googleapi.Field) *AccountsDeveloperRegistrationRegisterGcpCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsDeveloperRegistrationRegisterGcpCall) Context(ctx context.Context) *AccountsDeveloperRegistrationRegisterGcpCall {
	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 *AccountsDeveloperRegistrationRegisterGcpCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsDeveloperRegistrationRegisterGcpCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.registergcprequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:registerGcp")
	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", "merchantapi.accounts.developerRegistration.registerGcp", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.developerRegistration.registerGcp" call.
// Any non-2xx status code is an error. Response headers are in either
// *DeveloperRegistration.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 *AccountsDeveloperRegistrationRegisterGcpCall) Do(opts ...googleapi.CallOption) (*DeveloperRegistration, 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 := &DeveloperRegistration{
		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", "merchantapi.accounts.developerRegistration.registerGcp", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsDeveloperRegistrationUnregisterGcpCall struct {
	s                    *APIService
	name                 string
	unregistergcprequest *UnregisterGcpRequest
	urlParams_           gensupport.URLParams
	ctx_                 context.Context
	header_              http.Header
}

// UnregisterGcp: Unregister the calling GCP from the calling shopping account.
// Note that the GCP will still be able to access the API for at most 1 day
// from the unregister succussful call.
//
//   - name: The name of the developer registration to be created for the
//     merchant account that the GCP will be registered with. Format:
//     `accounts/{account}/developerRegistration`.
func (r *AccountsDeveloperRegistrationService) UnregisterGcp(name string, unregistergcprequest *UnregisterGcpRequest) *AccountsDeveloperRegistrationUnregisterGcpCall {
	c := &AccountsDeveloperRegistrationUnregisterGcpCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.unregistergcprequest = unregistergcprequest
	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 *AccountsDeveloperRegistrationUnregisterGcpCall) Fields(s ...googleapi.Field) *AccountsDeveloperRegistrationUnregisterGcpCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsDeveloperRegistrationUnregisterGcpCall) Context(ctx context.Context) *AccountsDeveloperRegistrationUnregisterGcpCall {
	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 *AccountsDeveloperRegistrationUnregisterGcpCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsDeveloperRegistrationUnregisterGcpCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.unregistergcprequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:unregisterGcp")
	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", "merchantapi.accounts.developerRegistration.unregisterGcp", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.developerRegistration.unregisterGcp" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsDeveloperRegistrationUnregisterGcpCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.developerRegistration.unregisterGcp", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetEmailPreferences: Returns the email preferences for a Merchant Center
// account user. This service only permits retrieving and updating email
// preferences for the authenticated user. Use the
// name=accounts/*/users/me/emailPreferences alias to get preferences for the
// authenticated user.
//
//   - name: The name of the `EmailPreferences` resource. Format:
//     `accounts/{account}/users/{email}/emailPreferences`.
func (r *AccountsEmailPreferencesService) GetEmailPreferences(name string) *AccountsEmailPreferencesGetEmailPreferencesCall {
	c := &AccountsEmailPreferencesGetEmailPreferencesCall{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 *AccountsEmailPreferencesGetEmailPreferencesCall) Fields(s ...googleapi.Field) *AccountsEmailPreferencesGetEmailPreferencesCall {
	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 *AccountsEmailPreferencesGetEmailPreferencesCall) IfNoneMatch(entityTag string) *AccountsEmailPreferencesGetEmailPreferencesCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsEmailPreferencesGetEmailPreferencesCall) Context(ctx context.Context) *AccountsEmailPreferencesGetEmailPreferencesCall {
	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 *AccountsEmailPreferencesGetEmailPreferencesCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsEmailPreferencesGetEmailPreferencesCall) 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, "accounts/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", "merchantapi.accounts.emailPreferences.getEmailPreferences", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.emailPreferences.getEmailPreferences" call.
// Any non-2xx status code is an error. Response headers are in either
// *EmailPreferences.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 *AccountsEmailPreferencesGetEmailPreferencesCall) Do(opts ...googleapi.CallOption) (*EmailPreferences, 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 := &EmailPreferences{
		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", "merchantapi.accounts.emailPreferences.getEmailPreferences", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsEmailPreferencesUpdateEmailPreferencesCall struct {
	s                *APIService
	name             string
	emailpreferences *EmailPreferences
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// UpdateEmailPreferences: Updates the email preferences for a Merchant Center
// account user. Advanced account users should specify the advanced account
// rather than a sub-account of the advanced account. Preferences which are not
// explicitly selected in the update mask will not be updated. It is invalid
// for updates to specify an UNCONFIRMED opt-in status value. Use the
// name=accounts/*/users/me/emailPreferences alias to update preferences for
// the authenticated user.
//
//   - name: Identifier. The name of the EmailPreferences. The endpoint is only
//     supported for the authenticated user.
func (r *AccountsEmailPreferencesService) UpdateEmailPreferences(name string, emailpreferences *EmailPreferences) *AccountsEmailPreferencesUpdateEmailPreferencesCall {
	c := &AccountsEmailPreferencesUpdateEmailPreferencesCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.emailpreferences = emailpreferences
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. List of
// fields being updated. The following fields are supported (in both
// `snake_case` and `lowerCamelCase`): - `news_and_tips`
func (c *AccountsEmailPreferencesUpdateEmailPreferencesCall) UpdateMask(updateMask string) *AccountsEmailPreferencesUpdateEmailPreferencesCall {
	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 *AccountsEmailPreferencesUpdateEmailPreferencesCall) Fields(s ...googleapi.Field) *AccountsEmailPreferencesUpdateEmailPreferencesCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsEmailPreferencesUpdateEmailPreferencesCall) Context(ctx context.Context) *AccountsEmailPreferencesUpdateEmailPreferencesCall {
	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 *AccountsEmailPreferencesUpdateEmailPreferencesCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsEmailPreferencesUpdateEmailPreferencesCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.emailpreferences)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.emailPreferences.updateEmailPreferences", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.emailPreferences.updateEmailPreferences" call.
// Any non-2xx status code is an error. Response headers are in either
// *EmailPreferences.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 *AccountsEmailPreferencesUpdateEmailPreferencesCall) Do(opts ...googleapi.CallOption) (*EmailPreferences, 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 := &EmailPreferences{
		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", "merchantapi.accounts.emailPreferences.updateEmailPreferences", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsGbpAccountsLinkGbpAccountCall struct {
	s                     *APIService
	parent                string
	linkgbpaccountrequest *LinkGbpAccountRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// LinkGbpAccount: Link the specified merchant to a GBP account for all
// countries. To run this method, you must have admin access to the Merchant
// Center account. If you don't have admin access, the request fails with the
// error message `User is not an administrator of account {ACCOUNT_ID}`.
//
//   - parent: The name of the parent resource to which the GBP account is
//     linked. Format: `accounts/{account}`.
func (r *AccountsGbpAccountsService) LinkGbpAccount(parent string, linkgbpaccountrequest *LinkGbpAccountRequest) *AccountsGbpAccountsLinkGbpAccountCall {
	c := &AccountsGbpAccountsLinkGbpAccountCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.linkgbpaccountrequest = linkgbpaccountrequest
	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 *AccountsGbpAccountsLinkGbpAccountCall) Fields(s ...googleapi.Field) *AccountsGbpAccountsLinkGbpAccountCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsGbpAccountsLinkGbpAccountCall) Context(ctx context.Context) *AccountsGbpAccountsLinkGbpAccountCall {
	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 *AccountsGbpAccountsLinkGbpAccountCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsGbpAccountsLinkGbpAccountCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.linkgbpaccountrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/gbpAccounts:linkGbpAccount")
	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", "merchantapi.accounts.gbpAccounts.linkGbpAccount", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.gbpAccounts.linkGbpAccount" call.
// Any non-2xx status code is an error. Response headers are in either
// *LinkGbpAccountResponse.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 *AccountsGbpAccountsLinkGbpAccountCall) Do(opts ...googleapi.CallOption) (*LinkGbpAccountResponse, 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 := &LinkGbpAccountResponse{
		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", "merchantapi.accounts.gbpAccounts.linkGbpAccount", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: List the GBP accounts for a given merchant.
//
//   - parent: The name of the parent resource under which the GBP accounts are
//     listed. Format: `accounts/{account}`.
func (r *AccountsGbpAccountsService) List(parent string) *AccountsGbpAccountsListCall {
	c := &AccountsGbpAccountsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// `GbpAccount` resources to return. The service returns fewer than this value
// if the number of gbp accounts is less that than the `pageSize`. The default
// value is 50. The maximum value is 1000; If a value higher than the maximum
// is specified, then the `pageSize` will default to the maximum.
func (c *AccountsGbpAccountsListCall) PageSize(pageSize int64) *AccountsGbpAccountsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListGbpAccounts` call. Provide the page token to retrieve
// the subsequent page. When paginating, all other parameters provided to
// `ListGbpAccounts` must match the call that provided the page token.
func (c *AccountsGbpAccountsListCall) PageToken(pageToken string) *AccountsGbpAccountsListCall {
	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 *AccountsGbpAccountsListCall) Fields(s ...googleapi.Field) *AccountsGbpAccountsListCall {
	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 *AccountsGbpAccountsListCall) IfNoneMatch(entityTag string) *AccountsGbpAccountsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsGbpAccountsListCall) Context(ctx context.Context) *AccountsGbpAccountsListCall {
	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 *AccountsGbpAccountsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsGbpAccountsListCall) 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, "accounts/v1/{+parent}/gbpAccounts")
	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", "merchantapi.accounts.gbpAccounts.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.gbpAccounts.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListGbpAccountsResponse.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 *AccountsGbpAccountsListCall) Do(opts ...googleapi.CallOption) (*ListGbpAccountsResponse, 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 := &ListGbpAccountsResponse{
		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", "merchantapi.accounts.gbpAccounts.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 *AccountsGbpAccountsListCall) Pages(ctx context.Context, f func(*ListGbpAccountsResponse) 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 AccountsHomepageClaimCall struct {
	s                    *APIService
	name                 string
	claimhomepagerequest *ClaimHomepageRequest
	urlParams_           gensupport.URLParams
	ctx_                 context.Context
	header_              http.Header
}

// Claim: Claims a store's homepage. Executing this method requires admin
// access. If the homepage is already claimed, this will recheck the
// verification (unless the business is exempted from claiming, which also
// exempts from verification) and return a successful response. If ownership
// can no longer be verified, it will return an error, but it won't clear the
// claim. In case of failure, a canonical error message is returned: *
// PERMISSION_DENIED: User doesn't have the necessary permissions on this
// Merchant Center account. * FAILED_PRECONDITION: - The account is not a
// Merchant Center account. - Merchant Center account doesn't have a homepage.
// - Claiming failed (in this case the error message contains more details).
//
//   - name: The name of the homepage to claim. Format:
//     `accounts/{account}/homepage`.
func (r *AccountsHomepageService) Claim(name string, claimhomepagerequest *ClaimHomepageRequest) *AccountsHomepageClaimCall {
	c := &AccountsHomepageClaimCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.claimhomepagerequest = claimhomepagerequest
	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 *AccountsHomepageClaimCall) Fields(s ...googleapi.Field) *AccountsHomepageClaimCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsHomepageClaimCall) Context(ctx context.Context) *AccountsHomepageClaimCall {
	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 *AccountsHomepageClaimCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsHomepageClaimCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.claimhomepagerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:claim")
	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", "merchantapi.accounts.homepage.claim", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.homepage.claim" call.
// Any non-2xx status code is an error. Response headers are in either
// *Homepage.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 *AccountsHomepageClaimCall) Do(opts ...googleapi.CallOption) (*Homepage, 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 := &Homepage{
		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", "merchantapi.accounts.homepage.claim", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetHomepage: Retrieves a store's homepage.
//
//   - name: The name of the homepage to retrieve. Format:
//     `accounts/{account}/homepage`.
func (r *AccountsHomepageService) GetHomepage(name string) *AccountsHomepageGetHomepageCall {
	c := &AccountsHomepageGetHomepageCall{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 *AccountsHomepageGetHomepageCall) Fields(s ...googleapi.Field) *AccountsHomepageGetHomepageCall {
	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 *AccountsHomepageGetHomepageCall) IfNoneMatch(entityTag string) *AccountsHomepageGetHomepageCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsHomepageGetHomepageCall) Context(ctx context.Context) *AccountsHomepageGetHomepageCall {
	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 *AccountsHomepageGetHomepageCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsHomepageGetHomepageCall) 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, "accounts/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", "merchantapi.accounts.homepage.getHomepage", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.homepage.getHomepage" call.
// Any non-2xx status code is an error. Response headers are in either
// *Homepage.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 *AccountsHomepageGetHomepageCall) Do(opts ...googleapi.CallOption) (*Homepage, 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 := &Homepage{
		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", "merchantapi.accounts.homepage.getHomepage", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsHomepageUnclaimCall struct {
	s                      *APIService
	name                   string
	unclaimhomepagerequest *UnclaimHomepageRequest
	urlParams_             gensupport.URLParams
	ctx_                   context.Context
	header_                http.Header
}

// Unclaim: Unclaims a store's homepage. Executing this method requires admin
// access.
//
//   - name: The name of the homepage to unclaim. Format:
//     `accounts/{account}/homepage`.
func (r *AccountsHomepageService) Unclaim(name string, unclaimhomepagerequest *UnclaimHomepageRequest) *AccountsHomepageUnclaimCall {
	c := &AccountsHomepageUnclaimCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.unclaimhomepagerequest = unclaimhomepagerequest
	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 *AccountsHomepageUnclaimCall) Fields(s ...googleapi.Field) *AccountsHomepageUnclaimCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsHomepageUnclaimCall) Context(ctx context.Context) *AccountsHomepageUnclaimCall {
	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 *AccountsHomepageUnclaimCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsHomepageUnclaimCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.unclaimhomepagerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:unclaim")
	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", "merchantapi.accounts.homepage.unclaim", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.homepage.unclaim" call.
// Any non-2xx status code is an error. Response headers are in either
// *Homepage.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 *AccountsHomepageUnclaimCall) Do(opts ...googleapi.CallOption) (*Homepage, 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 := &Homepage{
		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", "merchantapi.accounts.homepage.unclaim", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsHomepageUpdateHomepageCall struct {
	s          *APIService
	name       string
	homepage   *Homepage
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// UpdateHomepage: Updates a store's homepage. Executing this method requires
// admin access.
//
//   - name: Identifier. The resource name of the store's homepage. Format:
//     `accounts/{account}/homepage`.
func (r *AccountsHomepageService) UpdateHomepage(name string, homepage *Homepage) *AccountsHomepageUpdateHomepageCall {
	c := &AccountsHomepageUpdateHomepageCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.homepage = homepage
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `uri`
func (c *AccountsHomepageUpdateHomepageCall) UpdateMask(updateMask string) *AccountsHomepageUpdateHomepageCall {
	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 *AccountsHomepageUpdateHomepageCall) Fields(s ...googleapi.Field) *AccountsHomepageUpdateHomepageCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsHomepageUpdateHomepageCall) Context(ctx context.Context) *AccountsHomepageUpdateHomepageCall {
	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 *AccountsHomepageUpdateHomepageCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsHomepageUpdateHomepageCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.homepage)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.homepage.updateHomepage", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.homepage.updateHomepage" call.
// Any non-2xx status code is an error. Response headers are in either
// *Homepage.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 *AccountsHomepageUpdateHomepageCall) Do(opts ...googleapi.CallOption) (*Homepage, 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 := &Homepage{
		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", "merchantapi.accounts.homepage.updateHomepage", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: Lists all account issues of a Merchant Center account. When called on
// a multi-client account, this method only returns issues belonging to that
// account, not its sub-accounts. To retrieve issues for sub-accounts, you must
// first call the accounts.listSubaccounts method to obtain a list of
// sub-accounts, and then call `accounts.issues.list` for each sub-account
// individually.
//
//   - parent: The parent, which owns this collection of issues. Format:
//     `accounts/{account}`.
func (r *AccountsIssuesService) List(parent string) *AccountsIssuesListCall {
	c := &AccountsIssuesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// LanguageCode sets the optional parameter "languageCode": The issues in the
// response will have human-readable fields in the given language. The format
// is BCP-47 (https://tools.ietf.org/html/bcp47), such as `en-US` or `sr-Latn`.
// If not value is provided, `en-US` will be used.
func (c *AccountsIssuesListCall) LanguageCode(languageCode string) *AccountsIssuesListCall {
	c.urlParams_.Set("languageCode", languageCode)
	return c
}

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

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

// TimeZone sets the optional parameter "timeZone": The IANA
// (https://www.iana.org/time-zones) timezone used to localize times in
// human-readable fields. For example 'America/Los_Angeles'. If not set,
// 'America/Los_Angeles' will be used.
func (c *AccountsIssuesListCall) TimeZone(timeZone string) *AccountsIssuesListCall {
	c.urlParams_.Set("timeZone", timeZone)
	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 *AccountsIssuesListCall) Fields(s ...googleapi.Field) *AccountsIssuesListCall {
	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 *AccountsIssuesListCall) IfNoneMatch(entityTag string) *AccountsIssuesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsIssuesListCall) Context(ctx context.Context) *AccountsIssuesListCall {
	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 *AccountsIssuesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsIssuesListCall) 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, "accounts/v1/{+parent}/issues")
	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", "merchantapi.accounts.issues.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.issues.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListAccountIssuesResponse.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 *AccountsIssuesListCall) Do(opts ...googleapi.CallOption) (*ListAccountIssuesResponse, 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 := &ListAccountIssuesResponse{
		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", "merchantapi.accounts.issues.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 *AccountsIssuesListCall) Pages(ctx context.Context, f func(*ListAccountIssuesResponse) 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 AccountsOmnichannelSettingsCreateCall struct {
	s                  *APIService
	parent             string
	omnichannelsetting *OmnichannelSetting
	urlParams_         gensupport.URLParams
	ctx_               context.Context
	header_            http.Header
}

// Create: Create the omnichannel settings for a given merchant.
//
//   - parent: The parent resource where this omnichannel setting will be
//     created. Format: `accounts/{account}`.
func (r *AccountsOmnichannelSettingsService) Create(parent string, omnichannelsetting *OmnichannelSetting) *AccountsOmnichannelSettingsCreateCall {
	c := &AccountsOmnichannelSettingsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.omnichannelsetting = omnichannelsetting
	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 *AccountsOmnichannelSettingsCreateCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsCreateCall) Context(ctx context.Context) *AccountsOmnichannelSettingsCreateCall {
	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 *AccountsOmnichannelSettingsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.omnichannelsetting)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/omnichannelSettings")
	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", "merchantapi.accounts.omnichannelSettings.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *OmnichannelSetting.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 *AccountsOmnichannelSettingsCreateCall) Do(opts ...googleapi.CallOption) (*OmnichannelSetting, 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 := &OmnichannelSetting{
		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", "merchantapi.accounts.omnichannelSettings.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Get the omnichannel settings for a given merchant.
//
//   - name: The name of the omnichannel setting to retrieve. Format:
//     `accounts/{account}/omnichannelSettings/{omnichannel_setting}`.
func (r *AccountsOmnichannelSettingsService) Get(name string) *AccountsOmnichannelSettingsGetCall {
	c := &AccountsOmnichannelSettingsGetCall{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 *AccountsOmnichannelSettingsGetCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsGetCall {
	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 *AccountsOmnichannelSettingsGetCall) IfNoneMatch(entityTag string) *AccountsOmnichannelSettingsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsGetCall) Context(ctx context.Context) *AccountsOmnichannelSettingsGetCall {
	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 *AccountsOmnichannelSettingsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsGetCall) 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, "accounts/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", "merchantapi.accounts.omnichannelSettings.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *OmnichannelSetting.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 *AccountsOmnichannelSettingsGetCall) Do(opts ...googleapi.CallOption) (*OmnichannelSetting, 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 := &OmnichannelSetting{
		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", "merchantapi.accounts.omnichannelSettings.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: List all the omnichannel settings for a given merchant.
//
//   - parent: The parent, which owns this collection of omnichannel settings.
//     Format: `accounts/{account}`.
func (r *AccountsOmnichannelSettingsService) List(parent string) *AccountsOmnichannelSettingsListCall {
	c := &AccountsOmnichannelSettingsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

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

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListOmnichannelSettings` call. Provide this to retrieve the
// subsequent page. When paginating, all other parameters provided to
// `ListOmnichannelSettings` must match the call that provided the page token.
func (c *AccountsOmnichannelSettingsListCall) PageToken(pageToken string) *AccountsOmnichannelSettingsListCall {
	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 *AccountsOmnichannelSettingsListCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsListCall {
	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 *AccountsOmnichannelSettingsListCall) IfNoneMatch(entityTag string) *AccountsOmnichannelSettingsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsListCall) Context(ctx context.Context) *AccountsOmnichannelSettingsListCall {
	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 *AccountsOmnichannelSettingsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsListCall) 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, "accounts/v1/{+parent}/omnichannelSettings")
	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", "merchantapi.accounts.omnichannelSettings.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOmnichannelSettingsResponse.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 *AccountsOmnichannelSettingsListCall) Do(opts ...googleapi.CallOption) (*ListOmnichannelSettingsResponse, 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 := &ListOmnichannelSettingsResponse{
		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", "merchantapi.accounts.omnichannelSettings.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 *AccountsOmnichannelSettingsListCall) Pages(ctx context.Context, f func(*ListOmnichannelSettingsResponse) 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 AccountsOmnichannelSettingsPatchCall struct {
	s                  *APIService
	name               string
	omnichannelsetting *OmnichannelSetting
	urlParams_         gensupport.URLParams
	ctx_               context.Context
	header_            http.Header
}

// Patch: Update the omnichannel setting for a given merchant in a given
// country.
//
//   - name: Identifier. The resource name of the omnichannel setting. Format:
//     `accounts/{account}/omnichannelSettings/{omnichannel_setting}`.
func (r *AccountsOmnichannelSettingsService) Patch(name string, omnichannelsetting *OmnichannelSetting) *AccountsOmnichannelSettingsPatchCall {
	c := &AccountsOmnichannelSettingsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.omnichannelsetting = omnichannelsetting
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. The list of
// fields to be updated. The following fields are supported in snake_case only:
// - `lsf_type` - `in_stock` - `pickup` - `odo` - `about` -
// `inventory_verification` Full replacement with wildcard `*`is supported,
// while empty/implied update mask is not.
func (c *AccountsOmnichannelSettingsPatchCall) UpdateMask(updateMask string) *AccountsOmnichannelSettingsPatchCall {
	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 *AccountsOmnichannelSettingsPatchCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsPatchCall) Context(ctx context.Context) *AccountsOmnichannelSettingsPatchCall {
	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 *AccountsOmnichannelSettingsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.omnichannelsetting)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.omnichannelSettings.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *OmnichannelSetting.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 *AccountsOmnichannelSettingsPatchCall) Do(opts ...googleapi.CallOption) (*OmnichannelSetting, 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 := &OmnichannelSetting{
		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", "merchantapi.accounts.omnichannelSettings.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsOmnichannelSettingsRequestInventoryVerificationCall struct {
	s                                   *APIService
	name                                string
	requestinventoryverificationrequest *RequestInventoryVerificationRequest
	urlParams_                          gensupport.URLParams
	ctx_                                context.Context
	header_                             http.Header
}

// RequestInventoryVerification: Requests inventory verification for a given
// merchant in a given country.
//
//   - name: The name of the omnichannel setting to request inventory
//     verification. Format:
//     `accounts/{account}/omnichannelSettings/{omnichannel_setting}`.
func (r *AccountsOmnichannelSettingsService) RequestInventoryVerification(name string, requestinventoryverificationrequest *RequestInventoryVerificationRequest) *AccountsOmnichannelSettingsRequestInventoryVerificationCall {
	c := &AccountsOmnichannelSettingsRequestInventoryVerificationCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.requestinventoryverificationrequest = requestinventoryverificationrequest
	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 *AccountsOmnichannelSettingsRequestInventoryVerificationCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsRequestInventoryVerificationCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsRequestInventoryVerificationCall) Context(ctx context.Context) *AccountsOmnichannelSettingsRequestInventoryVerificationCall {
	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 *AccountsOmnichannelSettingsRequestInventoryVerificationCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsRequestInventoryVerificationCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.requestinventoryverificationrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:requestInventoryVerification")
	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", "merchantapi.accounts.omnichannelSettings.requestInventoryVerification", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.requestInventoryVerification" call.
// Any non-2xx status code is an error. Response headers are in either
// *RequestInventoryVerificationResponse.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 *AccountsOmnichannelSettingsRequestInventoryVerificationCall) Do(opts ...googleapi.CallOption) (*RequestInventoryVerificationResponse, 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 := &RequestInventoryVerificationResponse{
		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", "merchantapi.accounts.omnichannelSettings.requestInventoryVerification", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Find: Find the LFP provider candidates in a given country.
//
//   - parent: The name of the parent resource under which the LFP providers are
//     found. Format:
//     `accounts/{account}/omnichannelSettings/{omnichannel_setting}`.
func (r *AccountsOmnichannelSettingsLfpProvidersService) Find(parent string) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	c := &AccountsOmnichannelSettingsLfpProvidersFindCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// `LfpProvider` resources to return. The service returns fewer than this value
// if the number of lfp providers is less that than the `pageSize`. The default
// value is 50. The maximum value is 1000; If a value higher than the maximum
// is specified, then the `pageSize` will default to the maximum.
func (c *AccountsOmnichannelSettingsLfpProvidersFindCall) PageSize(pageSize int64) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `FindLfpProviders` call. Provide the page token to retrieve
// the subsequent page. When paginating, all other parameters provided to
// `FindLfpProviders` must match the call that provided the page token.
func (c *AccountsOmnichannelSettingsLfpProvidersFindCall) PageToken(pageToken string) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	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 *AccountsOmnichannelSettingsLfpProvidersFindCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	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 *AccountsOmnichannelSettingsLfpProvidersFindCall) IfNoneMatch(entityTag string) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsLfpProvidersFindCall) Context(ctx context.Context) *AccountsOmnichannelSettingsLfpProvidersFindCall {
	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 *AccountsOmnichannelSettingsLfpProvidersFindCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsLfpProvidersFindCall) 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, "accounts/v1/{+parent}/lfpProviders:find")
	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", "merchantapi.accounts.omnichannelSettings.lfpProviders.find", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.lfpProviders.find" call.
// Any non-2xx status code is an error. Response headers are in either
// *FindLfpProvidersResponse.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 *AccountsOmnichannelSettingsLfpProvidersFindCall) Do(opts ...googleapi.CallOption) (*FindLfpProvidersResponse, 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 := &FindLfpProvidersResponse{
		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", "merchantapi.accounts.omnichannelSettings.lfpProviders.find", "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 *AccountsOmnichannelSettingsLfpProvidersFindCall) Pages(ctx context.Context, f func(*FindLfpProvidersResponse) 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 AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall struct {
	s                      *APIService
	name                   string
	linklfpproviderrequest *LinkLfpProviderRequest
	urlParams_             gensupport.URLParams
	ctx_                   context.Context
	header_                http.Header
}

// LinkLfpProvider: Link the specified merchant to a LFP provider for the
// specified country.
//
//   - name: The name of the LFP provider resource to link. Format:
//     `accounts/{account}/omnichannelSettings/{omnichannel_setting}/lfpProviders/
//     {lfp_provider}`. The `lfp_provider` is the LFP provider ID.
func (r *AccountsOmnichannelSettingsLfpProvidersService) LinkLfpProvider(name string, linklfpproviderrequest *LinkLfpProviderRequest) *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall {
	c := &AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.linklfpproviderrequest = linklfpproviderrequest
	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 *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall) Fields(s ...googleapi.Field) *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall) Context(ctx context.Context) *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall {
	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 *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.linklfpproviderrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:linkLfpProvider")
	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", "merchantapi.accounts.omnichannelSettings.lfpProviders.linkLfpProvider", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.omnichannelSettings.lfpProviders.linkLfpProvider" call.
// Any non-2xx status code is an error. Response headers are in either
// *LinkLfpProviderResponse.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 *AccountsOmnichannelSettingsLfpProvidersLinkLfpProviderCall) Do(opts ...googleapi.CallOption) (*LinkLfpProviderResponse, 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 := &LinkLfpProviderResponse{
		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", "merchantapi.accounts.omnichannelSettings.lfpProviders.linkLfpProvider", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsOnlineReturnPoliciesCreateCall struct {
	s                  *APIService
	parent             string
	onlinereturnpolicy *OnlineReturnPolicy
	urlParams_         gensupport.URLParams
	ctx_               context.Context
	header_            http.Header
}

// Create: Creates a new return policy for a given business.
//
//   - parent: The Merchant Center account for which the return policy will be
//     created. Format: `accounts/{account}`.
func (r *AccountsOnlineReturnPoliciesService) Create(parent string, onlinereturnpolicy *OnlineReturnPolicy) *AccountsOnlineReturnPoliciesCreateCall {
	c := &AccountsOnlineReturnPoliciesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.onlinereturnpolicy = onlinereturnpolicy
	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 *AccountsOnlineReturnPoliciesCreateCall) Fields(s ...googleapi.Field) *AccountsOnlineReturnPoliciesCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOnlineReturnPoliciesCreateCall) Context(ctx context.Context) *AccountsOnlineReturnPoliciesCreateCall {
	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 *AccountsOnlineReturnPoliciesCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOnlineReturnPoliciesCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.onlinereturnpolicy)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/onlineReturnPolicies")
	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", "merchantapi.accounts.onlineReturnPolicies.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.onlineReturnPolicies.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *OnlineReturnPolicy.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 *AccountsOnlineReturnPoliciesCreateCall) Do(opts ...googleapi.CallOption) (*OnlineReturnPolicy, 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 := &OnlineReturnPolicy{
		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", "merchantapi.accounts.onlineReturnPolicies.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Delete: Deletes an existing return policy.
//
//   - name: The name of the return policy to delete. Format:
//     `accounts/{account}/onlineReturnPolicies/{return_policy}`.
func (r *AccountsOnlineReturnPoliciesService) Delete(name string) *AccountsOnlineReturnPoliciesDeleteCall {
	c := &AccountsOnlineReturnPoliciesDeleteCall{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 *AccountsOnlineReturnPoliciesDeleteCall) Fields(s ...googleapi.Field) *AccountsOnlineReturnPoliciesDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOnlineReturnPoliciesDeleteCall) Context(ctx context.Context) *AccountsOnlineReturnPoliciesDeleteCall {
	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 *AccountsOnlineReturnPoliciesDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOnlineReturnPoliciesDeleteCall) 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, "accounts/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", "merchantapi.accounts.onlineReturnPolicies.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.onlineReturnPolicies.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsOnlineReturnPoliciesDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.onlineReturnPolicies.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Gets an existing return policy for a given business.
//
//   - name: The name of the return policy to retrieve. Format:
//     `accounts/{account}/onlineReturnPolicies/{return_policy}`.
func (r *AccountsOnlineReturnPoliciesService) Get(name string) *AccountsOnlineReturnPoliciesGetCall {
	c := &AccountsOnlineReturnPoliciesGetCall{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 *AccountsOnlineReturnPoliciesGetCall) Fields(s ...googleapi.Field) *AccountsOnlineReturnPoliciesGetCall {
	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 *AccountsOnlineReturnPoliciesGetCall) IfNoneMatch(entityTag string) *AccountsOnlineReturnPoliciesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOnlineReturnPoliciesGetCall) Context(ctx context.Context) *AccountsOnlineReturnPoliciesGetCall {
	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 *AccountsOnlineReturnPoliciesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOnlineReturnPoliciesGetCall) 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, "accounts/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", "merchantapi.accounts.onlineReturnPolicies.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.onlineReturnPolicies.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *OnlineReturnPolicy.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 *AccountsOnlineReturnPoliciesGetCall) Do(opts ...googleapi.CallOption) (*OnlineReturnPolicy, 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 := &OnlineReturnPolicy{
		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", "merchantapi.accounts.onlineReturnPolicies.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: Lists all existing return policies for a given business.
//
//   - parent: The Merchant Center account for which to list return policies.
//     Format: `accounts/{account}`.
func (r *AccountsOnlineReturnPoliciesService) List(parent string) *AccountsOnlineReturnPoliciesListCall {
	c := &AccountsOnlineReturnPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// `OnlineReturnPolicy` resources to return. The service returns fewer than
// this value if the number of return policies for the given business is less
// that than the `pageSize`. The default value is 10. The maximum value is 100;
// If a value higher than the maximum is specified, then the `pageSize` will
// default to the maximum
func (c *AccountsOnlineReturnPoliciesListCall) PageSize(pageSize int64) *AccountsOnlineReturnPoliciesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListOnlineReturnPolicies` call. Provide the page token to
// retrieve the subsequent page. When paginating, all other parameters provided
// to `ListOnlineReturnPolicies` must match the call that provided the page
// token. The token returned as nextPageToken in the response to the previous
// request.
func (c *AccountsOnlineReturnPoliciesListCall) PageToken(pageToken string) *AccountsOnlineReturnPoliciesListCall {
	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 *AccountsOnlineReturnPoliciesListCall) Fields(s ...googleapi.Field) *AccountsOnlineReturnPoliciesListCall {
	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 *AccountsOnlineReturnPoliciesListCall) IfNoneMatch(entityTag string) *AccountsOnlineReturnPoliciesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsOnlineReturnPoliciesListCall) Context(ctx context.Context) *AccountsOnlineReturnPoliciesListCall {
	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 *AccountsOnlineReturnPoliciesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsOnlineReturnPoliciesListCall) 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, "accounts/v1/{+parent}/onlineReturnPolicies")
	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", "merchantapi.accounts.onlineReturnPolicies.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.onlineReturnPolicies.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOnlineReturnPoliciesResponse.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 *AccountsOnlineReturnPoliciesListCall) Do(opts ...googleapi.CallOption) (*ListOnlineReturnPoliciesResponse, 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 := &ListOnlineReturnPoliciesResponse{
		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", "merchantapi.accounts.onlineReturnPolicies.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 *AccountsOnlineReturnPoliciesListCall) Pages(ctx context.Context, f func(*ListOnlineReturnPoliciesResponse) 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 AccountsProgramsDisableCall struct {
	s                     *APIService
	name                  string
	disableprogramrequest *DisableProgramRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// Disable: Disable participation in the specified program for the account.
//
//   - name: The name of the program for which to disable participation for the
//     given account. Format: `accounts/{account}/programs/{program}`. For
//     example, `accounts/123456/programs/free-listings`.
func (r *AccountsProgramsService) Disable(name string, disableprogramrequest *DisableProgramRequest) *AccountsProgramsDisableCall {
	c := &AccountsProgramsDisableCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.disableprogramrequest = disableprogramrequest
	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 *AccountsProgramsDisableCall) Fields(s ...googleapi.Field) *AccountsProgramsDisableCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsDisableCall) Context(ctx context.Context) *AccountsProgramsDisableCall {
	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 *AccountsProgramsDisableCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsDisableCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.disableprogramrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:disable")
	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", "merchantapi.accounts.programs.disable", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.disable" call.
// Any non-2xx status code is an error. Response headers are in either
// *Program.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 *AccountsProgramsDisableCall) Do(opts ...googleapi.CallOption) (*Program, 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 := &Program{
		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", "merchantapi.accounts.programs.disable", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsProgramsEnableCall struct {
	s                    *APIService
	name                 string
	enableprogramrequest *EnableProgramRequest
	urlParams_           gensupport.URLParams
	ctx_                 context.Context
	header_              http.Header
}

// Enable: Enable participation in the specified program for the account.
//
//   - name: The name of the program for which to enable participation for the
//     given account. Format: `accounts/{account}/programs/{program}`. For
//     example, `accounts/123456/programs/free-listings`.
func (r *AccountsProgramsService) Enable(name string, enableprogramrequest *EnableProgramRequest) *AccountsProgramsEnableCall {
	c := &AccountsProgramsEnableCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.enableprogramrequest = enableprogramrequest
	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 *AccountsProgramsEnableCall) Fields(s ...googleapi.Field) *AccountsProgramsEnableCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsEnableCall) Context(ctx context.Context) *AccountsProgramsEnableCall {
	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 *AccountsProgramsEnableCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsEnableCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.enableprogramrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:enable")
	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", "merchantapi.accounts.programs.enable", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.enable" call.
// Any non-2xx status code is an error. Response headers are in either
// *Program.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 *AccountsProgramsEnableCall) Do(opts ...googleapi.CallOption) (*Program, 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 := &Program{
		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", "merchantapi.accounts.programs.enable", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieves the specified program for the account.
//
//   - name: The name of the program to retrieve. Format:
//     `accounts/{account}/programs/{program}`. For example,
//     `accounts/123456/programs/free-listings`.
func (r *AccountsProgramsService) Get(name string) *AccountsProgramsGetCall {
	c := &AccountsProgramsGetCall{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 *AccountsProgramsGetCall) Fields(s ...googleapi.Field) *AccountsProgramsGetCall {
	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 *AccountsProgramsGetCall) IfNoneMatch(entityTag string) *AccountsProgramsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsGetCall) Context(ctx context.Context) *AccountsProgramsGetCall {
	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 *AccountsProgramsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsGetCall) 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, "accounts/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", "merchantapi.accounts.programs.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Program.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 *AccountsProgramsGetCall) Do(opts ...googleapi.CallOption) (*Program, 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 := &Program{
		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", "merchantapi.accounts.programs.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: Retrieves all programs for the account.
//
//   - parent: The name of the account for which to retrieve all programs.
//     Format: `accounts/{account}`.
func (r *AccountsProgramsService) List(parent string) *AccountsProgramsListCall {
	c := &AccountsProgramsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// programs to return in a single response. If unspecified (or 0), a default
// size of 1000 is used. The maximum value is 1000; values above 1000 will be
// coerced to 1000.
func (c *AccountsProgramsListCall) PageSize(pageSize int64) *AccountsProgramsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A continuation token,
// received from a previous `ListPrograms` call. Provide this to retrieve the
// next page.
func (c *AccountsProgramsListCall) PageToken(pageToken string) *AccountsProgramsListCall {
	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 *AccountsProgramsListCall) Fields(s ...googleapi.Field) *AccountsProgramsListCall {
	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 *AccountsProgramsListCall) IfNoneMatch(entityTag string) *AccountsProgramsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsListCall) Context(ctx context.Context) *AccountsProgramsListCall {
	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 *AccountsProgramsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsListCall) 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, "accounts/v1/{+parent}/programs")
	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", "merchantapi.accounts.programs.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListProgramsResponse.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 *AccountsProgramsListCall) Do(opts ...googleapi.CallOption) (*ListProgramsResponse, 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 := &ListProgramsResponse{
		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", "merchantapi.accounts.programs.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 *AccountsProgramsListCall) Pages(ctx context.Context, f func(*ListProgramsResponse) 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 AccountsProgramsCheckoutSettingsCreateCall struct {
	s                *APIService
	parent           string
	checkoutsettings *CheckoutSettings
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// Create: Creates `CheckoutSettings` for the given merchant.
//
//   - parent: The merchant account for which the `CheckoutSettings` will be
//     created.
func (r *AccountsProgramsCheckoutSettingsService) Create(parent string, checkoutsettings *CheckoutSettings) *AccountsProgramsCheckoutSettingsCreateCall {
	c := &AccountsProgramsCheckoutSettingsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.checkoutsettings = checkoutsettings
	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 *AccountsProgramsCheckoutSettingsCreateCall) Fields(s ...googleapi.Field) *AccountsProgramsCheckoutSettingsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsCheckoutSettingsCreateCall) Context(ctx context.Context) *AccountsProgramsCheckoutSettingsCreateCall {
	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 *AccountsProgramsCheckoutSettingsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsCheckoutSettingsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.checkoutsettings)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/checkoutSettings")
	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", "merchantapi.accounts.programs.checkoutSettings.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.checkoutSettings.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *CheckoutSettings.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 *AccountsProgramsCheckoutSettingsCreateCall) Do(opts ...googleapi.CallOption) (*CheckoutSettings, 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 := &CheckoutSettings{
		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", "merchantapi.accounts.programs.checkoutSettings.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall struct {
	s          *APIService
	nameid     string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// DeleteCheckoutSettings: Deletes `CheckoutSettings` and unenrolls merchant
// from `Checkout` program.
//
//   - name: The name/identifier of the merchant account. Format:
//     `accounts/{account}/programs/{program}/checkoutSettings`.
func (r *AccountsProgramsCheckoutSettingsService) DeleteCheckoutSettings(nameid string) *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall {
	c := &AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	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 *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall) Fields(s ...googleapi.Field) *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall) Context(ctx context.Context) *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall {
	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 *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall) 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, "accounts/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.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.programs.checkoutSettings.deleteCheckoutSettings", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.checkoutSettings.deleteCheckoutSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsProgramsCheckoutSettingsDeleteCheckoutSettingsCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.programs.checkoutSettings.deleteCheckoutSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall struct {
	s            *APIService
	nameid       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetCheckoutSettings: Gets `CheckoutSettings` for the given merchant. This
// includes information about review state, enrollment state and URL settings.
//
//   - name: The name/identifier of the merchant account. Format:
//     `accounts/{account}/programs/{program}/checkoutSettings`.
func (r *AccountsProgramsCheckoutSettingsService) GetCheckoutSettings(nameid string) *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall {
	c := &AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	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 *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) Fields(s ...googleapi.Field) *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall {
	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 *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) IfNoneMatch(entityTag string) *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) Context(ctx context.Context) *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall {
	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 *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) 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, "accounts/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.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.programs.checkoutSettings.getCheckoutSettings", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.checkoutSettings.getCheckoutSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *CheckoutSettings.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 *AccountsProgramsCheckoutSettingsGetCheckoutSettingsCall) Do(opts ...googleapi.CallOption) (*CheckoutSettings, 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 := &CheckoutSettings{
		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", "merchantapi.accounts.programs.checkoutSettings.getCheckoutSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall struct {
	s                *APIService
	name             string
	checkoutsettings *CheckoutSettings
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// UpdateCheckoutSettings: Updates `CheckoutSettings` for the given merchant.
//
//   - name: Identifier. The resource name of the program configuration settings.
//     Format: `accounts/{account}/programs/{program}/checkoutSettings`.
func (r *AccountsProgramsCheckoutSettingsService) UpdateCheckoutSettings(name string, checkoutsettings *CheckoutSettings) *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall {
	c := &AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.checkoutsettings = checkoutsettings
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. List of
// fields being updated. The following fields are supported (in both
// `snake_case` and `lowerCamelCase`): - `eligible_destinations` -
// `uri_settings`
func (c *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) UpdateMask(updateMask string) *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall {
	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 *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) Fields(s ...googleapi.Field) *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) Context(ctx context.Context) *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall {
	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 *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.checkoutsettings)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.programs.checkoutSettings.updateCheckoutSettings", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.programs.checkoutSettings.updateCheckoutSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *CheckoutSettings.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 *AccountsProgramsCheckoutSettingsUpdateCheckoutSettingsCall) Do(opts ...googleapi.CallOption) (*CheckoutSettings, 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 := &CheckoutSettings{
		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", "merchantapi.accounts.programs.checkoutSettings.updateCheckoutSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsRegionsBatchCreateCall struct {
	s                         *APIService
	parent                    string
	batchcreateregionsrequest *BatchCreateRegionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// BatchCreate: Creates one or more regions in your Merchant Center account.
// Executing this method requires admin access.
//
//   - parent: The account to create one or more regions for. Format:
//     `accounts/{account}`.
func (r *AccountsRegionsService) BatchCreate(parent string, batchcreateregionsrequest *BatchCreateRegionsRequest) *AccountsRegionsBatchCreateCall {
	c := &AccountsRegionsBatchCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.batchcreateregionsrequest = batchcreateregionsrequest
	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 *AccountsRegionsBatchCreateCall) Fields(s ...googleapi.Field) *AccountsRegionsBatchCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsBatchCreateCall) Context(ctx context.Context) *AccountsRegionsBatchCreateCall {
	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 *AccountsRegionsBatchCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsBatchCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.batchcreateregionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/regions:batchCreate")
	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", "merchantapi.accounts.regions.batchCreate", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.batchCreate" call.
// Any non-2xx status code is an error. Response headers are in either
// *BatchCreateRegionsResponse.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 *AccountsRegionsBatchCreateCall) Do(opts ...googleapi.CallOption) (*BatchCreateRegionsResponse, 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 := &BatchCreateRegionsResponse{
		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", "merchantapi.accounts.regions.batchCreate", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsRegionsBatchDeleteCall struct {
	s                         *APIService
	parent                    string
	batchdeleteregionsrequest *BatchDeleteRegionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// BatchDelete: Deletes multiple regions by name from your Merchant Center
// account. Executing this method requires admin access.
//
//   - parent: The account to delete one or more regions from. Format:
//     `accounts/{account}`.
func (r *AccountsRegionsService) BatchDelete(parent string, batchdeleteregionsrequest *BatchDeleteRegionsRequest) *AccountsRegionsBatchDeleteCall {
	c := &AccountsRegionsBatchDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.batchdeleteregionsrequest = batchdeleteregionsrequest
	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 *AccountsRegionsBatchDeleteCall) Fields(s ...googleapi.Field) *AccountsRegionsBatchDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsBatchDeleteCall) Context(ctx context.Context) *AccountsRegionsBatchDeleteCall {
	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 *AccountsRegionsBatchDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsBatchDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.batchdeleteregionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/regions:batchDelete")
	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", "merchantapi.accounts.regions.batchDelete", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.batchDelete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsRegionsBatchDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.regions.batchDelete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsRegionsBatchUpdateCall struct {
	s                         *APIService
	parent                    string
	batchupdateregionsrequest *BatchUpdateRegionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// BatchUpdate: Updates one or more regions in your Merchant Center account.
// Executing this method requires admin access.
//
//   - parent: The account to update one or more regions for. Format:
//     `accounts/{account}`.
func (r *AccountsRegionsService) BatchUpdate(parent string, batchupdateregionsrequest *BatchUpdateRegionsRequest) *AccountsRegionsBatchUpdateCall {
	c := &AccountsRegionsBatchUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.batchupdateregionsrequest = batchupdateregionsrequest
	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 *AccountsRegionsBatchUpdateCall) Fields(s ...googleapi.Field) *AccountsRegionsBatchUpdateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsBatchUpdateCall) Context(ctx context.Context) *AccountsRegionsBatchUpdateCall {
	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 *AccountsRegionsBatchUpdateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsBatchUpdateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.batchupdateregionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/regions:batchUpdate")
	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", "merchantapi.accounts.regions.batchUpdate", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.batchUpdate" call.
// Any non-2xx status code is an error. Response headers are in either
// *BatchUpdateRegionsResponse.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 *AccountsRegionsBatchUpdateCall) Do(opts ...googleapi.CallOption) (*BatchUpdateRegionsResponse, 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 := &BatchUpdateRegionsResponse{
		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", "merchantapi.accounts.regions.batchUpdate", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsRegionsCreateCall struct {
	s          *APIService
	parent     string
	region     *Region
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Create: Creates a region definition in your Merchant Center account.
// Executing this method requires admin access.
//
// - parent: The account to create a region for. Format: `accounts/{account}`.
func (r *AccountsRegionsService) Create(parent string, region *Region) *AccountsRegionsCreateCall {
	c := &AccountsRegionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.region = region
	return c
}

// RegionId sets the optional parameter "regionId": Required. The identifier
// for the region, unique over all regions of the same account.
func (c *AccountsRegionsCreateCall) RegionId(regionId string) *AccountsRegionsCreateCall {
	c.urlParams_.Set("regionId", regionId)
	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 *AccountsRegionsCreateCall) Fields(s ...googleapi.Field) *AccountsRegionsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsCreateCall) Context(ctx context.Context) *AccountsRegionsCreateCall {
	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 *AccountsRegionsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.region)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/regions")
	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", "merchantapi.accounts.regions.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Region.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 *AccountsRegionsCreateCall) Do(opts ...googleapi.CallOption) (*Region, 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 := &Region{
		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", "merchantapi.accounts.regions.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Delete: Deletes a region definition from your Merchant Center account.
// Executing this method requires admin access.
//
//   - name: The name of the region to delete. Format:
//     `accounts/{account}/regions/{region}`.
func (r *AccountsRegionsService) Delete(name string) *AccountsRegionsDeleteCall {
	c := &AccountsRegionsDeleteCall{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 *AccountsRegionsDeleteCall) Fields(s ...googleapi.Field) *AccountsRegionsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsDeleteCall) Context(ctx context.Context) *AccountsRegionsDeleteCall {
	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 *AccountsRegionsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsDeleteCall) 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, "accounts/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", "merchantapi.accounts.regions.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsRegionsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.regions.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieves a region defined in your Merchant Center account.
//
//   - name: The name of the region to retrieve. Format:
//     `accounts/{account}/regions/{region}`.
func (r *AccountsRegionsService) Get(name string) *AccountsRegionsGetCall {
	c := &AccountsRegionsGetCall{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 *AccountsRegionsGetCall) Fields(s ...googleapi.Field) *AccountsRegionsGetCall {
	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 *AccountsRegionsGetCall) IfNoneMatch(entityTag string) *AccountsRegionsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsGetCall) Context(ctx context.Context) *AccountsRegionsGetCall {
	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 *AccountsRegionsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsGetCall) 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, "accounts/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", "merchantapi.accounts.regions.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Region.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 *AccountsRegionsGetCall) Do(opts ...googleapi.CallOption) (*Region, 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 := &Region{
		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", "merchantapi.accounts.regions.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: Lists the regions in your Merchant Center account.
//
// - parent: The account to list regions for. Format: `accounts/{account}`.
func (r *AccountsRegionsService) List(parent string) *AccountsRegionsListCall {
	c := &AccountsRegionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

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

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListRegions` call. Provide this to retrieve the subsequent
// page. When paginating, all other parameters provided to `ListRegions` must
// match the call that provided the page token.
func (c *AccountsRegionsListCall) PageToken(pageToken string) *AccountsRegionsListCall {
	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 *AccountsRegionsListCall) Fields(s ...googleapi.Field) *AccountsRegionsListCall {
	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 *AccountsRegionsListCall) IfNoneMatch(entityTag string) *AccountsRegionsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsListCall) Context(ctx context.Context) *AccountsRegionsListCall {
	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 *AccountsRegionsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsListCall) 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, "accounts/v1/{+parent}/regions")
	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", "merchantapi.accounts.regions.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListRegionsResponse.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 *AccountsRegionsListCall) Do(opts ...googleapi.CallOption) (*ListRegionsResponse, 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 := &ListRegionsResponse{
		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", "merchantapi.accounts.regions.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 *AccountsRegionsListCall) Pages(ctx context.Context, f func(*ListRegionsResponse) 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 AccountsRegionsPatchCall struct {
	s          *APIService
	name       string
	region     *Region
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Patch: Updates a region definition in your Merchant Center account.
// Executing this method requires admin access.
//
//   - name: Identifier. The resource name of the region. Format:
//     `accounts/{account}/regions/{region}`.
func (r *AccountsRegionsService) Patch(name string, region *Region) *AccountsRegionsPatchCall {
	c := &AccountsRegionsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.region = region
	return c
}

// UpdateMask sets the optional parameter "updateMask": The comma-separated
// field mask indicating the fields to update. Example:
// "displayName,postalCodeArea.regionCode".
func (c *AccountsRegionsPatchCall) UpdateMask(updateMask string) *AccountsRegionsPatchCall {
	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 *AccountsRegionsPatchCall) Fields(s ...googleapi.Field) *AccountsRegionsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRegionsPatchCall) Context(ctx context.Context) *AccountsRegionsPatchCall {
	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 *AccountsRegionsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRegionsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.region)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.regions.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.regions.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Region.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 *AccountsRegionsPatchCall) Do(opts ...googleapi.CallOption) (*Region, 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 := &Region{
		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", "merchantapi.accounts.regions.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieve an account relationship.
//
//   - name: The resource name of the account relationship to get. Format:
//     `accounts/{account}/relationships/{relationship}`. For example,
//     `accounts/123456/relationships/567890`.
func (r *AccountsRelationshipsService) Get(name string) *AccountsRelationshipsGetCall {
	c := &AccountsRelationshipsGetCall{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 *AccountsRelationshipsGetCall) Fields(s ...googleapi.Field) *AccountsRelationshipsGetCall {
	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 *AccountsRelationshipsGetCall) IfNoneMatch(entityTag string) *AccountsRelationshipsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRelationshipsGetCall) Context(ctx context.Context) *AccountsRelationshipsGetCall {
	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 *AccountsRelationshipsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRelationshipsGetCall) 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, "accounts/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", "merchantapi.accounts.relationships.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.relationships.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *AccountRelationship.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 *AccountsRelationshipsGetCall) Do(opts ...googleapi.CallOption) (*AccountRelationship, 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 := &AccountRelationship{
		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", "merchantapi.accounts.relationships.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: List account relationships for the specified account.
//
//   - parent: The parent account of the account relationship to filter by.
//     Format: `accounts/{account}`.
func (r *AccountsRelationshipsService) List(parent string) *AccountsRelationshipsListCall {
	c := &AccountsRelationshipsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// elements to return in the response. Use for paging. If no `page_size` is
// specified, `100` is used as the default value. The maximum allowed value is
// `1000`.
func (c *AccountsRelationshipsListCall) PageSize(pageSize int64) *AccountsRelationshipsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The token returned by the
// previous `list` request.
func (c *AccountsRelationshipsListCall) PageToken(pageToken string) *AccountsRelationshipsListCall {
	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 *AccountsRelationshipsListCall) Fields(s ...googleapi.Field) *AccountsRelationshipsListCall {
	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 *AccountsRelationshipsListCall) IfNoneMatch(entityTag string) *AccountsRelationshipsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRelationshipsListCall) Context(ctx context.Context) *AccountsRelationshipsListCall {
	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 *AccountsRelationshipsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRelationshipsListCall) 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, "accounts/v1/{+parent}/relationships")
	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", "merchantapi.accounts.relationships.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.relationships.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListAccountRelationshipsResponse.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 *AccountsRelationshipsListCall) Do(opts ...googleapi.CallOption) (*ListAccountRelationshipsResponse, 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 := &ListAccountRelationshipsResponse{
		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", "merchantapi.accounts.relationships.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 *AccountsRelationshipsListCall) Pages(ctx context.Context, f func(*ListAccountRelationshipsResponse) 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 AccountsRelationshipsPatchCall struct {
	s                   *APIService
	name                string
	accountrelationship *AccountRelationship
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// Patch: Updates the account relationship. Executing this method requires
// admin access.
//
//   - name: Identifier. The resource name of the account relationship. Format:
//     `accounts/{account}/relationships/{relationship}`. For example,
//     `accounts/123456/relationships/567890`.
func (r *AccountsRelationshipsService) Patch(name string, accountrelationship *AccountRelationship) *AccountsRelationshipsPatchCall {
	c := &AccountsRelationshipsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.accountrelationship = accountrelationship
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `account_id_alias`
func (c *AccountsRelationshipsPatchCall) UpdateMask(updateMask string) *AccountsRelationshipsPatchCall {
	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 *AccountsRelationshipsPatchCall) Fields(s ...googleapi.Field) *AccountsRelationshipsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsRelationshipsPatchCall) Context(ctx context.Context) *AccountsRelationshipsPatchCall {
	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 *AccountsRelationshipsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsRelationshipsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.accountrelationship)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.relationships.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.relationships.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *AccountRelationship.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 *AccountsRelationshipsPatchCall) Do(opts ...googleapi.CallOption) (*AccountRelationship, 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 := &AccountRelationship{
		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", "merchantapi.accounts.relationships.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsServicesApproveCall struct {
	s                            *APIService
	name                         string
	approveaccountservicerequest *ApproveAccountServiceRequest
	urlParams_                   gensupport.URLParams
	ctx_                         context.Context
	header_                      http.Header
}

// Approve: Approve an account service proposal.
//
//   - name: The resource name of the account service to approve. Format:
//     `accounts/{account}/services/{service}`.
func (r *AccountsServicesService) Approve(name string, approveaccountservicerequest *ApproveAccountServiceRequest) *AccountsServicesApproveCall {
	c := &AccountsServicesApproveCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.approveaccountservicerequest = approveaccountservicerequest
	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 *AccountsServicesApproveCall) Fields(s ...googleapi.Field) *AccountsServicesApproveCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsServicesApproveCall) Context(ctx context.Context) *AccountsServicesApproveCall {
	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 *AccountsServicesApproveCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsServicesApproveCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.approveaccountservicerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:approve")
	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", "merchantapi.accounts.services.approve", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.services.approve" call.
// Any non-2xx status code is an error. Response headers are in either
// *AccountService.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 *AccountsServicesApproveCall) Do(opts ...googleapi.CallOption) (*AccountService, 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 := &AccountService{
		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", "merchantapi.accounts.services.approve", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieve an account service.
//
//   - name: The resource name of the account service to get. Format:
//     `accounts/{account}/services/{service}`.
func (r *AccountsServicesService) Get(name string) *AccountsServicesGetCall {
	c := &AccountsServicesGetCall{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 *AccountsServicesGetCall) Fields(s ...googleapi.Field) *AccountsServicesGetCall {
	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 *AccountsServicesGetCall) IfNoneMatch(entityTag string) *AccountsServicesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsServicesGetCall) Context(ctx context.Context) *AccountsServicesGetCall {
	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 *AccountsServicesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsServicesGetCall) 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, "accounts/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", "merchantapi.accounts.services.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.services.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *AccountService.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 *AccountsServicesGetCall) Do(opts ...googleapi.CallOption) (*AccountService, 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 := &AccountService{
		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", "merchantapi.accounts.services.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: List account services for the specified accounts. Supports filtering.
//
//   - parent: The parent account of the account service to filter by. Format:
//     `accounts/{account}`.
func (r *AccountsServicesService) List(parent string) *AccountsServicesListCall {
	c := &AccountsServicesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of
// elements to return in the response. Use for paging. If no `page_size` is
// specified, `100` is used as the default value. The maximum allowed value is
// `1000`.
func (c *AccountsServicesListCall) PageSize(pageSize int64) *AccountsServicesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The token returned by the
// previous `list` request.
func (c *AccountsServicesListCall) PageToken(pageToken string) *AccountsServicesListCall {
	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 *AccountsServicesListCall) Fields(s ...googleapi.Field) *AccountsServicesListCall {
	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 *AccountsServicesListCall) IfNoneMatch(entityTag string) *AccountsServicesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsServicesListCall) Context(ctx context.Context) *AccountsServicesListCall {
	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 *AccountsServicesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsServicesListCall) 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, "accounts/v1/{+parent}/services")
	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", "merchantapi.accounts.services.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.services.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListAccountServicesResponse.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 *AccountsServicesListCall) Do(opts ...googleapi.CallOption) (*ListAccountServicesResponse, 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 := &ListAccountServicesResponse{
		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", "merchantapi.accounts.services.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 *AccountsServicesListCall) Pages(ctx context.Context, f func(*ListAccountServicesResponse) 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 AccountsServicesProposeCall struct {
	s                            *APIService
	parent                       string
	proposeaccountservicerequest *ProposeAccountServiceRequest
	urlParams_                   gensupport.URLParams
	ctx_                         context.Context
	header_                      http.Header
}

// Propose: Propose an account service.
//
//   - parent: The resource name of the parent account for the service. Format:
//     `accounts/{account}`.
func (r *AccountsServicesService) Propose(parent string, proposeaccountservicerequest *ProposeAccountServiceRequest) *AccountsServicesProposeCall {
	c := &AccountsServicesProposeCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.proposeaccountservicerequest = proposeaccountservicerequest
	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 *AccountsServicesProposeCall) Fields(s ...googleapi.Field) *AccountsServicesProposeCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsServicesProposeCall) Context(ctx context.Context) *AccountsServicesProposeCall {
	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 *AccountsServicesProposeCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsServicesProposeCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.proposeaccountservicerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/services:propose")
	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", "merchantapi.accounts.services.propose", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.services.propose" call.
// Any non-2xx status code is an error. Response headers are in either
// *AccountService.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 *AccountsServicesProposeCall) Do(opts ...googleapi.CallOption) (*AccountService, 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 := &AccountService{
		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", "merchantapi.accounts.services.propose", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsServicesRejectCall struct {
	s                           *APIService
	name                        string
	rejectaccountservicerequest *RejectAccountServiceRequest
	urlParams_                  gensupport.URLParams
	ctx_                        context.Context
	header_                     http.Header
}

// Reject: Reject an account service (both proposed and approve services can be
// rejected).
//
//   - name: The resource name of the account service to reject. Format:
//     `accounts/{account}/services/{service}`.
func (r *AccountsServicesService) Reject(name string, rejectaccountservicerequest *RejectAccountServiceRequest) *AccountsServicesRejectCall {
	c := &AccountsServicesRejectCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.rejectaccountservicerequest = rejectaccountservicerequest
	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 *AccountsServicesRejectCall) Fields(s ...googleapi.Field) *AccountsServicesRejectCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsServicesRejectCall) Context(ctx context.Context) *AccountsServicesRejectCall {
	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 *AccountsServicesRejectCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsServicesRejectCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.rejectaccountservicerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+name}:reject")
	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", "merchantapi.accounts.services.reject", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.services.reject" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsServicesRejectCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.services.reject", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// GetShippingSettings: Retrieve shipping setting information.
//
//   - name: The name of the shipping setting to retrieve. Format:
//     `accounts/{account}/shippingsettings`.
func (r *AccountsShippingSettingsService) GetShippingSettings(name string) *AccountsShippingSettingsGetShippingSettingsCall {
	c := &AccountsShippingSettingsGetShippingSettingsCall{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 *AccountsShippingSettingsGetShippingSettingsCall) Fields(s ...googleapi.Field) *AccountsShippingSettingsGetShippingSettingsCall {
	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 *AccountsShippingSettingsGetShippingSettingsCall) IfNoneMatch(entityTag string) *AccountsShippingSettingsGetShippingSettingsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsShippingSettingsGetShippingSettingsCall) Context(ctx context.Context) *AccountsShippingSettingsGetShippingSettingsCall {
	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 *AccountsShippingSettingsGetShippingSettingsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsShippingSettingsGetShippingSettingsCall) 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, "accounts/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", "merchantapi.accounts.shippingSettings.getShippingSettings", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.shippingSettings.getShippingSettings" call.
// Any non-2xx status code is an error. Response headers are in either
// *ShippingSettings.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 *AccountsShippingSettingsGetShippingSettingsCall) Do(opts ...googleapi.CallOption) (*ShippingSettings, 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 := &ShippingSettings{
		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", "merchantapi.accounts.shippingSettings.getShippingSettings", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsShippingSettingsInsertCall struct {
	s                *APIService
	parentid         string
	shippingsettings *ShippingSettings
	urlParams_       gensupport.URLParams
	ctx_             context.Context
	header_          http.Header
}

// Insert: Replace the shipping setting of a business with the request shipping
// setting. Executing this method requires admin access.
//
//   - parent: The account for which this shipping setting will be inserted. If
//     you are using an advanced account, you must specify the unique identifier
//     of the sub-account for which you want to insert the shipping setting.
//     Format: `accounts/{ACCOUNT_ID}`.
func (r *AccountsShippingSettingsService) Insert(parentid string, shippingsettings *ShippingSettings) *AccountsShippingSettingsInsertCall {
	c := &AccountsShippingSettingsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parentid = parentid
	c.shippingsettings = shippingsettings
	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 *AccountsShippingSettingsInsertCall) Fields(s ...googleapi.Field) *AccountsShippingSettingsInsertCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsShippingSettingsInsertCall) Context(ctx context.Context) *AccountsShippingSettingsInsertCall {
	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 *AccountsShippingSettingsInsertCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsShippingSettingsInsertCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.shippingsettings)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/shippingSettings:insert")
	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.parentid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.shippingSettings.insert", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.shippingSettings.insert" call.
// Any non-2xx status code is an error. Response headers are in either
// *ShippingSettings.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 *AccountsShippingSettingsInsertCall) Do(opts ...googleapi.CallOption) (*ShippingSettings, 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 := &ShippingSettings{
		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", "merchantapi.accounts.shippingSettings.insert", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsTermsOfServiceAgreementStatesGetCall struct {
	s            *APIService
	nameid       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Returns the state of a terms of service agreement.
//
//   - name: The resource name of the terms of service version. Format:
//     `accounts/{account}/termsOfServiceAgreementStates/{identifier}` The
//     identifier format is: `{TermsOfServiceKind}-{country}`.
func (r *AccountsTermsOfServiceAgreementStatesService) Get(nameid string) *AccountsTermsOfServiceAgreementStatesGetCall {
	c := &AccountsTermsOfServiceAgreementStatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	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 *AccountsTermsOfServiceAgreementStatesGetCall) Fields(s ...googleapi.Field) *AccountsTermsOfServiceAgreementStatesGetCall {
	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 *AccountsTermsOfServiceAgreementStatesGetCall) IfNoneMatch(entityTag string) *AccountsTermsOfServiceAgreementStatesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsTermsOfServiceAgreementStatesGetCall) Context(ctx context.Context) *AccountsTermsOfServiceAgreementStatesGetCall {
	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 *AccountsTermsOfServiceAgreementStatesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsTermsOfServiceAgreementStatesGetCall) 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, "accounts/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.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.termsOfServiceAgreementStates.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.termsOfServiceAgreementStates.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *TermsOfServiceAgreementState.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 *AccountsTermsOfServiceAgreementStatesGetCall) Do(opts ...googleapi.CallOption) (*TermsOfServiceAgreementState, 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 := &TermsOfServiceAgreementState{
		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", "merchantapi.accounts.termsOfServiceAgreementStates.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// RetrieveForApplication: Retrieves the state of the agreement for the
// application terms of service. Application terms of service covers
// permissions related to the usage of data provided through Merchant Center,
// CSS Center, Manufacturer Center, and more.
//
//   - parent: The account for which to get a TermsOfServiceAgreementState
//     Format: `accounts/{account}`.
func (r *AccountsTermsOfServiceAgreementStatesService) RetrieveForApplication(parent string) *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall {
	c := &AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	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 *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) Fields(s ...googleapi.Field) *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall {
	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 *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) IfNoneMatch(entityTag string) *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) Context(ctx context.Context) *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall {
	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 *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) 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, "accounts/v1/{+parent}/termsOfServiceAgreementStates:retrieveForApplication")
	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", "merchantapi.accounts.termsOfServiceAgreementStates.retrieveForApplication", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.termsOfServiceAgreementStates.retrieveForApplication" call.
// Any non-2xx status code is an error. Response headers are in either
// *TermsOfServiceAgreementState.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 *AccountsTermsOfServiceAgreementStatesRetrieveForApplicationCall) Do(opts ...googleapi.CallOption) (*TermsOfServiceAgreementState, 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 := &TermsOfServiceAgreementState{
		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", "merchantapi.accounts.termsOfServiceAgreementStates.retrieveForApplication", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsUsersCreateCall struct {
	s          *APIService
	parent     string
	user       *User
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Create: Creates a Merchant Center account user. Executing this method
// requires admin access.
//
//   - parent: The resource name of the account for which a user will be created.
//     Format: `accounts/{account}`.
func (r *AccountsUsersService) Create(parent string, user *User) *AccountsUsersCreateCall {
	c := &AccountsUsersCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.user = user
	return c
}

// UserId sets the optional parameter "userId": Required. The email address of
// the user (for example, `john.doe@gmail.com`).
func (c *AccountsUsersCreateCall) UserId(userId string) *AccountsUsersCreateCall {
	c.urlParams_.Set("userId", userId)
	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 *AccountsUsersCreateCall) Fields(s ...googleapi.Field) *AccountsUsersCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersCreateCall) Context(ctx context.Context) *AccountsUsersCreateCall {
	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 *AccountsUsersCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.user)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+parent}/users")
	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", "merchantapi.accounts.users.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *User.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 *AccountsUsersCreateCall) Do(opts ...googleapi.CallOption) (*User, 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 := &User{
		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", "merchantapi.accounts.users.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Delete: Deletes a Merchant Center account user. Executing this method
// requires admin access. The user to be deleted can't be the last admin user
// of that account.
//
//   - name: The name of the user to delete. Format:
//     `accounts/{account}/users/{email}` It is also possible to delete the user
//     corresponding to the caller by using `me` rather than an email address as
//     in `accounts/{account}/users/me`.
func (r *AccountsUsersService) Delete(name string) *AccountsUsersDeleteCall {
	c := &AccountsUsersDeleteCall{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 *AccountsUsersDeleteCall) Fields(s ...googleapi.Field) *AccountsUsersDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersDeleteCall) Context(ctx context.Context) *AccountsUsersDeleteCall {
	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 *AccountsUsersDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersDeleteCall) 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, "accounts/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", "merchantapi.accounts.users.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.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 *AccountsUsersDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, 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 := &Empty{
		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", "merchantapi.accounts.users.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieves a Merchant Center account user.
//
//   - name: The name of the user to retrieve. Format:
//     `accounts/{account}/users/{email}` It is also possible to retrieve the
//     user corresponding to the caller by using `me` rather than an email
//     address as in `accounts/{account}/users/me`.
func (r *AccountsUsersService) Get(name string) *AccountsUsersGetCall {
	c := &AccountsUsersGetCall{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 *AccountsUsersGetCall) Fields(s ...googleapi.Field) *AccountsUsersGetCall {
	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 *AccountsUsersGetCall) IfNoneMatch(entityTag string) *AccountsUsersGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersGetCall) Context(ctx context.Context) *AccountsUsersGetCall {
	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 *AccountsUsersGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersGetCall) 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, "accounts/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", "merchantapi.accounts.users.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *User.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 *AccountsUsersGetCall) Do(opts ...googleapi.CallOption) (*User, 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 := &User{
		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", "merchantapi.accounts.users.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// List: Lists all users of a Merchant Center account.
//
//   - parent: The parent, which owns this collection of users. Format:
//     `accounts/{account}`.
func (r *AccountsUsersService) List(parent string) *AccountsUsersListCall {
	c := &AccountsUsersListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

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

// PageToken sets the optional parameter "pageToken": A page token, received
// from a previous `ListUsers` call. Provide this to retrieve the subsequent
// page. When paginating, all other parameters provided to `ListUsers` must
// match the call that provided the page token.
func (c *AccountsUsersListCall) PageToken(pageToken string) *AccountsUsersListCall {
	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 *AccountsUsersListCall) Fields(s ...googleapi.Field) *AccountsUsersListCall {
	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 *AccountsUsersListCall) IfNoneMatch(entityTag string) *AccountsUsersListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersListCall) Context(ctx context.Context) *AccountsUsersListCall {
	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 *AccountsUsersListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersListCall) 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, "accounts/v1/{+parent}/users")
	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", "merchantapi.accounts.users.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListUsersResponse.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 *AccountsUsersListCall) Do(opts ...googleapi.CallOption) (*ListUsersResponse, 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 := &ListUsersResponse{
		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", "merchantapi.accounts.users.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 *AccountsUsersListCall) Pages(ctx context.Context, f func(*ListUsersResponse) 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 AccountsUsersPatchCall struct {
	s          *APIService
	name       string
	user       *User
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Patch: Updates a Merchant Center account user. Executing this method
// requires admin access.
//
//   - name: Identifier. The resource name of the user. Format:
//     `accounts/{account}/user/{email}` Use `me` to refer to your own email
//     address, for example `accounts/{account}/users/me`.
func (r *AccountsUsersService) Patch(name string, user *User) *AccountsUsersPatchCall {
	c := &AccountsUsersPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.user = user
	return c
}

// UpdateMask sets the optional parameter "updateMask": List of fields being
// updated. The following fields are supported (in both `snake_case` and
// `lowerCamelCase`): - `access_rights`
func (c *AccountsUsersPatchCall) UpdateMask(updateMask string) *AccountsUsersPatchCall {
	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 *AccountsUsersPatchCall) Fields(s ...googleapi.Field) *AccountsUsersPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersPatchCall) Context(ctx context.Context) *AccountsUsersPatchCall {
	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 *AccountsUsersPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.user)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/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", "merchantapi.accounts.users.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *User.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 *AccountsUsersPatchCall) Do(opts ...googleapi.CallOption) (*User, 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 := &User{
		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", "merchantapi.accounts.users.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type AccountsUsersMeVerifySelfCall struct {
	s                 *APIService
	account           string
	verifyselfrequest *VerifySelfRequest
	urlParams_        gensupport.URLParams
	ctx_              context.Context
	header_           http.Header
}

// VerifySelf: Updates the user that is represented by the caller from pending
// to verified.
//
//   - account: The name of the account under which the caller is a user. Format:
//     `accounts/{account}`.
func (r *AccountsUsersMeService) VerifySelf(account string, verifyselfrequest *VerifySelfRequest) *AccountsUsersMeVerifySelfCall {
	c := &AccountsUsersMeVerifySelfCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.account = account
	c.verifyselfrequest = verifyselfrequest
	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 *AccountsUsersMeVerifySelfCall) Fields(s ...googleapi.Field) *AccountsUsersMeVerifySelfCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *AccountsUsersMeVerifySelfCall) Context(ctx context.Context) *AccountsUsersMeVerifySelfCall {
	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 *AccountsUsersMeVerifySelfCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *AccountsUsersMeVerifySelfCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.verifyselfrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "accounts/v1/{+account}/users/me:verifySelf")
	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{
		"account": c.account,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.accounts.users.me.verifySelf", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.accounts.users.me.verifySelf" call.
// Any non-2xx status code is an error. Response headers are in either
// *User.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 *AccountsUsersMeVerifySelfCall) Do(opts ...googleapi.CallOption) (*User, 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 := &User{
		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", "merchantapi.accounts.users.me.verifySelf", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Accept: Accepts a `TermsOfService`. Executing this method requires admin
// access.
//
//   - name: The resource name of the terms of service version. Format:
//     `termsOfService/{version}`.
func (r *TermsOfServiceService) Accept(name string) *TermsOfServiceAcceptCall {
	c := &TermsOfServiceAcceptCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Account sets the optional parameter "account": Required. The account for
// which to accept the ToS. Format: `accounts/{account}`
func (c *TermsOfServiceAcceptCall) Account(account string) *TermsOfServiceAcceptCall {
	c.urlParams_.Set("account", account)
	return c
}

// RegionCode sets the optional parameter "regionCode": Required. Region code
// as defined by CLDR (https://cldr.unicode.org/). This is either a country
// when the ToS applies specifically to that country or 001 when it applies
// globally.
func (c *TermsOfServiceAcceptCall) RegionCode(regionCode string) *TermsOfServiceAcceptCall {
	c.urlParams_.Set("regionCode", regionCode)
	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 *TermsOfServiceAcceptCall) Fields(s ...googleapi.Field) *TermsOfServiceAcceptCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *TermsOfServiceAcceptCall) Context(ctx context.Context) *TermsOfServiceAcceptCall {
	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 *TermsOfServiceAcceptCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *TermsOfServiceAcceptCall) 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, "accounts/v1/{+name}:accept")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", 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", "merchantapi.termsOfService.accept", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.termsOfService.accept" call.
// Any non-2xx status code is an error. Response headers are in either
// *AcceptTermsOfServiceResponse.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 *TermsOfServiceAcceptCall) Do(opts ...googleapi.CallOption) (*AcceptTermsOfServiceResponse, 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 := &AcceptTermsOfServiceResponse{
		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", "merchantapi.termsOfService.accept", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

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

// Get: Retrieves the `TermsOfService` associated with the provided version.
//
//   - name: The resource name of the terms of service version. Format:
//     `termsOfService/{version}`.
func (r *TermsOfServiceService) Get(name string) *TermsOfServiceGetCall {
	c := &TermsOfServiceGetCall{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 *TermsOfServiceGetCall) Fields(s ...googleapi.Field) *TermsOfServiceGetCall {
	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 *TermsOfServiceGetCall) IfNoneMatch(entityTag string) *TermsOfServiceGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *TermsOfServiceGetCall) Context(ctx context.Context) *TermsOfServiceGetCall {
	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 *TermsOfServiceGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *TermsOfServiceGetCall) 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, "accounts/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", "merchantapi.termsOfService.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.termsOfService.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *TermsOfService.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 *TermsOfServiceGetCall) Do(opts ...googleapi.CallOption) (*TermsOfService, 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 := &TermsOfService{
		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", "merchantapi.termsOfService.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type TermsOfServiceRetrieveLatestCall struct {
	s            *APIService
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// RetrieveLatest: Retrieves the latest version of the `TermsOfService` for a
// given `kind` and `region_code`.
func (r *TermsOfServiceService) RetrieveLatest() *TermsOfServiceRetrieveLatestCall {
	c := &TermsOfServiceRetrieveLatestCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	return c
}

// Kind sets the optional parameter "kind": Required. The Kind this terms of
// service version applies to.
//
// Possible values:
//
//	"TERMS_OF_SERVICE_KIND_UNSPECIFIED" - Default value. This value is unused.
//	"MERCHANT_CENTER" - Terms of service for the Merchant Center application.
func (c *TermsOfServiceRetrieveLatestCall) Kind(kind string) *TermsOfServiceRetrieveLatestCall {
	c.urlParams_.Set("kind", kind)
	return c
}

// RegionCode sets the optional parameter "regionCode": Required. Region code
// as defined by CLDR (https://cldr.unicode.org/). This is either a country
// when the ToS applies specifically to that country or 001 when it applies
// globally.
func (c *TermsOfServiceRetrieveLatestCall) RegionCode(regionCode string) *TermsOfServiceRetrieveLatestCall {
	c.urlParams_.Set("regionCode", regionCode)
	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 *TermsOfServiceRetrieveLatestCall) Fields(s ...googleapi.Field) *TermsOfServiceRetrieveLatestCall {
	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 *TermsOfServiceRetrieveLatestCall) IfNoneMatch(entityTag string) *TermsOfServiceRetrieveLatestCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *TermsOfServiceRetrieveLatestCall) Context(ctx context.Context) *TermsOfServiceRetrieveLatestCall {
	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 *TermsOfServiceRetrieveLatestCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *TermsOfServiceRetrieveLatestCall) 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, "accounts/v1/termsOfService:retrieveLatest")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "merchantapi.termsOfService.retrieveLatest", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "merchantapi.termsOfService.retrieveLatest" call.
// Any non-2xx status code is an error. Response headers are in either
// *TermsOfService.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 *TermsOfServiceRetrieveLatestCall) Do(opts ...googleapi.CallOption) (*TermsOfService, 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 := &TermsOfService{
		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", "merchantapi.termsOfService.retrieveLatest", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}
