mobility.book_intracity_ride — Full Intent Specification
INTENT NAMESPACE: mobility
INTENT NAME: book_intracity_ride
FULL ID: mobility.book_intracity_ride
VERSION: v1.0.0
STATUS: live
LAST UPDATED: 2026-05-09
TTBS WEIGHTS: time 0.40 · taste 0.10 · budget 0.30 · safety 0.20
1. NATURAL LANGUAGE COVERAGE
Classifies IN
- "ride to airport"
- "cab to HITEC City"
- "auto to MG Road"
- "book me a Rapido to Banjara Hills"
- "I need a cab right now to Apollo Hospital"
- "Uber to home"
- "ola to office"
- "bike taxi to RGI airport"
- "EV cab to Gachibowli"
Classifies OUT — borderline NO
- "self-drive car for the weekend" →
mobility.book_self_drive - "Goa to Mumbai cab" →
mobility.book_intercity_ride - "rental scooter for the day" →
mobility.book_two_wheeler_rental - "outstation cab to Tirupati" →
mobility.book_outstation_package - "I want to drive to office tomorrow" → no intent (informational; NOT a TOMO action)
MULTI-INTENT TRIGGERS
- "ride to airport tomorrow morning, also order coffee" →
mobility.book_intracity_ride+food.order_delivery - "book cab to airport, pickup at 4 AM" + flight context → may chain
mobility.book_airport_transfer
2. INPUT — TOMO → PROVIDER
{
"intent": "mobility.book_intracity_ride",
"intent_version": "v1.0.0",
"request_id": "req_4r8t1k_2026-05-09T08:14:00Z",
"user_session_id": "anon_user_token_or_uid",
"pickup": {
"lat": 17.4435,
"lng": 78.3772,
"address": "HITEC City Main Road, Madhapur",
"neighborhood": "Madhapur",
"city": "Hyderabad",
"pincode": "500081",
"country_code": "IN",
"place_kind": "office",
"instructions": "Pickup gate B"
},
"drop": {
"lat": 17.2403,
"lng": 78.4294,
"address": "Rajiv Gandhi International Airport",
"neighborhood": "Shamshabad",
"city": "Hyderabad",
"pincode": "500409",
"country_code": "IN",
"place_kind": "airport",
"instructions": "Terminal 1 departures"
},
"intent_kind": "asap",
"scheduled_for_iso": "2026-05-09T08:14:00+05:30",
"party": {
"passenger_count": 1,
"luggage_pieces": 2,
"luggage_size": "checkin"
},
"preferences": {
"vehicle_kinds_acceptable": ["sedan", "suv", "hatchback", "ev_sedan"],
"budget_band": "good",
"budget_max_inr": 700,
"max_eta_minutes": 8,
"ac_required": true,
"female_driver_required": false,
"ev_only": false,
"wheelchair_accessible_required": false,
"child_seat_required": false,
"pet_friendly_required": false,
"no_pool": true,
"carry_pet": false,
"max_seat_capacity_min": 4
},
"route_context": {
"estimated_distance_km": 28.5,
"estimated_duration_min": 47,
"involves_toll": true,
"toll_count": 1,
"involves_highway": true,
"weather_celsius": 28,
"rain_probability_pct": 20,
"current_aqi": 142,
"is_late_night": false,
"is_surge_window": false
},
"context": {
"user_locale": "en-IN",
"user_currency_pref": "INR",
"trip_purpose": "airport_dropoff",
"trust_signals": {
"is_repeat_customer": true,
"prior_rides_with_partner": 37,
"user_account_age_days": 312,
"fastag_present": true,
"fastag_balance_inr": 245
}
}
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, equals "mobility.book_intracity_ride" |
|
pickup.country_code |
ISO_3166_2 | REQUIRED, always IN |
|
pickup.place_kind |
enum | REQUIRED, see §6 | |
drop.place_kind |
enum | REQUIRED, see §6 | |
intent_kind |
enum | REQUIRED, STRICT asap | scheduled |
|
party.luggage_size |
enum | REQUIRED, STRICT none | handbag | backpack | cabin | checkin | oversized |
|
preferences.vehicle_kinds_acceptable |
array |
REQUIRED, ≥1 | see §6 |
preferences.no_pool |
bool | REQUIRED | rejects shared rides if true |
route_context.involves_toll |
bool | REQUIRED | |
route_context.toll_count |
int | REQUIRED, ≥0 | |
route_context.current_aqi |
int | REQUIRED, ≥0 | |
route_context.is_late_night |
bool | REQUIRED | |
route_context.is_surge_window |
bool | REQUIRED | |
context.trip_purpose |
enum | REQUIRED, see §6 | |
context.trust_signals.fastag_present |
bool | REQUIRED | |
context.trust_signals.fastag_balance_inr |
INR_INTEGER | REQUIRED | 0 if no FASTag |
Anti-fabrication preamble (universal): no paid placement, no urgency text, no commission-influenced fields.
3. PROVIDER TOOLS
Tool 1: get_ride_estimates
PURPOSE: return ride options with fares + ETAs across vehicle kinds
INPUT: §2 request body
OUTPUT: { options: RideOption[], result_token, expires_at }
SLA: p50 < 400ms, p95 < 1000ms
RATE LIMIT: ≤ 2/sec per user
Tool 2: book_ride
PURPOSE: commit a ride
INPUT: { ride_option_id, payment_token, request_id, idempotency_key, user_phone, otp_required }
OUTPUT: { ride_ref, status, driver, vehicle, fare_quote, otp_for_driver }
SLA: p95 < 4000ms
IDEMPOTENCY: REQUIRED on idempotency_key
Tool 3: track_ride
PURPOSE: live ride state + driver location
INPUT: { ride_ref, request_id }
OUTPUT: RideTrack (§5)
SLA: p95 < 400ms
RATE LIMIT: ≤ 1 every 5s
Tool 4: cancel_ride
PURPOSE: cancel
INPUT: { ride_ref, reason, request_id }
OUTPUT: { status, cancellation_charge_inr, refund_amount_inr }
SLA: p95 < 2000ms
Tool 5: update_ride_drop
PURPOSE: change drop mid-ride (add stop or modify)
INPUT: { ride_ref, new_drop, additional_stops[], request_id }
OUTPUT: { revised_fare_inr, revised_eta_minutes, status }
SLA: p95 < 1500ms
Tool 6: rate_ride
PURPOSE: post-ride rating
INPUT: { ride_ref, rating_5star, comment, tip_inr, request_id }
OUTPUT: { acknowledged: true }
SLA: p95 < 800ms
Tool 7: share_trip_status
PURPOSE: return a tokenized URL the user can share for live trip tracking
INPUT: { ride_ref, recipient_phone_optional, request_id }
OUTPUT: { share_url, expires_at }
SLA: p95 < 500ms
All seven REQUIRED.
4. RESPONSE SHAPE
RideOption (returned by get_ride_estimates)
id: string, REQUIRED
ride_option_token: string, REQUIRED # opaque, used in book_ride
expires_at: ISO_DATETIME, REQUIRED
vehicle_kind: STRICT ENUM, REQUIRED # see §6
vehicle_class: STRICT ENUM, REQUIRED # see §6
display_label: string, REQUIRED # "Uber Premier", "Ola Sedan"
seat_capacity: int, REQUIRED, ≥1
luggage_capacity: STRICT ENUM, REQUIRED # see §6
eta:
pickup_minutes: int, REQUIRED
trip_minutes: int, REQUIRED
total_minutes: int, REQUIRED # pickup + trip
drivers_within_radius_count: int, REQUIRED, ≥0
closest_driver_km: float, REQUIRED, ≥0
fare:
total_inr: INR_INTEGER, REQUIRED
base_inr: INR_INTEGER, REQUIRED
per_km_inr: float, REQUIRED
per_minute_inr: float, REQUIRED
surge_multiplier: float, REQUIRED, ≥1.0 # 1.0 if no surge
surge_reason: STRICT ENUM, REQUIRED # see §6 ("none" if no surge)
toll_inr: INR_INTEGER, REQUIRED
toll_count: int, REQUIRED, ≥0
late_night_inr: INR_INTEGER, REQUIRED # 0 if not late night
airport_pickup_charge_inr: INR_INTEGER, REQUIRED # 0 unless airport
airport_drop_charge_inr: INR_INTEGER, REQUIRED # 0 unless airport
highway_charge_inr: INR_INTEGER, REQUIRED # 0 unless highway
state_border_charge_inr: INR_INTEGER, REQUIRED # 0 if same-state
parking_charge_inr: INR_INTEGER, REQUIRED # 0 if not relevant
platform_fee_inr: INR_INTEGER, REQUIRED
gst_inr: INR_INTEGER, REQUIRED
rider_tip_optional_inr: INR_INTEGER, REQUIRED # default 0; user-driven
fare_breakdown_text: string, REQUIRED # human-readable
is_upfront_fare: boolean, REQUIRED # true = locked
fare_locked_until_iso: ISO_DATETIME, REQUIRED
vehicle_amenities:
ac: boolean, REQUIRED
music_on_demand: boolean, REQUIRED
charging_port: boolean, REQUIRED # USB-A or USB-C
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 # see §6
wheelchair_accessible: boolean, REQUIRED
oxygen_supply_for_emergency: boolean, REQUIRED # ambulance-grade only
vehicle_meta:
age_years: int, REQUIRED
fuel_kind: STRICT ENUM, REQUIRED # see §6
ev_battery_charge_pct: int, REQUIRED, 0-100 # 0 if not EV
emission_norm: STRICT ENUM, REQUIRED # see §6
registration_state_code: string, REQUIRED # "TS"
vehicle_class_certification: STRICT ENUM, REQUIRED # commercial_yellow_plate | private | etc.
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 # see §6
commercial_aggregator_permit_number: string, REQUIRED
vehicle_color: string, REQUIRED # for visual ID
driver_meta:
driver_id: string, REQUIRED
display_name: string, REQUIRED # first name
photo_url: URL, REQUIRED
rating_avg: float, REQUIRED, 0-5
rides_completed_total: 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 # 18-25 | 26-35 | 36-50 | 51+
experience_years_driving: int, REQUIRED, ≥0
driver_kyc:
dl_verified: boolean, REQUIRED
dl_number_masked: string, REQUIRED # "TG**1234"
dl_valid_until_iso: ISO_DATE, 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 # required by Motor Vehicle Act
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
route_quality:
estimated_distance_km: float, REQUIRED
estimated_duration_min: int, REQUIRED
surge_zones_passed_through: int, REQUIRED, ≥0
highway_kms: float, REQUIRED
inner_road_kms: float, REQUIRED
toll_passes: array, REQUIRED, may be empty
- toll_name: string, REQUIRED
toll_amount_inr: INR_INTEGER, REQUIRED
fastag_supported: boolean, REQUIRED
cash_accepted: boolean, REQUIRED
cancellation:
free_cancel_within_minutes: int, REQUIRED # post-booking grace window
cancel_charge_after_grace_inr: INR_INTEGER, REQUIRED
no_show_charge_inr: INR_INTEGER, REQUIRED
driver_cancel_compensation_inr: INR_INTEGER, REQUIRED # if driver cancels late, what user gets
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 # derived from §2 input
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
RideTrack (returned by track_ride)
ride_ref: string, REQUIRED
status: STRICT ENUM, REQUIRED # see §6
status_updated_iso: ISO_DATETIME, REQUIRED
status_history: array, REQUIRED, ≥1
- status: STRICT ENUM, REQUIRED
iso: ISO_DATETIME, REQUIRED
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
vehicle:
vehicle_kind: STRICT ENUM, REQUIRED
display_label: string, REQUIRED
color: string, REQUIRED
plate_masked: string, REQUIRED # "•• 1234"
location:
current_lat: float, REQUIRED
current_lng: float, REQUIRED
heading_degrees: float, REQUIRED, 0-360
speed_kmh: float, REQUIRED, ≥0
location_updated_iso: ISO_DATETIME, REQUIRED
status: STRICT ENUM, REQUIRED # see §6
eta:
to_pickup_minutes: int, REQUIRED # 0 if past pickup
to_drop_minutes: int, REQUIRED
revised_fare_inr: INR_INTEGER, REQUIRED # if route changed
detour_minutes: int, REQUIRED # 0 if no detour
ride_safety:
on_route: boolean, REQUIRED
unusual_stop_detected: boolean, REQUIRED
unusual_speed_detected: boolean, REQUIRED
trip_share_active: boolean, REQUIRED
trip_share_url: URL, REQUIRED # always present, may be unused
fastag:
next_toll_distance_km: float, REQUIRED # 9999 if no upcoming toll
next_toll_amount_inr: INR_INTEGER, REQUIRED # 0 if none
user_fastag_balance_sufficient_for_remaining_tolls: boolean, REQUIRED
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_driver_rating | partner_paid_for_top_listing
5. CONTROLLED VOCABULARIES
vehicle_kind (preferences + RideOption)
auto | bike_taxi | hatchback | sedan | suv | premium_sedan | premium_suv |
ev_hatchback | ev_sedan | ev_suv | electric_3wheeler |
shared_hatchback | shared_sedan | luxury_sedan | luxury_suv |
xl_van | wheelchair_accessible_van
vehicle_class
economy | comfort | premium | luxury | xl | xl_premium | shared
RideOption.luggage_capacity
small | medium | large | xl
pickup.place_kind and drop.place_kind
home | office | airport | railway | metro_station | bus_terminal |
hotel | restaurant | mall | hospital | clinic | school | college |
gym | salon | event_venue | religious_place | grocery | pharmacy |
park | landmark | other
party.luggage_size
none | handbag | backpack | cabin | checkin | oversized
preferences.vehicle_kinds_acceptable
Same enum as vehicle_kind above.
preferences.female_driver_required / ac_required / ev_only etc.
booleans (no enum)
RideOption.fare.surge_reason
none | rain | weekend_evening | morning_peak | late_night | major_event |
festival | airport_demand | city_event | rider_shortage
route_context.is_late_night
boolean. Definition: pickup_local_time between 22:30 and 05:30.
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
contract_carriage | stage_carriage | private | tourist | aggregator_permit
vehicle_meta.vehicle_class_certification
commercial_yellow_plate | aggregator_white_with_yellow_strip | private | tourist | tempo_traveller
vehicle_amenities.child_seat_kind
none | infant | toddler | booster | universal
driver_meta.age_band
18-25 | 26-35 | 36-50 | 51+
RideTrack.status
searching_driver | driver_assigned | driver_arriving | arrived |
otp_required | trip_started | en_route | nearby_drop |
completed | cancelled_by_user | cancelled_by_driver | failed
RideTrack.location.status
heading_to_pickup | at_pickup | trip_in_progress | nearby_drop | reached_drop
cancellation.reason (in cancel_ride input)
user_changed_mind | wrong_vehicle | wrong_address | driver_too_far |
driver_unresponsive | safety_concern | no_longer_needed | found_alternative |
emergency
context.trip_purpose
commute_to_work | commute_to_home | airport_dropoff | airport_pickup |
hospital_visit | shopping | dining_out | event | religious | leisure |
emergency | other
merchant_id resolution
N/A — driver+vehicle is the listing unit, no cross-partner dedup necessary at the ride level.
6. TTBS DIMENSIONS
Per-domain weights (locked)
mobility: { time: 0.40, taste: 0.10, budget: 0.30, safety: 0.20 }
TIME
SIGNALS USED:
- eta.pickup_minutes weight 0.50
- eta.drivers_within_radius_count weight 0.10
- eta.closest_driver_km weight 0.10
- route_quality.estimated_duration_min weight 0.20
- is_surge_window penalty 0.10
USER BAND HANDLING:
- "asap" → pickup_minutes weight up to 0.60
- max_eta_minutes HARD FILTER → drop options exceeding
TASTE
SIGNALS USED:
- driver_meta.rating_avg weight 0.40
- vehicle_meta.age_years (newer = better) weight 0.20
- vehicle_amenities.ac (if ac_required) HARD FILTER
- vehicle_amenities match w/ user prefs weight 0.30
- languages_spoken match w/ user_locale weight 0.10
BUDGET
SIGNALS USED:
- fare.total_inr vs band:
ok → auto / hatchback / shared
good → sedan / hatchback / EV
great → premium_sedan / premium_suv / luxury
- surge_multiplier (lower = better) weight 0.20
- upfront_fare locked (yes = better) weight 0.10
HARD FILTERS:
- fare.total_inr > preferences.budget_max_inr → drop
USER BAND HANDLING:
- persistent "ok" users see budget_band defaults boosted
- emergency trip_purpose deweights budget
SAFETY
SIGNALS USED:
- driver_kyc.background_check_passed HARD FILTER
- driver_kyc.dl_verified HARD FILTER
- vehicle_meta.comprehensive_insurance HARD FILTER
- vehicle_meta.permit_kind in (aggregator|contract|tourist) HARD FILTER
- safety_features.sos_button_in_app weight 0.15
- safety_features.trip_share_supported weight 0.15
- safety_features.cctv_in_cab weight 0.10
- safety_features.driver_drowsiness_detection weight 0.10
- vehicle_meta.fitness_certificate_valid_until_iso > now+30d weight 0.10
- driver_meta.female_driver
(boosted if female_driver_required) weight 0.20
- is_late_night → safety weight scales 1.5x
HARD FILTERS:
- female_driver_required → drop male drivers
- wheelchair_accessible_required → drop non-wheelchair
- child_seat_required → drop without seat
- ev_only → drop non-EV
Hidden ranking factor
information_completeness_score weight 0.10.
FASTag check
If route_context.involves_toll AND user_fastag_balance_sufficient = false, TOMO surfaces a top-up CTA before booking. Locked behavior; not a TTBS dimension.
7. COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/{tomo_partner_id}
X-TOMO-Timestamp: <ms>
X-TOMO-Signature: sha256=<hex>
{
"intent": "mobility.book_intracity_ride",
"intent_version": "v1.0.0",
"external_id": "UBER-RIDE-XYZ",
"amount_inr": 480,
"closed_at": "2026-05-09T09:02:00+05:30",
"request_id": "req_4r8t1k_...",
"status": "completed",
"ride_ref": "UBER-RIDE-XYZ",
"started_at": "2026-05-09T08:21:00+05:30",
"completed_at": "2026-05-09T09:02:00+05:30",
"distance_traveled_km": 28.7,
"duration_minutes": 41,
"promised_eta_minutes": 47,
"actual_eta_minutes": 41,
"currency": "INR",
"fare_breakdown_total_inr": 480,
"rider_tip_inr": 0,
"ratings_pending": true,
"notes": ""
}
Status enum: completed | cancelled_by_user | cancelled_by_driver | failed | rerouted_with_extra_charge
8. WIDGET
WIDGET TYPE: ride_options
SOURCE: src/widgets/types.ts
TYPE NAME: RideOptionsPayload
RENDERED IN: components/widgets/RideOptionsWidget.tsx
Default: 3 stacked rows showing vehicle_kind, ETA, fare, key amenities. Tap row → confirmation card → "Book". Then RideTrackingCard with live driver location.
9. CACHING POLICY
| Call | TTL | Rationale |
|---|---|---|
get_ride_estimates |
30s | surge + driver positions move fast |
track_ride |
0s | always live |
book_ride |
0s | |
cancel_ride |
0s | |
update_ride_drop |
0s | |
| Failure responses | 0s |
10. ERROR CODES
| Code | HTTP | Meaning | TOMO behavior |
|---|---|---|---|
NO_DRIVERS_AVAILABLE |
503 | none in radius | retry with delay or fall back to other partners |
OUT_OF_SERVICE_AREA |
400 | pickup or drop outside coverage | surface to user |
OPTION_EXPIRED |
410 | ride_option_token invalid | re-quote |
PAYMENT_DECLINED |
402 | gateway rejection | surface |
OTP_FAILED |
401 | OTP-at-pickup mismatch | surface |
RIDE_NOT_FOUND |
404 | ride_ref doesn't exist | surface |
ALREADY_CANCELLED |
409 | duplicate cancel | idempotent return |
DRIVER_UNRESPONSIVE |
503 | driver assigned but not moving | offer reassign |
SURGE_EXCEEDED_BUDGET |
400 | new surge pushed over budget_max | re-quote with new band |
FASTAG_INSUFFICIENT |
400 | route requires FASTag, balance low | surface top-up CTA |
11. SANDBOX → PRODUCTION CHECKLIST
[ ] All §2 inputs validated, request_id echoed
[ ] get_ride_estimates returns ≥3 options for "HITEC City → RGI airport, 1 passenger, 2 bags"
[ ] All §4 required fields populated with REAL data
[ ] driver_kyc + vehicle_meta truthful + verifiable on demand
[ ] background_check_passed=true backed by partner's KYC vendor
[ ] fitness_certificate + insurance + PUC + permit numbers all valid
[ ] book_ride returns ride_ref + driver assignment within SLA
[ ] track_ride returns driver location ≤5s old
[ ] cancel_ride respects free_cancel_within_minutes window
[ ] update_ride_drop computes revised fare correctly
[ ] CPC webhook arrives within 60s of ride completion
[ ] HMAC verification passes
[ ] No forbidden fields anywhere
[ ] Trip share URL works for ≥2h post-completion
[ ] SOS button tested with TOMO ops monitoring
[ ] No paid placement / sponsored signals
[ ] customer_support_24x7 verified by TOMO field call
[ ] Aggregator permit certificate uploaded
[ ] State permit covers all cities partner serves
12. ANTI-FABRICATION RULES
RULE 1 — No paid placement signals
RULE 2 — No fake driver ratings
rating_avg = unrounded float from real ride feedback. TOMO samples 1% rides.
RULE 3 — No fake driver photos / AI photos
photo_url must show same driver who arrives. TOMO field-tests.
RULE 4 — Vehicle plate must match the actual vehicle dispatched
plate_masked at booking → must match vehicle that arrives. Mismatch = breach.
RULE 5 — Fare displayed must be honored
is_upfront_fare=true means fare_locked_until_iso. Any post-trip price hike
(other than legitimate detour) = breach.
RULE 6 — Driver KYC claims must be verifiable
TOMO ops can request KYC docs for any driver_id at any time. Failure to
produce within 48h = breach.
RULE 7 — SOS / panic features must function
Self-declared CCTV/SOS/panic features tested in sandbox; failures block
production approval.
RULE 8 — No surge gaming
surge_multiplier > 1.0 requires surge_reason ∈ valid enum. TOMO checks
surge against same-time-same-area data on partner's own app via 1% audit.
RULE 9 — Cancel charges must match displayed
free_cancel_within_minutes window enforced server-side. Charging within
the window = breach.
RULE 10 — No commission-based response shaping
Same trip on TOMO and on partner's app must yield same fare.
VERSION HISTORY
v1.0.0 — 2026-05-09 — Initial spec