// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.shopping.merchant.loyaltycustomers.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";

option csharp_namespace = "Google.Shopping.Merchant.LoyaltyCustomers.V1";
option go_package = "cloud.google.com/go/shopping/merchant/loyaltycustomers/apiv1/loyaltycustomerspb;loyaltycustomerspb";
option java_multiple_files = true;
option java_outer_classname = "LoyaltyCustomerProto";
option java_package = "com.google.shopping.merchant.loyaltycustomers.v1";
option php_namespace = "Google\\Shopping\\Merchant\\LoyaltyCustomers\\V1";
option ruby_package = "Google::Shopping::Merchant::LoyaltyCustomers::V1";
option (google.api.resource_definition) = {
  type: "merchantapi.googleapis.com/Account"
  pattern: "accounts/{account}"
};

// Manages customer loyalty program memberships for merchants.
//
// This service allows all merchants, including non-advertisers, to share their
// first-party customer data of loyalty program members. Google uses this data
// to personalize organic free listing shopping experiences, in compliance with
// the [Merchant Center Terms of
// Service](https://support.google.com/merchants/answer/160173).
//
//
// The service follows a non-standard, imperative pattern,
// exposing a single `ManageLoyaltyCustomerMatch` method rather than
// conventional resource identifiers and CRUD operations. This design protects
// user privacy by preventing the discovery of a customer's presence or
// membership status through standard GET or LIST methods.
service LoyaltyCustomerMatchService {
  option (google.api.default_host) = "merchantapi.googleapis.com";
  option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/content";

  // Manages (inserts, updates, or removes) a customer's loyalty tier
  // information.
  //
  // This method serves as a single interface for all changes to a customer's
  // loyalty status. The specific action (insert, update, or remove) is
  // determined by the current state of the merchant-to-customer association and
  // the `loyalty_tier` value provided in the request.
  //
  // **Operation Logic:**
  //
  // * **Upsert (Insert/Update):** Providing any valid tier other than
  // `NON_MEMBER` will associate the customer with that tier. If an association
  // already exists, it will be updated; otherwise, a new one will be created.
  // * **Removal:** Setting `loyalty_tier` to `NON_MEMBER` will remove any
  // existing loyalty association for the customer.
  //
  // **Privacy Note:** To protect user privacy, this method consistently returns
  // a `200 OK` status with a default `LoyaltyCustomer` response if the
  // customer's identifier cannot be matched to a Google account or if the user
  // has not opted into loyalty personalization.
  rpc ManageLoyaltyCustomerMatch(ManageLoyaltyCustomerMatchRequest)
      returns (ManageLoyaltyCustomerMatchResponse) {
    option (google.api.http) = {
      post: "/loyaltyCustomers/v1/{parent=accounts/*}/loyaltyCustomers:manage"
      body: "*"
    };
  }
}

// Represents a customer’s physical address.
message AddressInfo {
  // Optional. The given name of the customer.
  string given_name = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The family name of the customer.
  string family_name = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The city of the customer.
  string city = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The state or province of the customer.
  string state = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The Unicode country/region code (CLDR) of the customer, such as
  // "US" or "CH". This field is case-insensitive. For more information, see
  // https://cldr.unicode.org/ and
  // https://www.unicode.org/cldr/charts/latest/supplemental/territory_containment_un_m_49.html.
  string region_code = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The postal code (zip code) of the customer.
  //
  // **Format Rules:**
  //
  // * **United States:** 5-digit zip codes (e.g., "94108").
  string postal_code = 6 [(google.api.field_behavior) = OPTIONAL];
}

// The user identifiers associated with the customer.
// At least one of the fields within this message must be provided.
message UserIdentifier {
  // Optional. The customer’s email address.
  string email_address = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The customer’s physical address.
  AddressInfo address = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The customer's phone number, in
  // [E.164 format](https://support.google.com/google-ads/answer/16355235)
  // (e.g., "+16502530000").
  string phone_number = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Represents a customer’s loyalty information.
// Represents loyalty customer data in `ManageLoyaltyCustomerMatch` API, but
// is not a resource that can be retrieved or listed by other methods.
message LoyaltyCustomer {
  // The tier label of the loyalty tier the customer belongs to.
  enum LoyaltyTier {
    // Loyalty tier unspecified.
    LOYALTY_TIER_UNSPECIFIED = 0;

    // Loyalty tier 1.
    TIER1 = 1;

    // Loyalty tier 2.
    TIER2 = 2;

    // Loyalty tier 3.
    TIER3 = 3;

    // Loyalty tier 4.
    TIER4 = 4;

    // Loyalty tier 5.
    TIER5 = 5;

    // Loyalty tier 6.
    TIER6 = 6;

    // Loyalty tier 7.
    TIER7 = 7;

    // Disassociates the user from any loyalty tier. Only set to “NON_MEMBER”
    // when the intent is to remove the user association from Google organic
    // loyalty customer match experience.
    NON_MEMBER = 8;
  }

  // Required. The identifiers for the customer.
  UserIdentifier user_identifier = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The tier label of the loyalty tier the customer belongs to.
  LoyaltyTier loyalty_tier = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. The point balance of the loyalty customer.
  int64 point_balance = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for the ManageLoyaltyCustomerMatch method.
message ManageLoyaltyCustomerMatchRequest {
  // Required. The parent account where this loyalty customer will be handled.
  // Format: `accounts/{account}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "merchantapi.googleapis.com/Account"
    }
  ];

  // Required. The loyalty customer to insert, update, or remove.
  LoyaltyCustomer loyalty_customer = 2 [(google.api.field_behavior) = REQUIRED];
}

// Response message for the ManageLoyaltyCustomerMatch method.
message ManageLoyaltyCustomerMatchResponse {
  // The loyalty customer that was inserted, updated, or removed.
  // If the customer's identifier cannot be matched to a Google account or if
  // the user has not opted into loyalty personalization, this field will
  // contain a default `LoyaltyCustomer` instance.
  LoyaltyCustomer loyalty_customer = 1;
}
