travel.book_bus — Full Intent Specification
INTENT NAMESPACE: travel
INTENT NAME: book_bus
FULL ID: travel.book_bus
VERSION: v1.0.0
STATUS: draft
TTBS WEIGHTS: time 0.30 · taste 0.20 · budget 0.30 · safety 0.20
LAST UPDATED: 2026-05-14
Inter-city and intra-state bus booking via aggregators or operator-direct channels. Covers government-run state transport corporations (APSRTC, TSRTC, KSRTC, MSRTC, etc.) and private operators (Volvo Multi-Axle, Mercedes Multi-Axle, Sleeper Coach, Seater AC, Seater Non-AC). Distinct from travel.book_train (railway-issued tickets), mobility.book_intercity_ride (private cab city-to-city), and mobility.book_recurring_commute (subscription pooling). Partner exemplars: RedBus, Abhibus, Paytm Bus, Ixigo Bus, MakeMyTrip Bus, state RTC direct booking portals.
1. NATURAL LANGUAGE COVERAGE
Classifies IN
- "bus to Bangalore tomorrow night"
- "Volvo Hyderabad to Vijayawada"
- "sleeper bus to Mumbai"
- "AC Seater Pune Bangalore"
- "RedBus to Tirupati"
- "APSRTC bus to Vizag"
- "lower berth sleeper Coimbatore Bangalore"
- "ladies seat bus Chennai"
- "boarding point Madhapur"
- "Mercedes multi axle Hyderabad Bangalore"
Classifies OUT — borderline NO
- "train to Mumbai" →
travel.book_train - "flight to Goa" →
travel.book_flight - "intercity cab to Vizag" →
mobility.book_intercity_ride - "intracity bus / city bus" — not a v1 TOMO intent
- "carpool to office" →
mobility.book_recurring_commute - "bus pass / monthly pass" — out of scope v1
MULTI-INTENT TRIGGERS
- "Bangalore weekend — bus + hotel + scooter rental" →
travel.book_bus+travel.book_hotel+mobility.book_two_wheeler_rental - "Bus + cab to boarding point" →
travel.book_bus+mobility.book_intracity_ride - "Bus + bus to next city" → multi-leg single intent (handled inside this spec)
2. INPUT — TOMO → PROVIDER
{
"intent": "travel.book_bus",
"intent_version": "v1.0.0",
"request_id": "req_bus_2h4k_2026-05-14T10:00:00+05:30",
"user_session_id": "anon_user_token_or_uid",
"origin": {
"city": "Hyderabad",
"state": "Telangana",
"country_code": "IN",
"preferred_boarding_points": ["Madhapur", "Ameerpet", "MGBS"]
},
"destination": {
"city": "Bangalore",
"state": "Karnataka",
"country_code": "IN",
"preferred_dropping_points": ["Marathahalli", "Silk Board", "Majestic"]
},
"journey_date": "2026-05-20",
"departure_window": "night",
"flexible_days_window": 0,
"return_date_for_round_trip": null,
"party": {
"passenger_count": 2,
"adult_count": 2,
"children_with_age": [],
"infants_under_2": 0,
"senior_count": 0,
"ladies_count": 0
},
"preferences": {
"bus_kind_acceptable": ["volvo_multi_axle_sleeper", "mercedes_multi_axle_sleeper", "ac_sleeper"],
"seat_kind_acceptable": ["sleeper_lower", "sleeper_side_lower"],
"operator_kind_acceptable": ["private", "rtc"],
"max_journey_hours": 12,
"budget_band": "good",
"budget_max_inr_per_passenger": 1500,
"budget_max_inr_total": 3000,
"ladies_only_section_required": false,
"single_lady_traveling_alone": false,
"wheelchair_accessible_required": false,
"luggage_kg_per_passenger": 15,
"live_tracking_required": true,
"boarding_buffer_minutes_min": 30
},
"context": {
"user_locale": "en-IN",
"user_currency_pref": "INR",
"trip_purpose": "leisure",
"trust_signals": {
"is_repeat_customer": true,
"prior_bus_with_partner": 6,
"user_account_age_days": 312
}
}
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, equals "travel.book_bus" |
|
origin.city, destination.city |
string | REQUIRED | Validated against partner's city dictionary |
origin.preferred_boarding_points |
array |
REQUIRED, may be empty | Empty = any |
destination.preferred_dropping_points |
array |
REQUIRED, may be empty | Empty = any |
journey_date |
ISO_DATE | REQUIRED | Up to 60 days advance |
departure_window |
enum | REQUIRED, STRICT §6 | morning / afternoon / evening / night / any |
flexible_days_window |
int | REQUIRED, 0-3 | 0 = strict date |
return_date_for_round_trip |
ISO_DATE or null | REQUIRED | non-null triggers round-trip discount lookup |
party.passenger_count |
int | REQUIRED, 1-10 | |
party.children_with_age |
array |
REQUIRED, may be empty | each age 3-11 |
party.infants_under_2 |
int | REQUIRED | infants travel on adult lap, no separate seat |
party.ladies_count |
int | REQUIRED | drives ladies-quota / ladies-section eligibility |
preferences.bus_kind_acceptable |
array |
REQUIRED, ≥1, §6 | |
preferences.seat_kind_acceptable |
array |
REQUIRED, ≥1, §6 | |
preferences.operator_kind_acceptable |
array |
REQUIRED, ≥1, §6 | private / rtc |
preferences.ladies_only_section_required |
bool | REQUIRED | hard filter |
preferences.single_lady_traveling_alone |
bool | REQUIRED | drives safety reranking |
preferences.wheelchair_accessible_required |
bool | REQUIRED | hard filter |
preferences.live_tracking_required |
bool | REQUIRED | hard filter on operators with GPS feed |
preferences.boarding_buffer_minutes_min |
int | REQUIRED, ≥0 | walk-time from city centre to boarding point |
Anti-fabrication preamble: no paid placement, no commission-based operator ordering, TOMO never holds the rail — money flows user → operator (direct or via aggregator's pass-through merchant account).
3. PROVIDER TOOLS
Tool 1: search_buses
PURPOSE: return buses running origin → destination on journey_date matching filters
INPUT: §2 request body
OUTPUT: { buses: BusOption[], result_token, expires_at }
SLA: p50 < 1200ms, p95 < 3000ms, p99 < 5000ms
RATE LIMIT: ≤ 1/sec per (user_session_id, partner)
RESULT SET: up to 40 buses (typical route has 8-25)
Tool 2: get_seat_layout
PURPOSE: live seat availability matrix for one bus
INPUT: { bus_id, journey_date, boarding_point, dropping_point, request_id }
OUTPUT: SeatLayoutMatrix (§5)
SLA: p95 < 1200ms
RATE LIMIT: ≤ 2/sec per bus+date
Tool 3: hold_seats
PURPOSE: lock chosen seats for 10 minutes
INPUT: { bus_id, journey_date, seat_ids[], boarding_point, dropping_point, request_id }
OUTPUT: { hold_id, hold_expires_at, fare_breakdown }
SLA: p95 < 1500ms
RATE LIMIT: ≤ 1/sec per user
Tool 4: confirm_booking
PURPOSE: convert hold → confirmed booking + ticket PDF + e-receipt
INPUT: { hold_id, party, contact, payment_method_id, request_id }
OUTPUT: ConfirmedTicket (§5)
SLA: p95 < 4000ms
RATE LIMIT: ≤ 1/sec
IDEMPOTENCY: request_id
Tool 5: cancel_booking
PURPOSE: cancel ticket, compute refund per published policy
INPUT: { booking_id, reason_code, request_id }
OUTPUT: CancellationResult (§5)
SLA: p95 < 3000ms
4. RESPONSE SHAPE
BusOption
BusOption:
bus_id: { type: string, constraint: REQUIRED, opaque }
operator:
operator_id: { type: string, constraint: REQUIRED }
name: { type: string, constraint: REQUIRED, semantics: "e.g. 'VRL Travels', 'KSRTC' " }
kind: { type: enum, constraint: REQUIRED, STRICT §6, values: [private, rtc] }
permit_number: { type: string, constraint: REQUIRED, semantics: "RTO permit; verifiable on parivahan.gov.in" }
safety_certifications: { type: array<enum>, constraint: REQUIRED, STRICT §6, may be empty }
fleet_avg_age_years: { type: float, constraint: REQUIRED, ≥0 }
bus_kind: { type: enum, constraint: REQUIRED, STRICT §6 }
seats_total: { type: int, constraint: REQUIRED }
seats_available: { type: int, constraint: REQUIRED, semantics: "Live count for journey_date+boarding_point" }
origin_boarding_point:
point_name: { type: string, constraint: REQUIRED }
address: { type: string, constraint: REQUIRED }
lat: { type: float, constraint: REQUIRED }
lng: { type: float, constraint: REQUIRED }
landmark: { type: string, constraint: REQUIRED, semantics: "Plain-language landmark" }
boarding_time: { type: string, constraint: REQUIRED, ISO_DATETIME }
destination_dropping_point:
point_name: { type: string, constraint: REQUIRED }
address: { type: string, constraint: REQUIRED }
lat: { type: float, constraint: REQUIRED }
lng: { type: float, constraint: REQUIRED }
landmark: { type: string, constraint: REQUIRED }
dropping_time: { type: string, constraint: REQUIRED, ISO_DATETIME }
estimated_duration_minutes: { type: int, constraint: REQUIRED }
fare_breakdown:
base_fare_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
operator_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
aggregator_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "5% on AC, 0% on non-AC contract carriages" }
total_per_seat_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
total_for_party_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
amenities: { type: array<enum>, constraint: REQUIRED, STRICT §6, may be empty }
amenities_verified_within_days: { type: int, constraint: REQUIRED, semantics: "Days since amenity audit" }
safety:
live_tracking_available: { type: boolean, constraint: REQUIRED }
sos_button_in_bus: { type: boolean, constraint: REQUIRED }
cctv_in_bus: { type: boolean, constraint: REQUIRED }
female_attendant_onboard: { type: boolean, constraint: REQUIRED }
rest_stops_planned: { type: int, constraint: REQUIRED, ≥0 }
ladies_only_seats_available: { type: int, constraint: REQUIRED, ≥0 }
ladies_section_present: { type: boolean, constraint: REQUIRED }
cancellation_policy:
type: array<object>
constraint: REQUIRED, may NOT be empty
shape:
window_hours_before_departure_min: { type: int, constraint: REQUIRED, ≥0 }
window_hours_before_departure_max: { type: int, constraint: REQUIRED, ≥0 }
refund_pct: { type: int, constraint: REQUIRED, 0-100 }
rating:
operator_score: { type: float, constraint: REQUIRED, 0.0-5.0 }
on_time_pct: { type: float, constraint: REQUIRED, 0-100, semantics: "Past 90 days arrival within 30min of ETA" }
review_count: { type: int, constraint: REQUIRED, ≥0 }
partner_reference:
source: { type: string, constraint: REQUIRED }
deeplink: { type: string, constraint: REQUIRED, HTTPS URL }
SeatLayoutMatrix
SeatLayoutMatrix:
bus_id: { type: string, constraint: REQUIRED }
rows: { type: int, constraint: REQUIRED }
columns_layout: { type: string, constraint: REQUIRED, semantics: "e.g. '2+1' for sleeper, '2+2' for seater" }
decks: { type: enum, constraint: REQUIRED, STRICT §6, values: [single, double] }
seats:
type: array<object>
constraint: REQUIRED, may NOT be empty
shape:
seat_id: { type: string, constraint: REQUIRED }
seat_label: { type: string, constraint: REQUIRED, semantics: "e.g. 'L1', 'U5'" }
seat_kind: { type: enum, constraint: REQUIRED, STRICT §6 }
deck: { type: enum, constraint: REQUIRED, STRICT §6 }
position: { type: enum, constraint: REQUIRED, STRICT §6, values: [window, aisle, single, lower, upper, side_lower, side_upper] }
ladies_only: { type: boolean, constraint: REQUIRED }
available: { type: boolean, constraint: REQUIRED }
blocked_reason: { type: enum, constraint: REQUIRED, STRICT §6, values: [none, sold, on_hold, ladies_only_filter, maintenance] }
fare_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
ConfirmedTicket
ConfirmedTicket:
booking_id: { type: string, constraint: REQUIRED, immutable }
operator_pnr: { type: string, constraint: REQUIRED, semantics: "Operator's PNR; usable at boarding without TOMO" }
bus_id: { type: string, constraint: REQUIRED }
journey_date: { type: string, constraint: REQUIRED, ISO_DATE }
boarding_point: { type: object, constraint: REQUIRED, semantics: "Same shape as origin_boarding_point" }
dropping_point: { type: object, constraint: REQUIRED, semantics: "Same shape as destination_dropping_point" }
passengers:
type: array<object>
constraint: REQUIRED, may NOT be empty
shape:
passenger_name: { type: string, constraint: REQUIRED }
age: { type: int, constraint: REQUIRED }
gender: { type: enum, constraint: REQUIRED, STRICT §6 }
seat_id: { type: string, constraint: REQUIRED }
seat_label: { type: string, constraint: REQUIRED }
fare_paid_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
ticket_pdf_url: { type: string, constraint: REQUIRED, HTTPS URL }
e_receipt_url: { type: string, constraint: REQUIRED, HTTPS URL }
live_tracking_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "Empty when live tracking unsupported" }
driver_phone_at_t_minus_2h: { type: string, constraint: REQUIRED, E.164, semantics: "Empty until 2h before departure" }
cancellation_window:
full_refund_until: { type: string, constraint: REQUIRED, ISO_DATETIME }
last_cancellable_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
CancellationResult
CancellationResult:
booking_id: { type: string, constraint: REQUIRED }
cancelled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
refund_amount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
refund_method: { type: enum, constraint: REQUIRED, STRICT §6, values: [original_payment, partner_wallet] }
refund_eta_days: { type: int, constraint: REQUIRED, 0-10 }
cancellation_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
FORBIDDEN FIELDS
paid_placement_score,ad_bid,sponsored_rank,featured_operator,promotion_priorityeditor_pick,tomo_recommended,top_choiceurgency_text("Only 2 seats left!") unlessseats_available ≤ 3fake_review_block,inflated_rating,rounded_on_time_pctai_generated_bus_photo— real images required; expired imagery flaggedcommission_padded_fare,partner_revenue_shareunpublished_amenity("WiFi" without actual WiFi capability)expired_permit_number— Parivahan-verifiable permits only
5. CONTROLLED VOCABULARIES
preferences.bus_kind_acceptable / BusOption.bus_kind:
values:
volvo_multi_axle_sleeper: "Volvo multi-axle, sleeper berths"
mercedes_multi_axle_sleeper: "Mercedes-Benz multi-axle, sleeper berths"
ac_sleeper: "AC sleeper, generic"
non_ac_sleeper: "Non-AC sleeper"
ac_seater: "AC seater"
non_ac_seater: "Non-AC seater"
semi_sleeper_ac: "Semi-sleeper recliner AC"
semi_sleeper_non_ac: "Semi-sleeper recliner non-AC"
double_decker_sleeper: "Double-decker with sleeper upper deck"
luxury_sleeper: "Premium luxury sleeper (e.g. flatbed)"
preferences.seat_kind_acceptable / seat_kind:
values: [seater, sleeper_lower, sleeper_upper, sleeper_side_lower, sleeper_side_upper, semi_sleeper_lower, semi_sleeper_upper]
preferences.operator_kind_acceptable / operator.kind:
values:
private: "Private operator"
rtc: "State Road Transport Corporation"
departure_window:
values: [morning, afternoon, evening, night, any]
party gender (per passenger):
values: [male, female, other]
deck:
values: [single, double]
amenities:
values:
charging_socket, wifi, water_bottle, blanket, pillow, reading_light,
snacks, meals, recliner, footrest, usb_charger, entertainment_screen,
air_purifier, female_attendant, toilet_onboard, hand_sanitizer
operator.safety_certifications:
values: [iso_9001, iso_14001, isso_safety_audit, rto_permit_current, parivahan_verified, sebi_listed_operator]
CancellationResult.refund_method:
values: [original_payment, partner_wallet]
6. TTBS DIMENSIONS
TIME (weight = 0.30):
signals_used:
- boarding_time vs departure_window
- estimated_duration_minutes vs max_journey_hours
- on_time_pct
- boarding_point distance to user_location vs boarding_buffer_minutes_min
weighting:
departure_window_fit: 0.30
duration: 0.30
on_time: 0.25
boarding_proximity: 0.15
user_band_handling:
fast: prefer shortest duration even at +15% fare
balanced: standard
flexible: longer routes acceptable for cheaper fare
TASTE (weight = 0.20):
signals_used:
- bus_kind matches preferences (Volvo > Mercedes > AC > non-AC by user-stated preference)
- seat_kind preference fit
- amenities count match
- DNA repeat operator
weighting:
bus_kind_match: 0.35
seat_match: 0.25
amenities: 0.20
dna_repeat: 0.20
BUDGET (weight = 0.30):
signals_used:
- fare_breakdown.total_per_seat_inr
- fare_breakdown.total_for_party_inr
weighting:
per_seat: 0.50
total: 0.50
user_band_handling:
ok: cheapest passing safety floor (rating ≥3.5, on-time ≥75%)
good: balanced
great: premium luxury_sleeper or multi_axle_volvo
SAFETY (weight = 0.20):
signals_used:
- operator.permit_number verified live
- operator.fleet_avg_age_years (lower preferred)
- safety.live_tracking_available (HARD filter when requested)
- safety.sos_button_in_bus
- safety.cctv_in_bus
- safety.female_attendant_onboard (boost when single_lady_traveling_alone=true)
- ladies_section_present (HARD when ladies_only_section_required=true)
- rating.operator_score
- rating.on_time_pct floor (75%)
weighting:
permit_verified: 0.20
fleet_age: 0.15
live_tracking: 0.15
sos_cctv: 0.15
female_attendant: 0.10
rating_floor: 0.25
user_band_handling:
fast: relax operator_score floor to 3.5
balanced: floor 4.0
great: floor 4.3 + live tracking + SOS
Locked weights: time 0.30 / taste 0.20 / budget 0.30 / safety 0.20. Bus is a time-budget-driven domain; safety floors are HARD (permit verification, live tracking when requested) rather than dominant weight.
7. COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
"intent": "travel.book_bus",
"external_id": "<booking_id>",
"request_id": "<request_id>",
"amount_inr": 150, // NET partner commission only (typically 8-12% of fare)
"gst_inr": 27,
"tips_inr": 0,
"pass_through_inr": 1800, // fare remitted to operator
"closed_at": "2026-05-20T22:30:00+05:30",
"status": "completed",
"operator_id": "vrl_travels",
"bus_kind": "volvo_multi_axle_sleeper",
"journey_date": "2026-05-20",
"seats_booked": 2
}
User pays full fare (e.g. ₹1,950); operator gets ₹1,800; partner's commission (~₹150) is amount_inr. TOMO charges 10% × ₹150 = ₹15. HMAC-SHA256, 5-min replay window.
Cancellation completions file with status: cancelled and amount_inr adjusted to net partner-retained-commission after refund.
8. WIDGET
BusListingWidget (planned). Interim: ListingsWidget.
Field mapping:
- operator.name + bus_kind → header
- boarding_time → big departure time
- dropping_time + estimated_duration_minutes → "→ 6h 30m"
- fare_breakdown.total_per_seat_inr → price
- seats_available → "X seats left"
- amenities (top 3) → chip row
- rating.operator_score + on_time_pct → "4.3★ · 92% on-time"
- safety.live_tracking_available → "Live tracking" badge
- safety.female_attendant_onboard → "Female attendant" badge (boost when single_lady_traveling_alone)
- ladies_section_present → "Ladies section" badge (when ladies_only_section_required)
9. CACHING POLICY
| Call | TTL | Rationale |
|---|---|---|
| search_buses | 90s | Seat availability moves quickly |
| get_seat_layout | 30s | Live seat map |
| hold_seats | NO CACHE | Stateful lock |
| confirm_booking | NO CACHE | Idempotent by request_id |
| cancel_booking | NO CACHE | — |
| Operator static (permit, fleet, ratings) | 24h | |
| Boarding/dropping point geocodes | 7d |
10. ERROR CODES
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
INVALID_REQUEST |
400 | Malformed | No |
RATE_LIMITED |
429 | Throttle | 1, 2s |
INTERNAL_ERROR |
500 | Partner failure | 2, exp |
SIGNATURE_INVALID |
401 | HMAC fail | No |
NO_BUSES_FOUND |
200 (empty) | No bus on route+date | n/a |
SEAT_TAKEN |
409 | Hold race-lost | UI re-queries layout |
HOLD_EXPIRED |
410 | Hold window elapsed | UI re-holds |
PERMIT_INVALID |
422 | Operator permit lapsed | No (operator suspended) |
BOARDING_POINT_INVALID |
422 | Boarding point not served on this date | No |
PAYMENT_FAILED |
402 | Gateway declined | No |
LADIES_FILTER_NO_SEATS |
422 | ladies_only_section_required + no female-eligible seats | No |
WHEELCHAIR_NO_ROUTE |
422 | No wheelchair-accessible bus on route | No |
CANCELLED_TOO_LATE |
410 | Past last_cancellable_at | No |
OPERATOR_DOWN |
503 | Operator API unavailable | 1 retry, 2s |
ROUTE_CANCELLED_BY_OPERATOR |
410 | Operator cancelled bus | No (auto-refund flow) |
11. SANDBOX → PRODUCTION CHECKLIST
[ ] All five tools implemented
[ ] At least 50 routes in catalog covering 10+ cities
[ ] At least 30 operators (mix of private + RTC)
[ ] Every permit_number Parivahan-verifiable; daily re-check
[ ] amenities_verified_within_days ≤ 60 on all listings
[ ] live_tracking_url returns real GPS feed (sample tested on 5 buses)
[ ] CCTV / SOS / female_attendant flags audited via partner sample
[ ] on_time_pct computed from past 90 days of completed journeys
[ ] Cancellation policy publishes BEFORE payment, tested end-to-end
[ ] HMAC signing verified on test CPC webhook
[ ] amount_inr in CPC is COMMISSION (NET); pass_through_inr is fare to operator
[ ] All controlled vocabularies respected
[ ] No forbidden fields anywhere
[ ] SLA p95 met (100-call sandbox run)
[ ] GSTIN, MSO / aggregator license number, privacy policy URL uploaded
[ ] Customer support: 24×7 bus helpline + escalation email
[ ] Refund processed within stated refund_eta_days on test cancellations
[ ] Ladies-only / female-attendant logic tested with single_lady_traveling_alone flag
12. ANTI-FABRICATION RULES
RULE 1: operator.permit_number must be verifiable on parivahan.gov.in;
TOMO re-checks daily. Expired or fake permits = immediate suspension.
RULE 2: live_tracking_url must serve real GPS feed when live_tracking_available=true.
Fake polylines / static maps = customer-harm + suspension.
RULE 3: No paid_placement, ad_bid, sponsored_rank, featured_operator.
Bus ordering depends on TTBS only.
RULE 4: amenities listed must be physically present on the bus on the
journey date. "WiFi" listed without actual WiFi = customer-harm.
TOMO spot-audits 5% of new operators per quarter.
RULE 5: rating.operator_score must be unrounded over past 12 months of
completed journeys; review_count from completed journeys only.
RULE 6: on_time_pct computed from actual scheduled-vs-arrival comparison
in the past 90 days. Rounded up = ingest reject.
RULE 7: artificial_urgency_text "Only 2 left!" only when seats_available ≤ 3.
TOMO ingest validates seats_available against the same response;
mismatch = ingest reject.
RULE 8: ladies_only seat flagging must be operator-enforced at boarding
(operator app prompts attendant). Partner showing fake ladies
sections to bias ranking = suspension.
RULE 9: female_attendant_onboard must be verifiable from operator's
staffing roster. Partner can be asked to produce.
RULE 10: amount_inr in CPC is partner COMMISSION only. Fare remitted to
operator is pass_through_inr. Inflated commission base = suspension.
RULE 11: No AI-generated bus photos. Real recent photographs (within 12
months) required; sample audited at partner intake.
RULE 12: Cancellation policy published in §5 cancellation_policy must match
what partner enforces at cancel time. Mid-process policy changes
= customer-harm + suspension.
RULE 13: Driver phone in ConfirmedTicket must be the actual driver's number
from 2h before departure. Generic call-center numbers = ingest
reject.
RULE 14: Information-completeness score (hidden rank factor weight 0.10)
rewards full §4 shape. Sparse responses rank lower.
RULE 15: Operator-cancelled routes MUST trigger automatic refund within
24h, regardless of policy windows.
VERSION HISTORY
v1.0.0 — 2026-05-14 — Initial spec. Private + RTC operators, Parivahan-verified
permits, daily re-check. Live-tracking + SOS + CCTV +
female-attendant audited. Ladies-section / single-lady-
solo safety reranking. Net-commission base in §7.