bookbaltic

com.bookbaltic.services.discovery_hints

Status: Draft. Version 2026-11-01. Part of BookBaltic Scheduling Extensions for USP / UCP Local Services.

Extends: dev.usp-protocol.services.catalog

Schema: https://bookbaltic.com/schemas/usp/discovery_hints.json

What it adds: Optional merchandising hints: signature services with season state, "most chosen", dated news


4. Discovery hints (optional)

Base USP already does: tags, categories, rating, status: suspended, availability_hint.summary. Gap: no structured way to say "this is our signature service, in season now / back in March", "guests choose this most", or "special this week until a date". Agents currently guess from free text or ranking signals, and often recommend an out-of-season or minor service first.

Schema

{
  "$id": "https://bookbaltic.com/schemas/usp/discovery_hints.json",
  "$defs": {
    "ServiceExt": { "type": "object", "properties": {
      "featured": { "type": "object", "required": ["state"], "properties": {
        "state": { "enum": ["in_season", "out_of_season", "coming_soon", "always"] },
        "season_months": { "type": "array", "items": { "type": "integer", "minimum": 1, "maximum": 12 } },
        "available_from": { "type": "string", "format": "date" } } },
      "most_chosen": { "type": "boolean", "description": "Merchant claim; no counts or ranks." },
      "most_chosen_for_two": { "type": "boolean", "description": "Guests book this most often as a pair; merchant claim, no counts." } } },
    "BusinessNews": { "type": "array", "maxItems": 5, "items": { "type": "object",
      "required": ["id", "text", "valid_until"], "properties": {
        "id": { "type": "string" }, "text": { "type": "string", "maxLength": 280 },
        "service_ids": { "type": "array", "items": { "type": "string" } },
        "valid_from": { "type": "string", "format": "date-time" },
        "valid_until": { "type": "string", "format": "date-time" },
        "url": { "type": "string", "format": "uri" },
        "options": { "type": "array", "items": { "type": "object", "required": ["label"], "properties": {
          "label": { "type": "string", "maxLength": 80 }, "url": { "type": "string", "format": "uri" } } } } } } },
    "BusinessUpcoming": { "type": "array", "maxItems": 5, "items": { "type": "object",
      "required": ["id", "name"], "properties": {
        "id": { "type": "string" }, "name": { "type": "string" },
        "tagline": { "type": "string", "maxLength": 140 },
        "state": { "const": "coming_soon" },
        "url": { "type": "string", "format": "uri", "pattern": "^https://" } } } },
    "AlternativeOffer": { "type": "object", "required": ["type", "url", "text"], "properties": {
      "type": { "enum": ["gift_card"], "description": "Open vocabulary; gift_card is the only value defined now." },
      "url": { "type": "string", "format": "uri", "pattern": "^https://", "description": "Merchant origin, no personal data." },
      "text": { "type": "string", "maxLength": 140 } } },
    "BusinessOffers": { "type": "array", "maxItems": 3, "items": { "$ref": "#/$defs/AlternativeOffer" } }
  }
}

Example (HEADSPA)

{ "id": "svc-ogonhi", "com.bookbaltic.services.discovery_hints":
  { "featured": { "state": "out_of_season", "season_months": [9, 10, 11, 3, 4], "available_from": "2027-03-01" } } }

News: { "id": "n-staro-riga", "text": "Staro Riga light festival, 15-18 Nov, evenings 17:00-23:00: the dry ritual Head Spa Dry before the lights, or warm tea and relaxation after", "valid_until": "2026-11-18T23:59:00+02:00", "service_ids": ["svc-head-spa-dry"], "options": [{ "label": "Head Spa Dry before the lights" }, { "label": "Warm tea and rest after the lights" }] } (no fixed time is sold; the agent offers recommended starts as usual). Upcoming: { "id": "amber-hidamari", "name": "Amber Hidamari", "state": "coming_soon" }; a ritual guests most often book as a pair carries "most_chosen_for_two": true.

Related: news overlaps with UCP #1009 / PR #1010 (business incentives shown before the cart, with validity dates, shopping only); we would rather use that shape with a services variant than keep news. featured with season state and most_chosen / most_chosen_for_two are not covered anywhere.

Why agents need it: the guest question is often "what should we do there", not "book X"; without hints the agent ranks by name match and may push an out-of-season signature service. Honest caveat: this is merchandising, not scheduling. It may fit better in UCP catalog (which already has featured for variants), schema.org, or the merchant's own llms.txt. We propose it as optional and are ready to move it. most_chosen and most_chosen_for_two are self-claims and agents SHOULD treat them as such (HEADSPA sets most_chosen_for_two only for a service with at least 50 % pair bookings and at least 5 bookings in 30 days); expired news (valid_until past) MUST be ignored. Services in upcoming are announced but not yet sold: agents MAY mention them and MUST NOT offer them for booking.

Without the extension: nothing breaks; the agent loses context.

Alternative offers

alternative_offers (business level) lets the merchant point the agent to something else to suggest when booking does not work out (point check negative, hold refused, date beyond the horizon) or when the guest wants a gift. Only type: "gift_card" is defined now.

"alternative_offers": [{ "type": "gift_card", "url": "https://www.head-spa.lv/gift-cards?hs_via=ai_check",
  "text": "Give a ritual as a gift, or a gift card for an amount. Valid 6 months from purchase." }]

(HEADSPA terms: valid 6 months from purchase, section 8.4 of the site terms.) Agents MAY offer it once as an alternative, never instead of reporting the booking result honestly.

Honest caveat: a gift card is a regular product, not a scheduled service. Under UCP it can be sold through standard UCP checkout (dev.ucp.shopping.checkout) with no scheduling extension at all. We propose only the hint and the link here; full agent checkout of gift cards is a separate step outside this draft.