Availability feed

Definitions

AvailabilityFeed Definition

message AvailabilityFeed {
  FeedMetadata metadata = 1;
  repeated ServiceAvailability service_availability = 2;
}

ServiceAvailability Definition

message ServiceAvailability {
  // If provided, we will consider the Availability entities provided to be a
  // complete snapshot from [start_timestamp_restrict, end_timestamp_restrict).
  // That is, all existing availability will be deleted if the following
  // condition holds true:
  //
  //    start_timestamp_restrict <= Availability.start_sec &&
  //    Availability.start_sec < end_timestamp_restrict
  //
  // If a duration message is set, the condition is further restricted:
  //   Availability.duration == duration_restrict_sec
  //
  // If a resource_restrict message is set, the condition is further restricted:
  //
  //    Availability.resource.staff_id == resource_restrict.staff_id &&
  //    Availability.resource.room_id == resource_restrict.room_id
  //
  // These fields are typically used to provide a complete update of
  // availability in a given time range.
  //
  // Setting start_timestamp_restrict while leaving end_timestamp_restrict unset
  // is interpreted to mean all time beginning at start_timestamp_restrict.
  //
  // Setting end_timestamp_restrict while leaving start_timestamp_restrict unset
  // is interpreted to mean all time up to the end_timestamp_restrict.
  //
  // In Unix time format (seconds since the epoch) from UTC. (both optional)
  int64 start_timestamp_restrict = 1;
  int64 end_timestamp_restrict = 2;

  // If provided, the timestamp restricts will be applied only to the given
  // merchant or service.
  //
  // These fields are typically used to provide complete snapshot of
  // availability in a given range (defined above) for a specific merchant or
  // service.
  //
  // Leaving these fields unset, or setting these to the empty string or null,
  // is interpreted to mean that no restrict is intended. (both optional)
  string merchant_id_restrict = 3;
  string service_id_restrict = 4;

  // Setting duration further restricts the scope of the update to just the
  // availability with matching duration.
  //
  // In seconds. (optional)
  int64 duration_restrict_sec = 7;

  // Setting resources_restrict further restricts the scope of the update to
  // just this set of resources. All id fields of the resources must match
  // exactly. (optional)
  Resources resources_restrict = 6;

  // All Availability Slots included in this Service Availability (required)
  repeated Availability availability = 5;
}

Availability Definition

// An availability of the merchant's service, indicating time and number
// of spots.
// The availability feed should be a list of this message.
// Please note that it's up to the partner to call out all the possible
// availabilities.
// If a massage therapist is available 9am-12pm, and they provide
// one-hour massage sessions, the aggregator should provide the feed as
//   availability {start_sec: 9am, duration: 60 minutes, ...}
//   availability {start_sec: 10am, duration: 60 minutes, ...}
//   availability {start_sec: 11am, duration: 60 minutes, ...}
// instead of
//   availability {start_sec: 9am, duration: 180 minutes, ...}
//
message Availability {
  // An opaque string from an aggregator to identify a merchant. (required)
  string merchant_id = 1;
  // An opaque string from aggregator to identify a service of the
  // merchant. (required)
  string service_id = 2;
  // Start time of this availability, using epoch time in seconds in UTC.
  //(required)
  int64 start_sec = 3;
  // Duration of the service in seconds, e.g. 30 minutes for a chair massage.
  // (required)
  int64 duration_sec = 4;
  // Number of total spots and open spots of this availability.
  // E.g. a Yoga class of 10 spots with 3 booked.
  //   availability {spots_total: 10, spots_open: 7 ...}
  // E.g. a chair massage session which was already booked.
  //   availability {spots_total: 1, spots_open: 0 ...}
  //
  // Note: If sending requests using the availability compression format defined
  //       below, these two fields will be inferred. A Recurrence
  //       implies spots_total=1 and spots_open=1. A ScheduleException implies
  //       spots_total=1 and spots_open=0.
  // (both required if recurrence not set)
  int64 spots_total = 5;
  int64 spots_open = 6;
  // An optional opaque string to identify this availability slot. If set, it
  // will be included in the requests that book/update/cancel appointments.
  // (optional)
  string availability_tag = 7;

  // Optional resources used to disambiguate this availability slot from
  // others when different staff, room, or party_size values are part
  // of the service.
  //
  // E.g. the same Yoga class with two 2 instructors.
  //  availability { resources { staff_id: "1" staff_name: "Amy" }
  //                 spots_total: 10 spots_open: 7 }
  //  availability { resources { staff_id: "2" staff_name: "John" }
  //                 spots_total: 5 spots_open: 2 }
  // (optional)
  Resources resources = 8;

  // A list of IDs referencing the payment options which can be used to pay
  // for this slot. The actual payment options are defined at the Merchant
  // level, and can also be shared among multiple Merchants.
  //
  // This field overrides any payment_option_ids specified in the service
  // message. Similarly payment_option_ids specified here do NOT have to be
  // present in the service message, though must be defined at the
  // Merchant level.
  // Our current implementation limits the number of entries in this array to
  // one element. Multiple payment_option_id are still allowed at the Service
  // level, but an override at the availability slot level, is limited to a
  // single payment_option_id. (optional)
  repeated string payment_option_id = 9;

  // Recurrence messages are optional, but allow for a more compact
  // representation of consistently repeating availability slots. They typically
  // represent a day's working schedule.
  // ScheduleException messages are then used to represent booked/unavailable
  // time ranges within the work day.
  //
  // Requirements:
  //   1. The expansion of availability slots or recurrences must NOT create
  //      identical slots. If the ids, start_sec, duration_sec, and resources
  //      match, slots are considered identical.
  //   2. Do NOT mix the standard availability format and recurrence within the
  //      slots of a single service. Recurrence benefits merchants/services that
  //      offer appointments. The standard format is geared towards
  //      merchants/services with regularly scheduled classes.
  message Recurrence {
    // The inclusive maximum UTC timestamp the availability repeats until.
    // (required)
    int64 repeat_until_sec = 1;
    // Defines the time between successive availability slots.
    //
    // Example: An availability with a duration of 20 min, a repeat_every_sec of
    // 30 min, a start_sec of 9:00am, and a repeat_until_sec of 11:00am will
    // yield slots at 9-9:20am, 9:30-9:50am, 10-10:20am, 10:30-10:50am,
    // 11-11:20am. (required)
    int32 repeat_every_sec = 2;
  }
  // The recurrence information for the availability, representing more than one
  // start time. A recurrence should contain appointments for one working day.
  // (optional)
  Recurrence recurrence = 10;

  // ScheduleException messages represent booked/unavailable time ranges within
  // the workday, which are exceptions to the recurrence described above. As
  // time slots are booked, the list of exceptions should be updated to reflect
  // the newly unavailable time ranges. The recurrence itself shouldn't be
  // modified.
  message ScheduleException {
    // The time range of the exception. Any slots described by the recurrence
    // which overlap this closed-open time range will be considered unavailable.
    //
    // Example: If the recurrence specifies a duration of 20 min, a
    // repeat_every_sec of 30 min, a start_time of 9:00am, and a
    // repeat_until_sec of 11:00am, then a ScheduleException with a time_range
    // of 9:45am-11:00am would make unavailable the slots at 9:30-9:50am,
    // 10-10:20am, and 10:30-10:50am.
    //
    // Note that because the time range is closed-open, the slot beginning at
    // 11am slot would not be impacted.
    TimeRange time_range = 1;
  }
  // Times when this service cannot be scheduled. To limit the number of
  // schedule_exception messages, consider joining adjacent exceptions.
  // (optional)
  repeated ScheduleException schedule_exception = 11;

  // Defines how a deposit may be charged to the user. Overrides the service
  // deposit if one was specified. Setting this to an empty Deposit message
  // removes any service-level deposit. (optional)
  Deposit deposit = 12;

  // Defines a no show fee that may be charged to the user. Overrides the
  // service no show fee if one was specified. Setting this to an empty
  // NoShowFee message removes any service-level no show fee. (optional)
  NoShowFee no_show_fee = 13;

  // Optional prepayment information for this availability. Prepayment is only
  // available through the Payment Redirect Add-on
  Prepayment prepayment = 20;

  // Indicates whether the user must provide a credit card in order to book this
  // availability slot.
  // If the value is not set, it is inherited from the service level if it's set
  // there. (optional)
  RequireCreditCard require_credit_card = 14;


  // Availability level scheduling rules.
  message SchedulingRuleOverrides {
    // The last time (in seconds) that this slot is able to be booked. This
    // timestamp must be before the start_sec of the slot to be respected
    // (if users should be able to book after the start time, use service level
    // SchedulingRules.min_booking_buffer_before_end_time). If present, will
    // override anything specified in the min_booking_buffer of the
    // corresponding Service's SchedulingRules.
    int64 last_bookable_sec = 1;

    // The first time (in seconds) that this slot is able to be booked.
    int64 first_bookable_sec = 2;

    // If set, the last time (in seconds since the Unix epoch) that this
    // specific appointment slot can be cancelled through Reserve with Google.
    // This field will override any service-level cancellation rules. (optional)
    int64 last_online_cancellable_sec = 3;
  }

  // Availability scheduling rules. If fields are populated, they will override
  // any corresponding scheduling rules on the service-level SchedulingRules.
  SchedulingRuleOverrides scheduling_rule_overrides = 16;

  // This enum indicates what requirements exist for the user to
  // acknowledge or view the requested slots duration/end time.
  enum DurationRequirement {
    // The handling of the end time is not specified. This is the default.
    DURATION_REQUIREMENT_UNSPECIFIED = 0;

    // The end time is not shown to the user.
    DO_NOT_SHOW_DURATION = 1;

    // The end time has to be shown to the user before an appointment can be
    // made.
    MUST_SHOW_DURATION = 2;
  }

  // The requirement to show the slots duration and/or endtime.
  // This field will be ignored if the slot is unavailable. Not used in the
  // Things-To-Do vertical. (optional)
  DurationRequirement duration_requirement = 18;

  // The confirmation modes used when booking availabilities.
  enum ConfirmationMode {
    // The confirmation mode was not specified.
    // Synchronous confirmation will be assumed.
    CONFIRMATION_MODE_UNSPECIFIED = 0;
    // Bookings for this availability will be confirmed synchronously.
    CONFIRMATION_MODE_SYNCHRONOUS = 1;
    // Bookings for this availability will be confirmed asynchronously.
    CONFIRMATION_MODE_ASYNCHRONOUS = 2;
  }
  // The confirmation mode that will be used when booking this availability.
  // Attempts to create bookings for availabilities with a confirmation mode
  // of CONFIRMATION_MODE_SYNCHRONOUS must be immediatlely confirmed or denied.
  // Attempts to create bookings for availabilities with confirmation mode
  // of CONFIRMATION_MODE_ASYNCHRONOUS must be either immediately denied
  // or created with status PENDING. Populating confirmation_mode is strongly
  // recommended, but not strictly required. (optional)
  ConfirmationMode confirmation_mode = 17;

  // The reason why a slot requires a linkout. Currently only used for Dining
  // Reservations Payment Redirect Partners.
  enum LinkoutRequiredReason {
    // Default value: Do not use, equates to unknown.
    LINKOUT_REQUIRED_REASON_UNSPECIFIED = 0;
    // Slot requires payment in the partner platform to be booked.
    PAYMENT_REQUIRED = 1;
  }

  // The reason a linkout is required for this slot. If set, the Merchant
  // resource for this slot must have a valid LinkoutTemplate.
  LinkoutRequiredReason linkout_required_reason = 19;
}

Resources Definition

// A resource is used to disambiguate availability slots from one another when
// different staff, room or party_size values are part of the service.
// Multiple slots for the same service and time interval can co-exist when they
// have different resources.
message Resources {
  // One of staff_id, room_id, or party_size must be set.

  // Optional ID for a staff member providing the service. This field identifies
  // the staff member across all merchants, services, and availability records.
  // It also needs to be stable over time to allow correlation with past
  // bookings. (optional but required if staff_name is present)
  string staff_id = 1;

  // Optional name of a staff member providing the service. This field will be
  // displayed to users making a booking, and should be human-readable, as
  // opposed to an opaque identifier. (optional but required if staff_id is
  // present)
  string staff_name = 2;

  // An optional ID for the room the service is located in. This field
  // identifies the room across all merchants, services, and availability
  // records. It also needs to be stable over time to allow correlation with
  // past bookings. (optional but required if room_name is present)
  string room_id = 3;

  // An optional name for the room the service is located in or experience of
  // of the service. This field will be displayed to users making a booking,
  // and should be human readable, as opposed to an opaque identifier.
  // A room name should only be used for seating areas or prepaid experiences.
  // Examples of room names include "Bar", "Patio", "Dining Room". Examples of
  // dining experiences using room names include "Five-Course Tasting Menu",
  // "Chef Omakase". It is strongly recommended that the default seating area
  // does not have a room associated with it.
  string room_name = 4;

  // Applicable only for Dining: The party size that can be accommodated
  // during this time slot. A restaurant can be associated with multiple Slots
  // for the same time, each specifying a different party_size, if for instance
  // 2, 3, or 4 people can be seated with a reservation. (optional)
  int32 party_size = 5;

  // Localized room description with a limit of 500 characters. If set,
  // a default value must be provided, it is preferred to use the common
  // languages for the merchant's locale.
  Text room_description = 7;
}

TimeRange Definition

// A closed-open time range, i.e. [begin_sec, end_sec)
message TimeRange {
  // Seconds of UTC time since Unix epoch (required)
  int64 begin_sec = 1;

  // Seconds of UTC time since Unix epoch (required)
  int64 end_sec = 2;
}

Price Definition

// The price of a service or a fee.
message Price {
  // The price in micro-units of the currency.
  // For example: 1.95 USD is 1950000 in micro-units.
  // If your price contains fractions of the smallest currency unit, then it
  // will be rounded using nearest even rounding (e.g. 2.5 cents rounded
  // to 2 cents, 3.5 cents rounded to 4 cents, 0.5 cents rounded to 0 cents,
  // 2.51 cents rounded to 3 cents). (required)
  int64 price_micros = 1;

  // The currency of the price that is defined in ISO 4217. (required)
  string currency_code = 2;

  // An optional and opaque string that identifies the pricing option that is
  // associated with the extended price. (optional)
  string pricing_option_tag = 3;
}

PriceRange Definition

// Wrapper for a range of monetary amount treated as unbounded unless both
// values are set. At least one of min_amount and max_amount is required.
message PriceRange {
  // Minimum amount.
  Price min_price = 1;

  // Maximum amount. Should always be > min_price.
  Price max_price = 2;
}

PriceInfo Definition

// Container for price details.
message PriceInfo {
  oneof price_options {
    Price price = 1;

    // The upper and/or lower bound
    PriceRange price_range = 2
        ;
  }

  // Defines how price or price range is applied (per person or fixed)
  PriceType price_type = 3;
}

Linkout Required Reason Definition

  // The reason why a slot requires a linkout. Currently only used for Dining
  // Reservations Payment Redirect Partners.
  enum LinkoutRequiredReason {
    // Default value: Do not use, equates to unknown.
    LINKOUT_REQUIRED_REASON_UNSPECIFIED = 0;
    // Slot requires payment in the partner platform to be booked.
    PAYMENT_REQUIRED = 1;
  }

Deposit Definition

// A deposit that the user may be charged or have a hold on their credit card
// for.
message Deposit {
  // Deposit amount.
  Price deposit = 1;

  // Minimum advance cancellation for the deposit.
  int64 min_advance_cancellation_sec = 2;

  // Defines how the deposit is determined from the availability.
  PriceType deposit_type = 3;
}

Prepayment Definition

// A payment the user may be charged as part of their reservation.
message Prepayment {
  PriceInfo price_info = 1;
}

NoShowFee Definition

// A fee that a user may be charged if they have made a booking but do not
// show up.
message NoShowFee {
  // The amount the user may be charged if they do not show up for their
  // reservation.
  Price fee = 1;

  // Defines how the fee is determined from the availability.
  PriceType fee_type = 3;
}

PriceType Definition

// Defines how a total price is determined from an availability.
enum PriceType {
  // The price is for a fixed amount. This is the default value if the field is
  // not set.
  //
  // Examples:
  //   $50 deposit to reserve a table; $20 no show fee for a yoga class
  FIXED_RATE_DEFAULT = 0;

  // The price specified is per person, and the total price is calculated
  // according to the party size specified in Resources as price_micros *
  // party_size. A PER_PERSON price must be accompanied by a party size in the
  // availability resources. If it is not, a party size of one is used.
  //
  // Examples:
  //   $10 each for tickets to a museum
  PER_PERSON = 1;
}

RequiredCreditCard Definition

// Defines whether a credit card is required in order to book an appointment.
enum RequireCreditCard {
  // The credit card requirement is not explicitly specified and the
  // behaviour is identical to the one specified for CONDITIONAL.
  REQUIRE_CREDIT_CARD_UNSPECIFIED = 0;

  // Google will require a credit card for the booking if any of the following
  // conditions are met:
  // * the availability has a price and the prepayment_type is REQUIRED
  // * the no_show_fee is set
  // * the deposit field is set.
  REQUIRE_CREDIT_CARD_CONDITIONAL = 1;

  // A credit card is always required in order to book this availability
  // regardless of other field values.
  REQUIRE_CREDIT_CARD_ALWAYS = 2;
}

Availability Feed samples

Availability

{
  "metadata": {
    "processing_instruction": "PROCESS_AS_COMPLETE",
    "shard_number": 0,
    "total_shards": 1,
    "nonce": "11203880",
    "generation_timestamp": 1524606581
  },
  "service_availability": [
    {
      "availability": [
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 6
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 5
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 4
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
         {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 3
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
         {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 2
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535853600,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 1
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 6
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 5
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
       {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 4
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 3
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 2
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        },
        {
          "spots_total": 1,
          "spots_open": 1,
          "duration_sec": 3600,
          "service_id": "reservation",
          "start_sec": 1535855400,
          "merchant_id": "dining-1",
          "resources": {
            "party_size": 1
          },
          "confirmation_mode": "CONFIRMATION_MODE_SYNCHRONOUS"
        }
      ]
    }
  ]
}