|  | syntax = "proto3"; | 
|  |  | 
|  | package maps.booking.feeds; | 
|  |  | 
|  | message FeedMetadata { | 
|  | enum ProcessingInstruction { | 
|  | // By default we will assume that this feed is an incremental feed. | 
|  | PROCESS_UNKNOWN = 0; | 
|  |  | 
|  | // This Feed message is one shard of a complete feed. Anything previously | 
|  | // supplied by this partner will be deleted; the contents of this feed | 
|  | // represent the entire state of the world. | 
|  | PROCESS_AS_COMPLETE = 1; | 
|  |  | 
|  | // This Feed message is one shard of an incremental feed. Existing entities | 
|  | // will be left untouched except as modified in this feed. | 
|  | PROCESS_AS_INCREMENTAL = 2; | 
|  | } | 
|  |  | 
|  | // Instructs us how to process the feed: either as a shard of a complete feed, | 
|  | // or as a shard of an incremental update. | 
|  | ProcessingInstruction processing_instruction = 1; | 
|  |  | 
|  | // The current shard and total number of shards for this feed. | 
|  | // | 
|  | // Shard number is assumed to be zero-based. | 
|  | // | 
|  | // There does not need to be any relationship to the file name. | 
|  | // | 
|  | // Shards do not need to be transferred in order, and they may not be | 
|  | // processed in order. | 
|  | int32 shard_number = 2; | 
|  | int32 total_shards = 3; | 
|  |  | 
|  | // An identifier that must be consistent across all shards in a feed. | 
|  | // This value must be globally unique across each feed type. | 
|  | // | 
|  | // This value ensures that complete feeds spanning multiple shards are | 
|  | // processed together correctly. | 
|  | // | 
|  | // Clients only need to set this value when the processing_instruction is set | 
|  | // to PROCESS_AS_COMPLETE and the feed spans multiple shards (defined by | 
|  | // total_shards). | 
|  | // | 
|  | // Feeds that span multiple shards must set this nonce to the same value. | 
|  | uint64 nonce = 5; | 
|  |  | 
|  | // The timestamp at which this feed shard was generated. | 
|  | // | 
|  | // In Unix time format (seconds since the epoch). | 
|  | int64 generation_timestamp = 4; | 
|  | } | 
|  |  | 
|  | message AvailabilityFeed { | 
|  | FeedMetadata metadata = 1; | 
|  | repeated ServiceAvailability service_availability = 2; | 
|  | } | 
|  |  | 
|  | 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 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). | 
|  | 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. | 
|  | string merchant_id_restrict = 3; | 
|  | string service_id_restrict = 4; | 
|  |  | 
|  | // 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. | 
|  | Resources resources_restrict = 6; | 
|  |  | 
|  | repeated Availability availability = 5; | 
|  | } | 
|  |  | 
|  | // 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. | 
|  | string merchant_id = 1; | 
|  | // An opaque string from aggregator to identify a service of the | 
|  | // merchant. | 
|  | string service_id = 2; | 
|  | // Start time of this availability, using epoch time in seconds. | 
|  | int64 start_sec = 3; | 
|  | // Duration of the service in seconds, e.g. 30 minutes for a chair massage. | 
|  | 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. | 
|  | 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. | 
|  | 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 } | 
|  | 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. | 
|  | 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. | 
|  | int64 repeat_until_sec = 1; | 
|  | // Defines the time between successive availability slots. | 
|  | // | 
|  | // E.g. 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. | 
|  | 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. | 
|  | Recurrence recurrence = 10; | 
|  |  | 
|  | // ScheduleException messages are used to represent booked/unavailable time | 
|  | // ranges within the work day. As time slots are booked, the list of | 
|  | // exceptions should grow to reflect the newly unavailable time ranges. | 
|  | // The recurrence itself shouldn't be modified. | 
|  | message ScheduleException { | 
|  | // The time range of the exception. | 
|  | TimeRange time_range = 1; | 
|  | } | 
|  | // When this service cannot be scheduled. To limit the number of | 
|  | // schedule_exception messages consider joining adjacent exceptions. | 
|  | repeated ScheduleException schedule_exception = 11; | 
|  | } | 
|  |  | 
|  | // 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 { | 
|  | // 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. | 
|  | // This field must be present 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. | 
|  | // This field must be present 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. | 
|  | // This field must be present if room_name is present. | 
|  | string room_id = 3; | 
|  |  | 
|  | // An optional name for the room the service is located in. This | 
|  | // field will be displayed to users making a booking, and should be human | 
|  | // readable, as opposed to an opaque identifier. | 
|  | // This field must be present if room_id is present. | 
|  | string room_name = 4; | 
|  |  | 
|  | // Applicable only for Dining: The party size which 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. | 
|  | int32 party_size = 5; | 
|  | } | 
|  |  | 
|  | message TimeRange { | 
|  | int64 begin_sec = 1; | 
|  | int64 end_sec = 2; | 
|  | } |