mobility.book_outstation_package — Full Intent Specification
INTENT NAMESPACE: mobility
INTENT NAME: book_outstation_package
FULL ID: mobility.book_outstation_package
VERSION: v1.0.0
STATUS: draft
LAST UPDATED: 2026-05-10
TTBS WEIGHTS: time 0.20 · taste 0.20 · budget 0.30 · safety 0.30
Outstation packages are multi-day cab+driver bookings with itinerary-driven KM allowances, daily DA, night halts, and sightseeing flexibility. They differ from intercity (one A→B trip) and from self-drive (no driver) and from chauffeur-hourly (single city). Locked structural shape: (a) itinerary block with day-by-day plan; (b) package_kind enum with fixed allowances; (c) per-day KM cap with overage rate; (d) driver allowance + night halt accumulate per day; (e) longer trip exposure → safety weight 0.30, taste up because vehicle becomes the user's home for days.
1. NATURAL LANGUAGE COVERAGE
Classifies IN
- "Goa 4N5D package with cab"
- "outstation cab to Tirupati 2N3D"
- "Coorg package 3 nights with driver"
- "weekend Hampi cab and stay"
- "Munnar trip 2 nights with cab"
- "outstation Innova for 5 days Hyderabad to Bangalore via Mysore"
- "Tirupati Tirumala darshan package round trip"
- "5 day cab booking with sightseeing"
- "Pondicherry trip 4 nights cab"
Classifies OUT — borderline NO
- "Hyderabad to Bangalore one way" →
mobility.book_intercity_ride - "self-drive Goa 4 days" →
mobility.book_self_drive - "chauffeur for full day Bangalore" →
mobility.book_chauffeur_hourly - "weekend road trip self-drive" →
mobility.book_self_drive - "package tour with hotel" →
travel.book_package
MULTI-INTENT TRIGGERS
- "Goa 4N5D cab and book hotel near Calangute" →
mobility.book_outstation_package+travel.book_hotel - "Tirupati cab 2N3D and book darshan slot" →
mobility.book_outstation_package+travel.book_tour_guide - "outstation cab 5 days and FASTag top-up" →
mobility.book_outstation_package+pay.fastag_topup
2. INPUT — TOMO → PROVIDER
{
"intent": "mobility.book_outstation_package",
"intent_version": "v1.0.0",
"request_id": "req_outs_2k9p_2026-05-10T07:30:00Z",
"user_session_id": "anon_user_token_or_uid",
"package_kind": "round_trip_with_sightseeing",
"origin_city": {
"lat": 17.4435,
"lng": 78.3772,
"address": "HITEC City Main Road, Madhapur",
"city": "Hyderabad",
"state_code": "TS",
"country_code": "IN"
},
"primary_destination_city": {
"lat": 15.2993,
"lng": 74.1240,
"address": "Calangute Beach Road, Goa",
"city": "Goa",
"state_code": "GA",
"country_code": "IN"
},
"itinerary": [
{
"day_index": 1,
"date_iso": "2026-05-11",
"from_city": "Hyderabad",
"to_city": "Goa",
"expected_distance_km": 640,
"expected_drive_hours": 13,
"stops_planned": ["Hubli food break"],
"night_halt_city": "Goa",
"is_drive_day": true
},
{
"day_index": 2,
"date_iso": "2026-05-12",
"from_city": "Goa",
"to_city": "Goa",
"expected_distance_km": 80,
"expected_drive_hours": 4,
"stops_planned": ["Calangute", "Baga", "Anjuna"],
"night_halt_city": "Goa",
"is_drive_day": false
},
{
"day_index": 3,
"date_iso": "2026-05-13",
"from_city": "Goa",
"to_city": "Goa",
"expected_distance_km": 120,
"expected_drive_hours": 5,
"stops_planned": ["Old Goa Basilica", "Dudhsagar Falls"],
"night_halt_city": "Goa",
"is_drive_day": false
},
{
"day_index": 4,
"date_iso": "2026-05-14",
"from_city": "Goa",
"to_city": "Goa",
"expected_distance_km": 60,
"expected_drive_hours": 3,
"stops_planned": ["Palolem"],
"night_halt_city": "Goa",
"is_drive_day": false
},
{
"day_index": 5,
"date_iso": "2026-05-15",
"from_city": "Goa",
"to_city": "Hyderabad",
"expected_distance_km": 640,
"expected_drive_hours": 13,
"stops_planned": ["Hubli"],
"night_halt_city": "none",
"is_drive_day": true
}
],
"trip_duration_days": 5,
"trip_nights_count": 4,
"trip_starts_iso": "2026-05-11T05:00:00+05:30",
"trip_ends_iso": "2026-05-15T22:00:00+05:30",
"party": {
"passenger_count": 4,
"luggage_pieces": 8,
"luggage_size": "checkin",
"minor_count": 1,
"senior_count": 1
},
"preferences": {
"vehicle_kinds_acceptable": ["sedan_intercity", "suv_intercity", "tempo_traveller"],
"budget_band": "good",
"budget_max_inr": 45000,
"ac_required": true,
"female_driver_required": false,
"ev_only": false,
"wheelchair_accessible_required": false,
"child_seat_required": true,
"max_seat_capacity_min": 4,
"driver_must_speak_locales": ["en-IN", "te-IN", "hi-IN"],
"music_system_required": true,
"include_recliner_seats": true
},
"trip_intent_meta": {
"expected_total_distance_km": 1540,
"expected_states_crossed": ["TS", "KA", "GA"],
"involves_highway": true,
"involves_offroad": false,
"is_overnight_drives_count": 2,
"is_pilgrim_trip": false,
"purpose": "leisure_family"
},
"context": {
"user_locale": "en-IN",
"user_currency_pref": "INR",
"trust_signals": {
"is_repeat_customer": true,
"prior_outstation_with_partner": 1,
"user_account_age_days": 312,
"fastag_present": true,
"fastag_balance_inr": 1840
}
}
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, equals "mobility.book_outstation_package" |
|
package_kind |
enum | REQUIRED, see §5 | |
origin_city.state_code |
string | REQUIRED | |
primary_destination_city.state_code |
string | REQUIRED | |
itinerary |
array | REQUIRED, ≥1 | one entry per day |
itinerary[].day_index |
int | REQUIRED, ≥1, contiguous | |
itinerary[].date_iso |
ISO_DATE | REQUIRED | |
itinerary[].is_drive_day |
bool | REQUIRED | drives DA + night halt math |
itinerary[].night_halt_city |
string | REQUIRED, may be "none" |
|
itinerary[].expected_distance_km |
float | REQUIRED | |
trip_duration_days |
int | REQUIRED, ≥1 | |
trip_nights_count |
int | REQUIRED, ≥0 | |
trip_starts_iso |
ISO_DATETIME | REQUIRED | |
trip_ends_iso |
ISO_DATETIME | REQUIRED | must be > trip_starts |
party.minor_count |
int | REQUIRED, ≥0 | |
party.senior_count |
int | REQUIRED, ≥0 | |
preferences.driver_must_speak_locales |
array |
REQUIRED, ≥1 | |
preferences.music_system_required |
bool | REQUIRED | |
preferences.include_recliner_seats |
bool | REQUIRED | |
trip_intent_meta.is_pilgrim_trip |
bool | REQUIRED | drives behavior signals (no alcohol etc.) |
trip_intent_meta.is_overnight_drives_count |
int | REQUIRED, ≥0 |
Anti-fabrication preamble (universal): no paid placement, no urgency text, no commission-influenced fields.
3. PROVIDER TOOLS
Tool 1: get_outstation_package_estimates
PURPOSE: return package options across vehicle kinds for itinerary
INPUT: §2 request body
OUTPUT: { options: OutstationPackageOption[], result_token, expires_at }
SLA: p50 < 800ms, p95 < 2000ms
RATE LIMIT: ≤ 1/sec per user
Tool 2: book_outstation_package
PURPOSE: commit package
INPUT: { option_id, payment_token, request_id, idempotency_key, user_phone, otp_required }
OUTPUT: { booking_ref, status, driver, vehicle, fare_quote, allowance_breakdown, day_by_day_kit }
SLA: p95 < 6000ms
IDEMPOTENCY: REQUIRED on idempotency_key
Tool 3: track_outstation_package
PURPOSE: live state across the trip with day-by-day progress
INPUT: { booking_ref, request_id }
OUTPUT: OutstationPackageTrack (§4)
SLA: p95 < 500ms
RATE LIMIT: ≤ 1 every 30s
Tool 4: cancel_outstation_package
PURPOSE: cancel before trip starts OR mid-trip
INPUT: { booking_ref, reason, request_id }
OUTPUT: { status, cancellation_charge_inr, refund_amount_inr, cancellation_window_kind }
SLA: p95 < 2000ms
Tool 5: update_itinerary
PURPOSE: modify day plan (add stop, change night halt, etc.)
INPUT: { booking_ref, day_index, updated_day_plan, request_id }
OUTPUT: { revised_fare_inr, revised_distance_km, status }
SLA: p95 < 1500ms
Tool 6: mark_day_complete
PURPOSE: partner closes a day's leg
INPUT: { booking_ref, day_index, day_summary, request_id }
OUTPUT: { acknowledged: true, day_completion_iso, partial_fare_settled_inr }
SLA: p95 < 1500ms
Tool 7: rate_outstation_package
PURPOSE: post-trip rating
INPUT: { booking_ref, rating_5star, comment, tip_inr, request_id }
OUTPUT: { acknowledged: true }
SLA: p95 < 800ms
Tool 8: share_trip_status
PURPOSE: tokenized live tracking URL
INPUT: { booking_ref, recipient_phone_optional, request_id }
OUTPUT: { share_url, expires_at }
SLA: p95 < 500ms
All eight REQUIRED.
4. RESPONSE SHAPE
OutstationPackageOption (returned by get_outstation_package_estimates)
id: string, REQUIRED
option_token: string, REQUIRED
expires_at: ISO_DATETIME, REQUIRED
vehicle_kind: STRICT ENUM, REQUIRED
vehicle_class: STRICT ENUM, REQUIRED
display_label: string, REQUIRED
seat_capacity: int, REQUIRED, ≥1
luggage_capacity: STRICT ENUM, REQUIRED
availability:
trip_dispatch_iso: ISO_DATETIME, REQUIRED
driver_pre_dispatch_minutes: int, REQUIRED
alternate_pickup_options: array, REQUIRED, may be empty
fare:
total_inr: INR_INTEGER, REQUIRED
base_per_day_inr: INR_INTEGER, REQUIRED
base_per_km_inr: float, REQUIRED
total_billed_km: int, REQUIRED
included_km_total: int, REQUIRED
per_km_overage_inr: float, REQUIRED
driver_allowance_inr_per_day: INR_INTEGER, REQUIRED
driver_allowance_total_inr: INR_INTEGER, REQUIRED
night_halt_charge_inr_per_night: INR_INTEGER, REQUIRED
night_halt_charge_total_inr: INR_INTEGER, REQUIRED
night_halt_count: int, REQUIRED, ≥0
toll_inr: INR_INTEGER, REQUIRED
toll_count: int, REQUIRED, ≥0
state_border_charge_inr: INR_INTEGER, REQUIRED
state_border_count: int, REQUIRED, ≥0
highway_charge_inr: INR_INTEGER, REQUIRED
ac_charge_inr: INR_INTEGER, REQUIRED
parking_charge_inr: INR_INTEGER, REQUIRED
late_night_drive_inr: INR_INTEGER, REQUIRED
platform_fee_inr: INR_INTEGER, REQUIRED
gst_inr: INR_INTEGER, REQUIRED
rider_tip_optional_inr: INR_INTEGER, REQUIRED
fare_breakdown_text: string, REQUIRED
is_upfront_fare: boolean, REQUIRED
fare_locked_until_iso: ISO_DATETIME, REQUIRED
return_trip_empty_pricing: boolean, REQUIRED # for one_way packages
day_by_day_breakdown:
- day_index: int, REQUIRED
distance_km: float, REQUIRED
drive_hours: float, REQUIRED
is_drive_day: boolean, REQUIRED
night_halt_city: string, REQUIRED
daily_inr: INR_INTEGER, REQUIRED # day's portion of total
sightseeing_supported: boolean, REQUIRED
additional_stops_allowed: int, REQUIRED, ≥0
vehicle_amenities:
ac: boolean, REQUIRED
music_on_demand: boolean, REQUIRED
charging_port: boolean, REQUIRED
wifi_in_cab: boolean, REQUIRED
bottled_water: boolean, REQUIRED
newspaper: boolean, REQUIRED
pet_friendly: boolean, REQUIRED
child_seat_available: boolean, REQUIRED
child_seat_kind: STRICT ENUM, REQUIRED
wheelchair_accessible: boolean, REQUIRED
recliner_seats: boolean, REQUIRED
panoramic_roof: boolean, REQUIRED
fridge_in_cabin: boolean, REQUIRED
oxygen_supply_for_emergency: boolean, REQUIRED
vehicle_meta:
age_years: int, REQUIRED
fuel_kind: STRICT ENUM, REQUIRED
fuel_efficiency_kmpl: float, REQUIRED
ev_battery_charge_pct: int, REQUIRED, 0-100
ev_range_km_remaining: int, REQUIRED
emission_norm: STRICT ENUM, REQUIRED
registration_state_code: string, REQUIRED
vehicle_class_certification: STRICT ENUM, REQUIRED
comprehensive_insurance: boolean, REQUIRED
insurance_valid_until_iso: ISO_DATE, REQUIRED
fitness_certificate_valid_until_iso: ISO_DATE, REQUIRED
puc_valid_until_iso: ISO_DATE, REQUIRED
permit_kind: STRICT ENUM, REQUIRED
all_india_tourist_permit: boolean, REQUIRED
permit_states_covered: array<string>, REQUIRED, ≥1
commercial_aggregator_permit_number: string, REQUIRED
vehicle_color: string, REQUIRED
last_serviced_iso: ISO_DATE, REQUIRED
odometer_reading_km: int, REQUIRED, ≥0
driver_meta:
driver_id: string, REQUIRED
display_name: string, REQUIRED
photo_url: URL, REQUIRED
rating_avg: float, REQUIRED, 0-5
rides_completed_total: int, REQUIRED, ≥0
outstation_packages_completed: int, REQUIRED, ≥0
partner_account_age_days: int, REQUIRED, ≥0
languages_spoken: array<RFC_3066_LOCALE>, REQUIRED, ≥1
female_driver: boolean, REQUIRED
age_band: STRICT ENUM, REQUIRED
experience_years_driving: int, REQUIRED, ≥0
highway_experience_years: int, REQUIRED, ≥0
states_familiar_with: array<string>, REQUIRED, ≥1
defensive_driving_certified: boolean, REQUIRED
multi_day_trip_certified: boolean, REQUIRED # partner-internal multi-day rating
driver_kyc:
dl_verified: boolean, REQUIRED
dl_number_masked: string, REQUIRED
dl_valid_until_iso: ISO_DATE, REQUIRED
dl_class_includes_lmv: boolean, REQUIRED
rc_verified: boolean, REQUIRED
aadhaar_verified: boolean, REQUIRED
pan_verified: boolean, REQUIRED
background_check_passed: boolean, REQUIRED
background_check_iso: ISO_DATETIME, REQUIRED
badge_id_displayed: boolean, REQUIRED
fatigue_compliance_certified: boolean, REQUIRED
safety_features:
sos_button_in_app: boolean, REQUIRED
trip_share_supported: boolean, REQUIRED
in_app_chat_supported: boolean, REQUIRED
in_app_call_supported: boolean, REQUIRED
emergency_contact_alerts: boolean, REQUIRED
cctv_in_cab: boolean, REQUIRED
panic_alert_to_local_police: boolean, REQUIRED
driver_drowsiness_detection: boolean, REQUIRED
speed_limit_governing: boolean, REQUIRED
highway_assist_telematics: boolean, REQUIRED
spare_tyre_present: boolean, REQUIRED
first_aid_kit_present: boolean, REQUIRED
fire_extinguisher_present: boolean, REQUIRED
reflective_triangle_present: boolean, REQUIRED
multi_day_relief_driver_available: boolean, REQUIRED # if trip > 8h drive on any day
route_quality:
estimated_total_distance_km: float, REQUIRED
estimated_total_duration_min: int, REQUIRED
total_drive_days: int, REQUIRED
total_sightseeing_days: int, REQUIRED
highway_kms: float, REQUIRED
inner_road_kms: float, REQUIRED
states_crossed_count: int, REQUIRED, ≥1
primary_highway_codes: array<string>, REQUIRED, may be empty
toll_passes: array, REQUIRED, may be empty
cancellation:
free_cancel_until_iso: ISO_DATETIME, REQUIRED
cancel_charge_within_72h_inr: INR_INTEGER, REQUIRED
cancel_charge_within_24h_inr: INR_INTEGER, REQUIRED
cancel_charge_within_2h_inr: INR_INTEGER, REQUIRED
no_show_charge_inr: INR_INTEGER, REQUIRED
driver_cancel_compensation_inr: INR_INTEGER, REQUIRED
partial_completion_refund_policy: STRICT ENUM, REQUIRED # see §5
refund_processing_days: int, REQUIRED, ≥0
fastag_check:
toll_count_on_route: int, REQUIRED, ≥0
fastag_required: boolean, REQUIRED
estimated_toll_total_inr: INR_INTEGER, REQUIRED
user_fastag_balance_sufficient: boolean, REQUIRED
fastag_topup_recommended_inr: INR_INTEGER, REQUIRED
freshness:
data_last_synced_iso: ISO_DATETIME, REQUIRED
_provider:
name: string, REQUIRED
tomo_partner_id: string, REQUIRED
partner_tier: STRICT ENUM, REQUIRED
deep_link: URL, REQUIRED
customer_support_phone: string, REQUIRED
customer_support_24x7: boolean, REQUIRED
in_app_chat_supported: boolean, REQUIRED
partner_outstation_volume_30d: int, REQUIRED, ≥0
partner_outstation_complete_rate_30d: float, REQUIRED, 0-1
OutstationPackageTrack (returned by track_outstation_package)
booking_ref: string, REQUIRED
status: STRICT ENUM, REQUIRED
status_updated_iso: ISO_DATETIME, REQUIRED
status_history: array, REQUIRED, ≥1
trip_progress:
current_day_index: int, REQUIRED, ≥0
total_days: int, REQUIRED
days_completed: int, REQUIRED, ≥0
km_traveled_so_far: float, REQUIRED, ≥0
current_leg_distance_remaining_km: float, REQUIRED
next_night_halt_city: string, REQUIRED
itinerary_compliance: STRICT ENUM, REQUIRED # see §5
driver:
driver_id: string, REQUIRED
display_name: string, REQUIRED
phone_masked: string, REQUIRED
photo_url: URL, REQUIRED
rating_avg: float, REQUIRED, 0-5
in_app_chat_supported: boolean, REQUIRED
in_app_call_supported: boolean, REQUIRED
cumulative_drive_minutes_today: int, REQUIRED, ≥0
cumulative_drive_minutes_trip: int, REQUIRED, ≥0
vehicle:
vehicle_kind: STRICT ENUM, REQUIRED
display_label: string, REQUIRED
color: string, REQUIRED
plate_masked: string, REQUIRED
location:
current_lat: float, REQUIRED
current_lng: float, REQUIRED
current_state_code: string, REQUIRED
heading_degrees: float, REQUIRED, 0-360
speed_kmh: float, REQUIRED, ≥0
location_updated_iso: ISO_DATETIME, REQUIRED
status: STRICT ENUM, REQUIRED
eta:
to_next_stop_minutes: int, REQUIRED
to_next_night_halt_minutes: int, REQUIRED
revised_total_fare_inr: INR_INTEGER, REQUIRED
detour_minutes_today: int, REQUIRED
ride_safety:
on_route: boolean, REQUIRED
unusual_stop_detected: boolean, REQUIRED
unusual_speed_detected: boolean, REQUIRED
driver_fatigue_warning_active: boolean, REQUIRED
trip_share_active: boolean, REQUIRED
trip_share_url: URL, REQUIRED
fastag:
next_toll_distance_km: float, REQUIRED
next_toll_amount_inr: INR_INTEGER, REQUIRED
user_fastag_balance_sufficient_for_remaining_tolls: boolean, REQUIRED
cumulative_toll_paid_inr: INR_INTEGER, REQUIRED, ≥0
support_phone: string, REQUIRED
support_email: string, REQUIRED
Forbidden fields
paid_placement_score | sponsored_rank | promotion_priority |
artificial_demand_text | fake_recent_booking_text |
auto_inflate_outstation_volume_30d | partner_paid_for_top_listing |
fake_complete_rate_30d | hidden_da_charge_inr | undocumented_night_halt_charge
5. CONTROLLED VOCABULARIES
package_kind
round_trip_with_sightseeing | round_trip_no_sightseeing |
one_way_with_sightseeing | one_way_no_sightseeing |
pilgrim_circuit | adventure_circuit | beach_circuit |
hill_station_circuit | wildlife_circuit | custom_itinerary
vehicle_kind
sedan_intercity | suv_intercity | premium_sedan_intercity |
premium_suv_intercity | tempo_traveller | mini_bus |
ev_sedan_intercity | ev_suv_intercity | luxury_sedan_intercity |
luxury_suv_intercity
vehicle_class
economy | comfort | premium | luxury | xl | xl_premium
OutstationPackageOption.luggage_capacity
small | medium | large | xl | xxl
vehicle_meta.fuel_kind
petrol | diesel | cng | lpg | ev_full | hybrid | bs6_petrol | bs6_diesel
vehicle_meta.emission_norm
bs3 | bs4 | bs6 | ev | unknown_legacy
vehicle_meta.permit_kind
tourist | all_india_tourist | contract_carriage
Outstation REQUIRES tourist | all_india_tourist | contract_carriage. Aggregator-only permits NOT valid for multi-day cross-state.
vehicle_meta.vehicle_class_certification
commercial_yellow_plate | tourist | tempo_traveller | luxury_charter
vehicle_amenities.child_seat_kind
none | infant | toddler | booster | universal
driver_meta.age_band
21-30 | 31-40 | 41-55 | 56+
cancellation.partial_completion_refund_policy
pro_rata_remaining_days | flat_50pct_unused_days |
flat_70pct_unused_days | no_refund_after_day_one | full_refund_until_day_one
OutstationPackageTrack.status
booked | scheduled | driver_assigned | driver_dispatched |
trip_started_day_1 | day_in_progress | day_complete |
night_halt | trip_complete | cancelled_by_user |
cancelled_by_driver | partial_completion | failed |
itinerary_modified
OutstationPackageTrack.location.status
heading_to_pickup | at_pickup | trip_in_progress |
at_intermediate_stop | at_sightseeing_stop |
crossing_state_border | nearby_night_halt | at_night_halt |
at_drop
OutstationPackageTrack.trip_progress.itinerary_compliance
fully_compliant | minor_deviation_under_30km | major_deviation_over_30km |
day_skipped_with_consent | day_skipped_without_consent
cancel_outstation_package.reason
user_changed_mind | weather_cancellation | driver_unavailable |
vehicle_breakdown | safety_concern | medical_emergency |
no_longer_needed | found_alternative | itinerary_unworkable | other
context.trip_intent_meta.purpose
leisure_family | leisure_friends | leisure_solo | leisure_couple |
pilgrimage | wedding_event | business_trip | medical_trip |
school_trip | corporate_offsite | other
6. TTBS DIMENSIONS
Per-domain weights (locked; outstation override)
mobility (outstation_package): { time: 0.20, taste: 0.20, budget: 0.30, safety: 0.30 }
Time drops (multi-day, no minute-precision pressure). Taste up (vehicle becomes home). Safety strong (highway exposure × multi-day).
TIME
SIGNALS USED:
- availability.trip_dispatch_iso ≤ trip_starts_iso HARD FILTER
- driver_pre_dispatch_minutes (low=better) weight 0.10
- route_quality.estimated_total_duration_min weight 0.30
- cancellation.refund_processing_days weight 0.10
- day_by_day_breakdown sightseeing_supported on requested days HARD FILTER for tight itineraries
USER BAND HANDLING:
- "morning departure" preference shifts pickup_minutes weight
TASTE
SIGNALS USED:
- driver_meta.rating_avg weight 0.25
- vehicle.year_of_manufacture weight 0.10
- vehicle_amenities match w/ user prefs weight 0.25
- vehicle_amenities.recliner_seats (multi-day comfort) weight 0.10
- vehicle_amenities.fridge_in_cabin (luxury/great) weight 0.10
- driver languages match user_locale + states crossed weight 0.10
- driver_meta.multi_day_trip_certified weight 0.10
HARD FILTER:
- ac_required + ac=false → drop
- is_pilgrim_trip + driver doesn't speak local pilgrim_locale → drop
BUDGET
SIGNALS USED:
- fare.total_inr vs band:
ok → sedan_intercity / EV economy
good → suv_intercity / sedan_intercity_premium
great → luxury_sedan_intercity / luxury_suv_intercity / tempo_traveller_premium
- fare.is_upfront_fare=true weight 0.20
- fare.included_km_total vs expected_total_distance_km weight 0.20
- fare.return_trip_empty_pricing=false (better) weight 0.10
- fastag_topup_recommended_inr (lower) weight 0.10
HARD FILTERS:
- fare.total_inr > preferences.budget_max_inr → drop
- day_by_day_breakdown.daily_inr exceeds 1.5x average for any single day → flag (likely surge gaming)
USER BAND HANDLING:
- leisure_family deweights ok; pilgrim trip stays cost-conscious
SAFETY
SIGNALS USED:
- driver_kyc.background_check_passed HARD FILTER
- driver_kyc.dl_class_includes_lmv HARD FILTER
- driver_kyc.fatigue_compliance_certified HARD FILTER
- vehicle_meta.comprehensive_insurance HARD FILTER
- vehicle_meta.permit_kind in (tourist|all_india_tourist|contract_carriage) HARD FILTER
- vehicle_meta.permit_states_covered ⊇ states_crossed HARD FILTER
- safety_features.driver_drowsiness_detection weight 0.15
- safety_features.highway_assist_telematics weight 0.15
- safety_features.first_aid_kit_present weight 0.05
- safety_features.fire_extinguisher_present weight 0.05
- safety_features.multi_day_relief_driver_available
(if any drive_day > 8h) weight 0.20
- driver_meta.outstation_packages_completed (≥10) weight 0.10
- driver_meta.highway_experience_years (≥5) weight 0.10
- driver_meta.defensive_driving_certified weight 0.05
- driver_meta.multi_day_trip_certified weight 0.10
- driver_meta.female_driver
(boosted if female_driver_required) weight 0.10
- is_overnight_drives_count > 0 → safety scales 1.5x
HARD FILTERS:
- female_driver_required → drop male drivers
- states_crossed not covered by permit → drop
- any drive_day > 12h AND multi_day_relief_driver_available=false → drop
- is_pilgrim_trip AND alcohol_consumption_history detected (partner-tracked) → drop
Hidden ranking factor
information_completeness_score weight 0.10.
FASTag check
Surface FASTag balance vs estimated_toll_total_inr at option-card level. For multi-day trips, also surface day-by-day toll preview.
7. COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/{tomo_partner_id}
X-TOMO-Timestamp: <ms>
X-TOMO-Signature: sha256=<hex>
{
"intent": "mobility.book_outstation_package",
"intent_version": "v1.0.0",
"external_id": "OLA-OUTS-XYZ",
"amount_inr": 42500,
"closed_at": "2026-05-15T22:14:00+05:30",
"request_id": "req_outs_2k9p_...",
"status": "completed",
"booking_ref": "OLA-OUTS-XYZ",
"trip_started_at": "2026-05-11T05:08:00+05:30",
"trip_completed_at": "2026-05-15T22:00:00+05:30",
"days_completed": 5,
"total_distance_traveled_km": 1614,
"states_traversed": ["TS", "KA", "GA"],
"tolls_paid_inr": 2840,
"night_halts_paid": 4,
"driver_allowance_paid_inr": 2500,
"currency": "INR",
"fare_breakdown_total_inr": 42500,
"rider_tip_inr": 1500,
"ratings_pending": true,
"notes": ""
}
Status enum: completed | cancelled_by_user | cancelled_by_driver | failed | partial_completion_user_drop_early | extended_with_extra_charge | itinerary_changed_with_consent
8. WIDGET
WIDGET TYPE: outstation_package_options
SOURCE: src/widgets/types.ts
TYPE NAME: OutstationPackageOptionsPayload
RENDERED IN: components/widgets/OutstationPackageOptionsWidget.tsx
Default: 3 stacked rows showing vehicle_kind, total trip duration, fare with day-count + DA + night-halt badge, key amenities, FASTag adequacy. Tap row → confirmation card with day-by-day fare breakdown timeline → "Book". Then OutstationTrackingCard with day-by-day progress strip + current leg + state-crossing indicators.
9. CACHING POLICY
| Call | TTL | Rationale |
|---|---|---|
get_outstation_package_estimates |
300s | demand moves slowly for multi-day plans |
track_outstation_package |
0s | always live |
book_outstation_package |
0s | |
cancel_outstation_package |
0s | |
update_itinerary |
0s | |
mark_day_complete |
0s | |
| Failure responses | 0s |
10. ERROR CODES
| Code | HTTP | Meaning | TOMO behavior |
|---|---|---|---|
NO_DRIVERS_AVAILABLE |
503 | none with multi-day permit + capacity | retry or fall back |
OUT_OF_SERVICE_AREA |
400 | origin or destination outside coverage | surface |
STATE_NOT_COVERED_BY_PERMIT |
400 | permit doesn't cover required state | surface, suggest alternate |
OPTION_EXPIRED |
410 | option_token invalid | re-quote |
PAYMENT_DECLINED |
402 | gateway rejection | surface |
BOOKING_NOT_FOUND |
404 | booking_ref doesn't exist | surface |
ALREADY_CANCELLED |
409 | duplicate cancel | idempotent return |
DRIVER_FATIGUE_LIMIT_REACHED |
503 | MV Act drive-hours exceeded | partner reassigns or relief driver |
WEATHER_BLOCK |
503 | route flagged unsafe | suggest reschedule |
FASTAG_INSUFFICIENT |
400 | route requires FASTag, balance low | top-up CTA |
ITINERARY_INFEASIBLE |
400 | day plan exceeds drive-hours cap | surface alternate |
DAY_INDEX_OUT_OF_RANGE |
400 | update_itinerary invalid day_index | surface |
11. SANDBOX → PRODUCTION CHECKLIST
[ ] All §2 inputs validated, request_id echoed
[ ] get_outstation_package_estimates returns ≥3 options for "Hyderabad → Goa 4N5D"
[ ] All §4 required fields populated with REAL data
[ ] driver_kyc + vehicle_meta truthful + verifiable
[ ] permit_states_covered ⊇ states_crossed validated
[ ] all_india_tourist_permit OR equivalent verified for multi-state
[ ] fitness_certificate + insurance + PUC + permit valid through trip_ends_iso
[ ] book_outstation_package returns booking_ref + driver assignment within SLA
[ ] track_outstation_package returns location ≤30s old + day progress accurate
[ ] cancel respects free_cancel_until_iso absolute window
[ ] update_itinerary handles ≥2 day changes with correct fare recalc
[ ] mark_day_complete fires on every completed day with summary
[ ] CPC webhook arrives within 60s of trip completion
[ ] HMAC verification passes
[ ] No forbidden fields anywhere
[ ] Trip share URL works for ≥7 days post-completion
[ ] SOS button tested with TOMO ops monitoring
[ ] Fatigue compliance check tested on 14h+ day simulation
[ ] multi_day_relief_driver_available tested on >8h drive day
[ ] partner_outstation_complete_rate_30d audited against TOMO sample
[ ] No paid placement / sponsored signals
[ ] customer_support_24x7 verified by TOMO field call
[ ] Tourist + aggregator permit certificates uploaded for every state
12. ANTI-FABRICATION RULES
RULE 1 — No paid placement signals.
RULE 2 — No fake driver ratings.
RULE 3 — No fake outstation_packages_completed inflation.
TOMO compares stated count against partner's CPC ledger; mismatch >5% = breach.
RULE 4 — No fake complete_rate_30d.
Rate must come from partner's CPC ledger of completed multi-day trips.
TOMO samples 1% trips and validates against day-by-day completion records.
RULE 5 — Fare displayed must be honored.
is_upfront_fare=true means fare_locked_until_iso. Per-km overage is the ONLY
legitimate post-trip increase (and must be audit-trail-linked to actual
km_traveled_so_far in track payload).
RULE 6 — Day-by-day fare must add to total.
Sum of day_by_day_breakdown.daily_inr must equal fare.total_inr (within
±50 INR rounding). Mismatch = pricing fraud.
RULE 7 — Driver KYC + permit claims must be verifiable.
RULE 8 — Fatigue compliance is non-negotiable.
cumulative_drive_minutes_today must be reported truthfully. MV Act caps at
10h continuous; partners ignoring this = breach.
RULE 9 — Cancel charges must match displayed thresholds.
Each tier (72h, 24h, 2h) of cancellation must hold to the displayed value.
RULE 10 — No commission-based response shaping.
RULE 11 — Night halt charged only on actual halt nights.
night_halt_count must equal nights between trip_starts and trip_ends where
vehicle remained outside origin city. Charging for nights vehicle returned
home = breach.
RULE 12 — Driver allowance charged only on actual drive days.
driver_allowance_total_inr ≤ allowance_per_day × drive_days_actual. Charging
full DA for non-drive days = breach.
RULE 13 — No silent driver swap mid-trip.
Any driver_id change mid-trip must trigger user notification + consent.
RULE 14 — Itinerary deviation > 30km requires user consent.
itinerary_compliance=major_deviation_over_30km without recorded user consent
= breach.
RULE 15 — Pilgrim trip constraints.
is_pilgrim_trip=true means partner ensures non-alcohol-history driver.
Partner falsifying alcohol-history clearance = severe breach.
VERSION HISTORY
v1.0.0 — 2026-05-10 — Initial spec