Feeds

Feed Specifications

The specification of the OfferFeed and all related objects.

OfferFeed definition

// Next tag: 24
message OfferFeed {
  repeated Offer data = 1;
}

Offer definition

// Next tag: 24
message Offer {
  // Unique ID of the offer.
  // Required.
  string offer_id = 1 [(validator.rule) = {
    predicate: "not empty($) ?: ERROR_MISSING_OFFER_ID",
  }];

  // List of merchants who are participating in this offer.
  repeated string entity_ids = 2 [(validator.rule) = {
    predicate: "if($add_on_offer_applicable_to_all_entities, empty($)) ?: ERROR_OFFER_APPLICABLE_TO_ALL_ENTITIES_AND_HAS_ENTITY_IDS"
  }];

  // If true, this offer is applicable to all entities under the aggregator.
  // Only applicable for add on offers.
  bool add_on_offer_applicable_to_all_entities = 17 [(validator.rule) = {
    predicate: "if(empty($entity_ids), $ == true) ?: ERROR_OFFER_APPLICABLE_TO_ALL_ENTITIES_AND_HAS_ENTITY_IDS"
  }];

  // An offer can be provided by the aggregator, an individual merchant, or even
  // a third party as an add on.
  // Required.
  OfferSource offer_source = 3 [(validator.rule) = {
    predicate: "$ == OFFER_SOURCE_AGGREGATOR or $ == OFFER_SOURCE_MERCHANT ?: WARNING_ILLEGAL_OFFER_SOURCE"
  }];


  // The service that is providing the offer. An offer_id can belong to only one
  // action_type. If an offer can be shared across multiple service types then
  // duplicate offers with unique Ids are expected to be created for each
  // service type.
  // Required.
  ActionType action_type = 4 [(validator.rule) = {
    predicate: "$ != ACTION_TYPE_UNSPECIFIED ?: WARNING_ILLEGAL_ACTION_TYPE"
  }];

  // The methods the offer can be availed - walk in, reservation, online, etc.
  // Required.
  repeated OfferMode offer_modes = 5 [(validator.rule) = {
    can_report_all_predicate_violations: true,
    predicate: "not empty($) ?: WARNING_MISSING_OFFER_MODE",
    predicate: "if(contains($, OFFER_MODE_PAID_RESERVATION) and $offer_category == OFFER_CATEGORY_BASE_OFFER, has($offer_details.booking_cost) and ($offer_details.booking_cost.units > 0 or $offer_details.booking_cost.nanos > 0)) ?: ERROR_MISSING_BOOKING_COST"
    predicate: "if(not contains($, OFFER_MODE_PAID_RESERVATION) and $offer_category == OFFER_CATEGORY_BASE_OFFER, not has($offer_details.booking_cost) or ($offer_details.booking_cost.units == 0 and $offer_details.booking_cost.nanos == 0)) ?: ERROR_ILLEGAL_OFFER_MODE"
    element_predicate: "$ != OFFER_MODE_OTHER ?: WARNING_ILLEGAL_OFFER_MODE",
  }];

  // The category of the offer.
  // Required.
  OfferCategory offer_category = 6 [(validator.rule) = {
    predicate: "$ != OFFER_CATEGORY_UNSPECIFIED ?: WARNING_ILLEGAL_OFFER_CATEGORY"
  }];

  // Non-negative integer ([1-100], where 1 represents the highest priority)
  // indicating the priority level of the offer assigned by the source. When
  // multiple offers are available for the same merchant, this will be a signal
  // for ranking offers. 0 would represent that the priority is not set.
  int32 source_assigned_priority = 7;

  // Details of the offer such as the discount, booking cost, etc.
  // Required.
  OfferDetails offer_details = 8 [
    (validator.rule) = { is_required: "true ?: WARNING_MISSING_OFFER_DETAILS" }
  ];

  // Describes how the offer is restricted i.e. whether a subscription/payment
  // instrument is required, whether this offer can be combined with other
  // offers (and what types), etc.
  // Required.
  OfferRestrictions offer_restrictions = 9 [(validator.rule) = {
    is_required: "true ?: WARNING_MISSING_OFFER_RESTRICTIONS"
  }];

  // Details of a coupon.
  // Required for offer_category: OFFER_CATEGORY_ADD_ON_COUPON_OFFER.
  Coupon coupon = 10 [(validator.rule) = {
    is_required: "$offer_category == OFFER_CATEGORY_ADD_ON_COUPON_OFFER ?: WARNING_MISSING_COUPON"
  }];

  // Details of a payment instrument.
  // Required for offer_category: OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER.
  PaymentInstrument payment_instrument = 11 [(validator.rule) = {
    is_required: "$offer_category == OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER ?: WARNING_MISSING_PAYMENT_INSTRUMENT"
  }];

  // Details of a subscription.
  // Required for offer_category: OFFER_CATEGORY_ADD_ON_SUBSCRIPTION_OFFER.
  Subscription subscription = 12 [(validator.rule) = {
    is_required: "$offer_category == OFFER_CATEGORY_ADD_ON_SUBSCRIPTION_OFFER ?: WARNING_MISSING_SUBSCRIPTION"
  }];

  // Terms and conditions of the offer.
  // Required.
  Terms terms = 13
      [(validator.rule) = { is_required: "true ?: WARNING_MISSING_TERMS" }];

  // The validity period of the offer. Describes what time period the offer is
  // valid for including start and end times, days of the week, etc.
  // Required.
  repeated ValidityPeriod validity_periods = 14 [(validator.rule) = {
    can_report_all_predicate_violations: true,
    predicate: "not empty($) ?: WARNING_MISSING_VALID_PERIOD",
    element_predicate: "has($.valid_period) ?: WARNING_MISSING_VALID_PERIOD",
    element_predicate: "if(contains($offer_modes, OFFER_MODE_FREE_RESERVATION) or contains($offer_modes, OFFER_MODE_PAID_RESERVATION), "
                       "not empty($.time_of_day)) ?: WARNING_MISSING_VALID_PERIOD_TIME_OF_DAY",
    element_predicate: "if(has($.valid_period), has($.valid_period.valid_from_time)) ?: WARNING_MISSING_VALID_PERIOD_VALID_FROM_TIME"
  }];

  // URL to the merchant's offer page.
  // Required for offer_category: OFFER_CATEGORY_BASE_OFFER.
  string offer_url = 15 [(validator.rule) = {
    predicate: "if($offer_category == OFFER_CATEGORY_BASE_OFFER, not empty($)) ?: ERROR_MISSING_OFFER_URL"
  }];

  // URL to the merchant’s offer image.
  string image_url = 16;

}

OfferSource definition

enum OfferSource {
  OFFER_SOURCE_UNSPECIFIED = 0;
  OFFER_SOURCE_AGGREGATOR = 1;
}

ActionType definition

enum ActionType {
  ACTION_TYPE_UNSPECIFIED = 0;
  ACTION_TYPE_DINING = 4;
}

OfferMode definition

enum OfferMode {
  OFFER_MODE_OTHER = 0;
  OFFER_MODE_WALK_IN = 1;
  OFFER_MODE_FREE_RESERVATION = 2;
  OFFER_MODE_PAID_RESERVATION = 3;
  OFFER_MODE_ONLINE_ORDER = 4;
}

OfferCategory definition

// Category of the offer. A base offer is a standard offer available to all
// customers such as 10% off spending over $100. A base offer restricted by a
// coupon or payment instrument will have the respective fields set. We also
// have add on x offers such as ADD_ON_PAYMENT_OFFER. Such offers can be added
// to other offers to gain additional discounts.
enum OfferCategory {
  OFFER_CATEGORY_UNSPECIFIED = 0;
  OFFER_CATEGORY_BASE_OFFER = 1;
  OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER = 2;
  OFFER_CATEGORY_ADD_ON_COUPON_OFFER = 3;
  OFFER_CATEGORY_ADD_ON_SUBSCRIPTION_OFFER = 4;
}

OfferDetails definition

// Next tag: 13
message OfferDetails {
  option (validator.defs) = {
    feature: "ignore_offers_with_no_monetary_value"
  };

  // The offer text the offer provider wants to display to customers on the
  // search results page.
  // Required.
  string offer_display_text = 1 [(validator.rule) = {
    predicate: "not empty($) ?: ERROR_MISSING_OFFER_DISPLAY_TEXT"
  }];


  // The discount can be a percentage or a fixed value subtracted from the total
  // value.
  // For example:
  // 1. 10% off the final bill.
  // 2. $15 off an order.
  // Merchants can also offer custom discounts such as ‘buy one get one free’
  // through the relevant specification fields.
  // Required.
  oneof offer_specification {
    option (validator.one_of).is_required =
        "true ?: ERROR_MISSING_OFFER_SPECIFICATION";

    // Percentage of the bill that is discounted.
    // [0, 100]
    // For 1+1 or 50% off offers that are applicable to the whole meal
    // (e.g. 1+1 buffet, 1+1 on entire bill, 1+1 on set menu), this value can
    // be set to 50.
    float discount_percent = 2 [(validator.rule) = {
      predicate: "if (#ignore_offers_with_no_monetary_value, $ != 0) ?: ERROR_NO_MONETARY_VALUE"
    }];

    // Fixed value of the discount.
    google.type.Money discount_value = 3 [(validator.rule) = {
      predicate: "if (#ignore_offers_with_no_monetary_value, $.units != 0 or $.nanos != 0) ?: ERROR_NO_MONETARY_VALUE"
    }];

    // Free-form text to describe the discount.
    // For specific 1+1 offers (e.g. 1+1 drinks, +1 main course, 1+1
    // selected menu items), these details should be described here.
    string other_offer_detail_text = 4 [(validator.rule) = {
      // Since this is a oneof the predicate will be checked only if this
      // field is explicitly set.
      predicate: "not #ignore_offers_with_no_monetary_value ?: ERROR_NO_MONETARY_VALUE"
    }];
  }

  // The maximum discount that can be availed. For example, 10% off up to $100.
  google.type.Money max_discount_value = 5;

  // The minimum spend value to avail the discount.
  // For example, 10% off when the total price is $100 or more.
  google.type.Money min_spend_value = 6;

  // The cost to book this offer. For example, $100 off the final bill when a
  // table is reserved at the cost of $15.
  google.type.Money booking_cost = 7;

  // The unit of the booking cost. For example, per person, per transaction.
  FeeUnit booking_cost_unit = 11;

  Fee convenience_fee = 12;

  // Whether the booking cost is adjustable i.e. the booking cost is subtracted
  // from the final bill.
  // For example:
  // 30% off dinner with reservation. Cost to reserve $15 and it will be
  // applied to the final bill.
  // Hence final bill: Total Spent - 30% - $15
  bool booking_cost_adjustable = 8;

  // Additional fees that are charged to the user.
  // Examples: convenience, handling etc.
  repeated AdditionalFee additional_fees = 10;
}

OfferRestrictions definition

message OfferRestrictions {
  // Whether this offer can be combined with other offers.
  // When true, partners can specify what offers this offer can be combined
  // with. If both combinable_offer_categories & combinable_offer_ids are set
  // then any offer matching one of the conditions above will be combinable.
  bool combinable_with_other_offers = 1;

  // List of offer types that this offer can be combined with. For example, this
  // offer may be combinable with other Coupons. If combinable_with_other_offers
  // is true and this field is unset all types will be combinable.
  repeated OfferCategory combinable_offer_categories = 2;

  // List of offer_ids that this offer can be combined with. Some offers may
  // only be combined with certain specific other offer_ids (can be
  // considered parent offers). If combinable_with_other_offers is true and this
  // field is unset all offer ids will be combinable.
  repeated string combinable_offer_ids = 3;

  // List of conditions that must be met for the offer to be valid (e.g.,
  // non-alcoholic drinks, food).
  repeated OfferCondition inclusions = 5;

  // List of conditions that would invalidate the offer (e.g., buffet, combo
  // offers, and cocktails ).
  repeated OfferCondition exclusions = 6;

  // The minimum number of people required to avail the offer.
  int32 min_guest = 7;

  // Restrictions specific to food offers.
  FoodOfferRestrictions food_offer_restrictions = 4;
}

FoodOfferRestrictions definition

message FoodOfferRestrictions {
  // The meal types the offer can be applied to, such as lunch or dinner.
  // If unset, the offer can be applied to all meal types.
  repeated MealType meal_types = 1;

  // Whether the offer can only be applied to certain courses.
  bool restricted_to_certain_courses = 2;
}

MealType definition

enum MealType {
  MEAL_TYPE_UNSPECIFIED = 0;
  MEAL_TYPE_BREAKFAST = 1;
  MEAL_TYPE_LUNCH = 2;
  MEAL_TYPE_DINNER = 3;
}

PaymentInstrument definition

message PaymentInstrument {
  // List of payment instruments that can be used to avail the offer.
  // Required.
  repeated PaymentInstrumentItem items = 1 [(validator.rule) = {
    predicate: "not empty($) ?: WARNING_MISSING_PAYMENT_INSTRUMENT_ITEMS"
  }];

  // Name of the payment instrument provider. Could be a banking partner, name
  // of a bank, etc. For example: American Express, HDFC, ICICI.
  // Required.
  string provider_name = 2 [(validator.rule) = {
    predicate: "not empty($) ?: WARNING_MISSING_PAYMENT_INSTRUMENT_PROVIDER_NAME"
  }];
}

PaymentInstrumentType definition

enum PaymentInstrumentType {
  PAYMENT_INSTRUMENT_TYPE_UNSPECIFIED = 0;
  PAYMENT_INSTRUMENT_CREDIT_CARD = 1;
  PAYMENT_INSTRUMENT_DEBIT_CARD = 2;
  PAYMENT_INSTRUMENT_BANK_ACCOUNT = 3;
  PAYMENT_INSTRUMENT_UPI = 4;
  PAYMENT_INSTRUMENT_ONLINE_WALLET = 5;
}

PaymentInstrumentItem definition

message PaymentInstrumentItem {
  // Type of the payment instrument.
  // Required.
  PaymentInstrumentType type = 1 [(validator.rule) = {
    predicate: "$ != PAYMENT_INSTRUMENT_TYPE_UNSPECIFIED ?: WARNING_ILLEGAL_PAYMENT_INSTRUMENT_ITEM_TYPE"
  }];

  // Name of the payment instrument item like the name of the credit card.
  // For example: HDFC Infinia, American Express Platinum.
  // Required.
  string name = 2 [(validator.rule) = {
    predicate: "not empty($) ?: WARNING_MISSING_PAYMENT_INSTRUMENT_ITEM_NAME"
  }];
}

Coupon definition

message Coupon {
  // The coupon text the offer provider wants to display to users.
  string text = 1;

  // Coupon code required to redeem the offer.
  // Required.
  string code = 2 [(validator.rule) = {
    predicate: "not empty($) ?: WARNING_MISSING_COUPON_CODE"
  }];
}

Subscription definition

message Subscription {
  // The name of the subscription.
  // Required.
  string name = 1 [(validator.rule) = {
    predicate: "not empty($) ?: WARNING_MISSING_SUBSCRIPTION_NAME"
  }];

  // Whether the subscription is auto added when a user avails this offer
  bool subscription_auto_added = 2;

  // The cost of the subscription.
  // Required.
  google.type.Money cost = 3 [(validator.rule) = {
    is_required: "true ?: WARNING_MISSING_SUBSCRIPTION_COST"
    predicate: "$.units > 0 or $.nanos > 0 ?: WARNING_MISSING_SUBSCRIPTION_COST"
  }];

  // How long the subscription is valid for at the subscription_cost.
  // Required.
  google.protobuf.Duration subscription_duration = 4 [(validator.rule) = {
    is_required: "true ?: WARNING_MISSING_SUBSCRIPTION_DURATION"
    predicate: "$.seconds > 0 or $.nanos > 0 ?: WARNING_MISSING_SUBSCRIPTION_DURATION"
  }];

  // URL to the partner's terms and conditions relevant to this subscription.
  string terms_and_conditions_url = 5;
}

Terms definition

message Terms {
  // URL to the partner's terms and conditions.
  string url = 1;

  // Whether the offer is restricted to certain users.
  bool restricted_to_certain_users = 2;

  // Primary T&C text provided by the partner.
  string terms_and_conditions = 3;

  // Terms and conditions in addition to the primary T&C from the partner.
  repeated string additional_terms_and_conditions = 4;
}

ValidityPeriod definition

message ValidityPeriod {
  // The start and end timestamp that the offer is valid for.
  // These times must represent distinct days i.e. the start time must be 00:00
  // (beginning of the day) and the end time must be 00:00 (exclusive) on the
  // day the validity period ends.
  ValidityRange valid_period = 1;

  // Specifies the valid time interval on a given day and which days are
  // available for the offer.
  // For example:
  // Monday: 10AM to 5PM
  // Tuesday: 10AM to 2PM
  // Tuesday:  5PM to 7PM
  // Wed, Thur, Fri, Sat, Sun: 3PM to 7PM
  // If none set, it means the offer is available for all time within
  // `valid_period`.
  repeated TimeOfDayWindow time_of_day = 2;

  // Specifies exceptions to the above valid_period and valid_time_of_week
  repeated ValidTimeException time_exceptions = 3;
}

ValidityRange definition

// A closed-open timestamp range.
message ValidityRange {
  // The beginning time of the range (inclusive).
  // Required.
  google.protobuf.Timestamp valid_from_time = 1;

  // The ending time of the range (exclusive).
  // If not set, it means that this period is never ending.
  // Optional.
  google.protobuf.Timestamp valid_through_time = 2;
}

TimeOfDayWindow definition

message TimeOfDayWindow {
  option (validator.defs) = {
    feature: "deals"
  };

  // The time window the order can be placed/fulfilled.
  // Required.
  TimeOfDayRange time_windows = 1 [
    (validator.rule) = { is_required: "#deals ?: WARNING_MISSING_TIME_WINDOW" }
  ];

  // The list of days in a week the windows are applied.
  // If none set, it means that it applies for all days of the week.
  // Optional.
  repeated google.type.DayOfWeek day_of_week = 2;
}

TimeOfDayRange definition

// A closed-open time range.
message TimeOfDayRange {
  option (validator.defs) = {
    feature: "deals"
  };

  // A Time indicating the beginning time of the day of the range (inclusive).
  // If not set, it means 00:00:00.
  // Optional.
  google.type.TimeOfDay open_time = 1 [
    (validator.rule) = { is_required: "#deals ?: WARNING_MISSING_OPEN_TIME" }
  ];

  // A Time indicating the ending time of the day of the range (exclusive).
  // If not set, it means 23:59:59.
  // Optional.
  google.type.TimeOfDay close_time = 2 [
    (validator.rule) = { is_required: "#deals ?: WARNING_MISSING_CLOSE_TIME" }
  ];
}

ValidTimeException definition

message ValidTimeException {
  option (validator.defs) = {
    feature: "deals"
  };

  // The start and end timestamp that the offer is not valid for.
  // These times must represent distinct days i.e. the start time must be 00:00
  // (beginning of the day) and the end time must be 00:00 (exclusive) on the
  // day the exception period ends.
  ValidityRange exceptional_period = 1 [(validator.rule) = {
    is_required: "#deals ?: WARNING_MISSING_EXCEPTIONAL_PERIOD"
  }];

}

AdditionalFee definition

message AdditionalFee {
  // The name of the additional fee. Examples: convenience fee, handling fee
  // etc.
  // Required.
  string name = 1 [(validator.rule) = {
    predicate: "if(has($fee), not empty($)) ?: ERROR_MISSING_ADDITIONAL_FEE_NAME",
  }];

  Fee fee = 2;
}

Fee definition

// Next ID: 5
message Fee {
  option (validator.defs) = {
    feature: "ignore_offers_with_no_monetary_value"
  };

  FeeUnit unit = 1;
  FeeType type = 2;
  oneof cost {
    google.type.Money amount = 3 [(validator.rule) = {
      predicate: "if($type == FEE_TYPE_FIXED and not #ignore_offers_with_no_monetary_value, $.units > 0 or $.nanos > 0) ?: ERROR_NO_MONETARY_VALUE"
    }];
    MoneyRange amount_range = 4;
  }
}

FeeType definition

enum FeeType {
  FEE_TYPE_UNSPECIFIED = 0;
  FEE_TYPE_FIXED = 1;
  FEE_TYPE_VARIABLE = 2;
}

FeeUnit definition

enum FeeUnit {
  FEE_UNIT_UNSPECIFIED = 0;
  FEE_UNIT_PER_GUEST = 1;
  FEE_UNIT_PER_TRANSACTION = 2;
}

MoneyRange definition

// Wrapper for a range of monetary amount that could be bounded or unbounded.
// At least one of min_amount and max_amount is required.
message MoneyRange {
  // Minimum amount.
  google.type.Money min_amount = 1
      ;

  // Maximum amount.
  google.type.Money max_amount = 2;
}

OfferCondition definition

message OfferCondition {
  string description = 1;
}

Other generic specifications

Samples

Example 1

{
  "data": [
    {
      "offer_id": "offer-1",
      "entity_ids": ["dining-1"],
      "offer_source": "OFFER_SOURCE_AGGREGATOR",
      "action_type": "ACTION_TYPE_DINING",
      "offer_modes": ["OFFER_MODE_WALK_IN", "OFFER_MODE_FREE_RESERVATION"],
      "offer_category": "OFFER_CATEGORY_BASE_OFFER",
      "offer_details": {
        "offer_display_text": "₹100 off on your order",
        "discount_value": {
          "currency_code": "INR",
          "units": 100
        }
      },
      "offer_restrictions": {
        "combinable_with_other_offers": true,
        "combinable_offer_categories": [
          "OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER",
          "OFFER_CATEGORY_ADD_ON_COUPON_OFFER"
        ]
      },
      "terms": {
        "restricted_to_certain_users": false,
        "terms_and_conditions": "Valid on all menu items."
      },
      "validity_periods": [
        {
          "valid_period": {
            "valid_from_time": { "seconds": 1687062000 },
            "valid_through_time": { "seconds": 1956556800 }
          }
        }
      ],
      "offer_url": "https://www.example-restaurant.com/offer/base_offer_1",
      "image_url": "https://www.example-restaurant.com/images/offer_base.jpg"
    },
    {
      "offer_id": "offer-2",
      "entity_ids": ["dining-1"],
      "offer_source": "OFFER_SOURCE_AGGREGATOR",
      "action_type": "ACTION_TYPE_DINING",
      "offer_modes": ["OFFER_MODE_WALK_IN"],
      "offer_category": "OFFER_CATEGORY_ADD_ON_COUPON_OFFER",
      "coupon": {
        "text": "Use code STUDENT for 10% off",
        "code": "STUDENT"
      },
      "offer_details": {
        "offer_display_text": "10% off with code STUDENT",
        "discount_percent": 10.0
      },
      "offer_restrictions": {
        "combinable_with_other_offers": true,
        "combinable_offer_categories": ["OFFER_CATEGORY_BASE_OFFER"]
      },
      "terms": {
        "restricted_to_certain_users": true,
        "terms_and_conditions": "Only available for students."
      },
      "validity_periods": [
        {
          "valid_period": {
            "valid_from_time": { "seconds": 1687062000 },
            "valid_through_time": { "seconds": 1956556800 }
          }
        }
      ],
      "offer_url": "https://www.example-restaurant.com/offer/coupon_offer_2"
    },
    {
      "offer_id": "offer-3",
      "entity_ids": ["dining-1"],
      "offer_source": "OFFER_SOURCE_AGGREGATOR",
      "action_type": "ACTION_TYPE_DINING",
      "offer_modes": ["OFFER_MODE_FREE_RESERVATION"],
      "offer_category": "OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER",
      "payment_instrument": {
        "items": [
          { "type": "PAYMENT_INSTRUMENT_ONLINE_WALLET", "name": "my-wallet" }
        ],
        "provider_name": "My Wallet Provider"
      },
      "offer_details": {
        "offer_display_text": "10% off when you pay with my-wallet",
        "discount_percent": 10.0
      },
      "offer_restrictions": {
        "combinable_with_other_offers": true,
        "combinable_offer_categories": ["OFFER_CATEGORY_BASE_OFFER"]
      },
      "terms": {
        "restricted_to_certain_users": false
      },
      "validity_periods": [
        {
          "valid_period": {
            "valid_from_time": { "seconds": 1687062000 },
            "valid_through_time": { "seconds": 1956556800 }
          }
        }
      ],
      "offer_url": "https://www.example-restaurant.com/offer/payment_offer_3"
    },
    {
      "offer_id": "offer-4",
      "entity_ids": ["dining-1"],
      "offer_source": "OFFER_SOURCE_AGGREGATOR",
      "action_type": "ACTION_TYPE_DINING",
      "offer_modes": ["OFFER_MODE_FREE_RESERVATION"],
      "offer_category": "OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER",
      "payment_instrument": {
        "items": [
          { "type": "PAYMENT_INSTRUMENT_ONLINE_WALLET", "name": "my-wallet" }
        ],
        "provider_name": "My Wallet Provider"
      },
      "offer_details": {
        "offer_display_text": "15% off when you pay with my-wallet on weekdays between 2pm and 6pm",
        "discount_percent": 15.0
      },
      "offer_restrictions": {
        "combinable_with_other_offers": true,
        "combinable_offer_ids": ["OFFER_CATEGORY_BASE_OFFER"]
      },
      "terms": {
        "restricted_to_certain_users": false
      },
      "validity_periods": [
        {
          "valid_period": {
            "valid_from_time": { "seconds": 1687062000 },
            "valid_through_time": { "seconds": 1956556800 }
          },
          "time_of_day": [
            {
              "time_windows": {
                "open_time": { "hours": 14 },
                "close_time": { "hours": 18 }
              },
              "day_of_week": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ]
            }
          ]
        }
      ],
      "offer_url": "https://www.example-restaurant.com/offer/payment_offer_weekdays_4"
    },
    {
      "offer_id": "offer-5",
      "entity_ids": ["dining-1"],
      "offer_source": "OFFER_SOURCE_AGGREGATOR",
      "action_type": "ACTION_TYPE_DINING",
      "offer_modes": ["OFFER_MODE_WALK_IN"],
      "offer_category": "OFFER_CATEGORY_BASE_OFFER",
      "subscription": {
        "name": "Foodie Club",
        "subscription_auto_added": false,
        "cost": {
          "currency_code": "INR",
          "units": 499
        },
        "subscription_duration": { "seconds": 2592000 },
        "terms_and_conditions_url": "https://www.example-restaurant.com/subscriptions/foodie-club-terms"
      },
      "offer_details": {
        "offer_display_text": "Join Foodie Club for ₹499/month and get 20% off every bill!",
        "discount_percent": 20.0
      },
      "offer_restrictions": {
        "combinable_with_other_offers": false
      },
      "terms": {
        "restricted_to_certain_users": false,
        "terms_and_conditions": "Subscription benefits apply to all bills paid during the subscription period."
      },
      "validity_periods": [
        {
          "valid_period": {
            "valid_from_time": { "seconds": 1687062000 }
          }
        }
      ],
      "offer_url": "https://www.example-restaurant.com/offer/subscription_offer_5"
    }
  ]
}

File Descriptor

{
  "generation_timestamp": 1692998244,
  "name": "google.offer",
  "data_file": [
    "offer_1692825444.json"
  ]
}