May 24, 2026 · 7 min read

Tourism circuits are a first-class data type, not a string

Every travel API I've audited treats "Buddhist Circuit" as a tag. A free-form string attached to a row, maybe normalized into a slug. That shape is wrong, and it's why your itinerary endpoint keeps inventing routes.

What a circuit actually is

A tourism circuit is not a label. It's a sequenced membership: an ordered list of stops, each pinned to a real city with coordinates, sometimes with notes about why a stop matters or how long pilgrims typically spend there. The Buddhist Circuit is not "places relevant to Buddhism in India." It's a specific path: Bodh Gaya, then Rajgir, then Nalanda, then Vaishali, then Kushinagar, then Sarnath, with Lumbini across the Nepal border for the full classical sequence. Reorder the stops and you've described a different trip.

Once you accept that, "circuit" stops being a tag column and starts being a relationship. A circuit has many stops; a stop belongs to one or more circuits with a sequence number; both have geometry.

The public response shape

We expose this through /v1/circuits/{slug}. The response looks like this:

GET /v1/circuits/buddhist-circuit
Authorization: Bearer tmai_live_...

{
  "slug": "buddhist-circuit",
  "name": "Buddhist Circuit",
  "narrative": "The classical pilgrimage route...",
  "stop_count": 7,
  "stops": [
    {
      "sequence_no": 1,
      "city": "Bodh Gaya",
      "state": "Bihar",
      "lat": 24.6975, "lon": 84.9913,
      "notes": "Site of the Bodhi tree and Mahabodhi Temple."
    },
    {
      "sequence_no": 2,
      "city": "Rajgir",
      "state": "Bihar",
      "lat": 25.0260, "lon": 85.4197,
      "notes": "Vulture Peak; first Buddhist council."
    }
    /* ... */
  ]
}

Three things matter about this shape. First, sequence_no is explicit — not implied by array index, not derived from coordinates. Second, every stop is a real city we already cover elsewhere in the API, so you can join. Third, the narrative is a paragraph of context an LLM can use as grounding without inventing.

What this unlocks

The shape is the product. Itinerary generation becomes a real query instead of a creative-writing prompt: "give me a 5-day route along the Buddhist Circuit starting in Patna" can be answered by ordering stops, computing inter-stop distances, and binning by day. Route optimization becomes the standard TSP-on-a-subgraph problem, not a hallucination risk.

Proximity queries also become free. "Which circuits pass within 50km of Varanasi?" is a spatial join over stops. With circuits as strings, that question doesn't have an answer.

The fifteen circuits we cover

India's Ministry of Tourism designates a number of thematic circuits under its Swadesh Darshan program. We cover fifteen, including the well-known religious routes and the less-marketed thematic ones:

Each is sequenced. Each stop joins to a city we cover with admin attribution and geo. None of this is a tag.

Why this is the right shape

The case for circuits-as-tags is one of convenience. You can attach a string to a row in five minutes. The case for circuits-as-sequences is that everything downstream — itinerary generation, routing, grounding for chatbots, day-trip recommendations — works only if the sequence exists. If it doesn't exist in your data, your chatbot will invent it. And it will invent it badly, because circuits are exactly the kind of structure LLMs pattern-match into existence.

The shape isn't novel. Graph-shaped tourism data has been a research topic for fifteen years. What's missing is somebody shipping it as a boring B2B API with prices on the page. That's what we did.

Sign up — free See India coverage →