{
  "schema_version": "1.1",
  "name": "Touri",
  "description": "Touri is a last-minute tour booking platform operating in Mexico. Agents can browse live experiences, view per-run pricing and availability, make negotiated price offers, or book directly at list price.",
  "url": "https://www.gotouri.com",
  "updated_at": "2026-09-21",
  "authentication": {
    "required_for": [
      "make_offer",
      "buy_now",
      "view_negotiation_thread",
      "view_bookings"
    ],
    "not_required_for": [
      "browse_experiences",
      "view_experience"
    ],
    "method": "browser_session",
    "login_page": "https://www.gotouri.com/login",
    "notes": "Unauthenticated agents can browse and view all experience and pricing data. Authentication is required to submit or respond to offers, complete bookings, or view negotiation threads."
  },
  "agent_policy": {
    "offer_submission": "Do not submit offers speculatively, in bulk, or without intent to complete the booking. Each offer notifies a real human guide in real time.",
    "hammering": "Do not repeatedly submit offers on the same run. The negotiation endpoint is rate-limited to 50 requests/minute and monitored for abuse.",
    "availability_polling": "Do not poll /explore or /experience/:id more frequently than the 300s cache TTL — responses will be identical within that window.",
    "automated_offers": "Agents acting on behalf of a user must have explicit user authorisation before submitting or accepting any offer or booking.",
    "compliance": "Use of this platform by automated agents is subject to the Touri terms of service at https://www.gotouri.com/help/terms."
  },
  "data_freshness": {
    "availability": "cache_up_to_300s",
    "pricing": "cache_up_to_300s",
    "experience_details": "cache_up_to_300s",
    "notes": "All discovery endpoints (/explore, /experience/:id, /run/:id) are Redis-cached with a 300s TTL. A run may fill between fetch and booking attempt — treat availability as indicative, not guaranteed."
  },
  "rate_limit_advisory": {
    "discovery": "rate-limited",
    "booking_actions": "rate-limited",
    "notes": "Rate limits are enforced server-side on all endpoints. Exceeding them will return 429."
  },
  "capabilities": [
    {
      "id": "browse_experiences",
      "description": "Browse all live, upcoming experiences with real-time availability and pricing.",
      "auth_required": false,
      "entry_point": "https://www.gotouri.com/cdmx/explore",
      "hubs": [
        {
          "code": "cdmx",
          "entry_point": "https://www.gotouri.com/cdmx/explore"
        },
        {
          "code": "puebla",
          "entry_point": "https://www.gotouri.com/puebla/explore"
        }
      ],
      "result_model": {
        "scope": "All open runs for the requested hub and date, plus the following calendar day (2-day window), in the hub's local timezone",
        "required_parameters": {
          "hub": "Location hub code, e.g. cdmx",
          "date": "Target date in YYYY-MM-DD format"
        },
        "pagination": "none — full result set returned in a single response",
        "notes": "Each card in the result links to a full experience detail page containing JSON-LD structured data."
      }
    },
    {
      "id": "view_experience",
      "description": "View full experience details including description, route, inclusions, pricing, and upcoming open runs with per-run availability. Returns up to 10 runs, ordered by start_time ascending, filtered to status=open and start_time >= now.",
      "auth_required": false,
      "url_pattern": "https://www.gotouri.com/{hub}/experience/{experience_id}/{experience_slug}",
      "parameters": {
        "hub": "Location hub code the experience belongs to, e.g. cdmx or puebla — see browse_experiences.hubs for the full list. The hub-less /experience/{id}/{slug} path still resolves via redirect but is not guaranteed to match the experience's actual hub."
      },
      "structured_data": {
        "format": "application/ld+json",
        "type": "schema.org/Event",
        "key_fields": {
          "name": "Experience title",
          "description": "Full experience description",
          "url": "Canonical experience URL",
          "offers": "Array — two entries per run: (1) fixed buy-now offer, (2) negotiable offer with priceSpecification",
          "offers[].@type": "schema.org/Offer",
          "offers[].url": "Direct booking URL for this run",
          "offers[].price": "List price per person (buy-now offer only)",
          "offers[].priceCurrency": "ISO 4217 currency code, e.g. USD or MXN",
          "offers[].availability": "schema.org/InStock or schema.org/SoldOut",
          "offers[].validFrom": "Run start time in ISO 8601 UTC",
          "offers[].priceSpecification.minPrice": "Floor price per person (negotiable offer only)",
          "offers[].priceSpecification.maxPrice": "List price per person (negotiable offer only)",
          "offers[].description": "Present on negotiable offer only — value: 'Negotiable — make an offer between floor and list price'"
        }
      }
    },
    {
      "id": "make_offer",
      "description": "Submit a negotiated price offer for a specific run. The agent sets a price between the floor and list price. The guide is notified and can accept, counter, or decline in real time.",
      "auth_required": true,
      "url_pattern": "https://www.gotouri.com/new?run={run_id}&ref=make_offer",
      "parameters": {
        "run": "required — the run ID to make an offer on",
        "ref": "optional — referral source, use make_offer"
      },
      "notes": "Offers below the floor price will be rejected. The floor price is exposed per run in the page's JSON-LD structured data. After submitting, a negotiation thread is created — see view_negotiation_thread."
    },
    {
      "id": "buy_now",
      "description": "Book a run immediately at the guide's listed price, bypassing negotiation.",
      "auth_required": true,
      "url_pattern": "https://www.gotouri.com/new?run={run_id}&buyNow=true",
      "parameters": {
        "run": "required — the run ID to book",
        "buyNow": "required — must be true"
      }
    },
    {
      "id": "view_negotiation_thread",
      "description": "View an active negotiation thread, see the current offer state, and submit a counter-offer.",
      "auth_required": true,
      "url_pattern": "https://www.gotouri.com/thread/{thread_id}",
      "offer_states": [
        "pending",
        "countered",
        "accepted",
        "declined",
        "expired"
      ]
    },
    {
      "id": "view_bookings",
      "description": "View all confirmed bookings for the authenticated traveller.",
      "auth_required": true,
      "entry_point": "https://www.gotouri.com/bookings",
      "url_pattern": "https://www.gotouri.com/bookings/{booking_id}"
    }
  ],
  "flows": [
    {
      "id": "negotiate_and_book",
      "name": "Browse → Offer → Negotiate → Checkout",
      "steps": [
        {
          "step": 1,
          "capability": "browse_experiences",
          "description": "Find an experience at a hub's explore page, e.g. /cdmx/explore or /puebla/explore — see browse_experiences.hubs for the full list"
        },
        {
          "step": 2,
          "capability": "view_experience",
          "description": "View the experience detail page and read JSON-LD for run IDs, pricing, and floor prices"
        },
        {
          "step": 3,
          "capability": "make_offer",
          "description": "Submit an offer above the floor price at /new?run={run_id}&ref=make_offer"
        },
        {
          "step": 4,
          "capability": "view_negotiation_thread",
          "description": "Poll /thread/{thread_id} for state changes. States: pending → countered or accepted or declined"
        },
        {
          "step": 5,
          "description": "If countered, optionally submit a counter-offer from the thread page. If accepted, proceed to checkout (payment handled in-platform)."
        }
      ]
    },
    {
      "id": "buy_now_flow",
      "name": "Browse → Buy Now → Checkout",
      "steps": [
        {
          "step": 1,
          "capability": "browse_experiences",
          "description": "Find an experience at a hub's explore page, e.g. /cdmx/explore or /puebla/explore — see browse_experiences.hubs for the full list"
        },
        {
          "step": 2,
          "capability": "view_experience",
          "description": "View experience detail and confirm availability and list price from JSON-LD"
        },
        {
          "step": 3,
          "capability": "buy_now",
          "description": "Book immediately at /new?run={run_id}&buyNow=true"
        },
        {
          "step": 4,
          "description": "Checkout and payment handled in-platform. Booking confirmed at /bookings/{booking_id}"
        }
      ]
    }
  ],
  "pricing_model": {
    "type": "negotiable",
    "description": "Each experience has a list price and a floor price. Travellers can book at list price or submit an offer anywhere above the floor. The guide accepts, counters, or declines. Final price is agreed between traveller and guide.",
    "per": "person",
    "total": "price_per_person x group_size",
    "floor_price_exposed": "yes — available per run in JSON-LD structured data on each experience page"
  },
  "geography": {
    "cities": [
      "Mexico City (CDMX)",
      "Puebla"
    ],
    "languages": [
      "en",
      "es"
    ],
    "language_url_prefix": "Locale is inferred automatically. Explicit prefix optional: /en/ or /es/"
  }
}