T
TOMO
Developer Docs
BETA These docs are under partner review. Some features described are roadmap items, not yet shipped. Verify against your sandbox before relying on any contract.
● DRAFTv1.0.0auto.book_paint_job

Intent Spec — auto.book_paint_job

FULL ID:       auto.book_paint_job
VERSION:       v1.0.0
STATUS:        draft
LAST UPDATED:  2026-05-12
DOMAIN:        auto
PRIMARY AGENT: AutoServicesAgent
TTBS WEIGHTS:  time=0.15 taste=0.30 budget=0.25 safety=0.30

User books paint repair, panel respray, or full-body paint job — scratch repair, accident paint repair, full repaint, denting + painting combo, custom colour. Distinct from detailing's paint correction (which polishes existing paint without repainting). Higher safety weight because mismatched colour or poor body-prep work surfaces 6-12 months later.

Partner exemplars: 3M Body Shop, ASA Body Shops, OEM-authorised body shops (Maruti Service / Hyundai Body Shop), Carnation Auto, GoMechanic Body, local specialist body shops.


SECTION 1 — INTENT IDENTITY

User wants actual paint applied (not polish/correction) to a vehicle panel or whole body. Distinct from:

  • auto.book_detailing — paint correction polishes existing paint; this intent applies new paint
  • auto.book_major_service — major mechanical work; may include body repair as separate sub-job
  • auto.book_breakdown_assist — emergency
  • Wrap install (vinyl) — separate intent in v1.1+ (auto.book_wrap)

Single intent per booking. Multi-panel jobs (e.g. both doors + bumper) are one intent. Denting + painting combo is in-scope (most India body shops bundle).


SECTION 2 — NATURAL LANGUAGE COVERAGE

CLASSIFIES IN

  • "Repaint my bumper"
  • "Scratch on the door, need touch-up"
  • "Full body respray for my Innova"
  • "Accident repair — bonnet + fender need painting"
  • "Match the colour for my Hyundai Verna"
  • "Pearl white paint job estimate"
  • "Denting + painting for rear quarter panel"
  • "Repaint over rust spot"
  • "Insurance claim — body shop authorised by Bajaj Allianz"
  • "Quote for repainting the whole car"

CLASSIFIES OUT — BORDERLINE NO

  • "Polish the paint" → auto.book_detailing
  • "PPF / film install" → auto.book_detailing (current scope) or v1.1+ auto.book_wrap
  • "Touch-up pen for tiny scratches" → not in scope (DIY)
  • "Engine work after accident" → auto.book_major_service

MULTI-INTENT TRIGGERS

  • "Paint job + general service" → auto.book_paint_job + auto.book_general_service
  • "Body work + insurance claim assistance" → auto.book_paint_job + auto.book_insurance_renewal (latter handles claim filing in v1.1+)
  • "Repaint before selling" → auto.book_paint_job + auto.book_rc_transfer

SECTION 3 — INPUT (TOMO → PROVIDER)

{
  "intent": "auto.book_paint_job",
  "request_id": "req_01J9Z...",
  "user_location": { "lat": 17.4475, "lng": 78.3563, "max_radius_km": 25, "city": "Hyderabad" },
  "vehicle": {
    "type": "car",
    "size_class": "sedan",
    "make": "Hyundai",
    "model": "Verna",
    "variant": "SX",
    "year_of_manufacture": 2020,
    "registration_number_last4": "1234",
    "paint_code": "PGU",                       // OEM paint code; user may not know
    "paint_color_name": "Polar White Pearl",
    "current_color_changed": false,            // user repainted away from OEM colour previously
    "panel_count": 4                            // size proxy for full-body estimates
  },
  "job_scope": {
    "scope_type": "panel_repair",              // STRICT ENUM §6
    "panels_to_paint": ["front_bumper", "left_front_door"],   // STRICT ENUM §6
    "denting_required": true,
    "damage_severity": "moderate",             // STRICT ENUM §6
    "match_oem_color_exactly": true,
    "preferred_paint_brand": "any",            // STRICT ENUM §6
    "insurance_claim_intended": true,
    "insurer_name": "Bajaj Allianz"            // free-text when insurance_claim_intended=true
  },
  "service_preferences": {
    "preferred_window": {
      "earliest_drop_off": "2026-05-16T09:00:00+05:30",
      "latest_pickup":     "2026-05-25T18:00:00+05:30"
    },
    "max_acceptable_cost_inr": 25000,
    "loaner_vehicle_required": true,
    "oem_authorised_only": false               // user open to multi-brand if quality verified
  },
  "ttbs_user_band": { "time": "flexible", "taste": "great", "budget": "good", "safety": "great" },
  "session_context": { "tomo_session_id": "ses_01J9Z...", "user_dna_hash": "dna_v3_a7c9..." }
}
Field Type Constraint Notes
intent string REQUIRED, STRICT ENUM Always auto.book_paint_job
vehicle.paint_code string REQUIRED nullable When null, body shop colour-matches from VIN
vehicle.paint_color_name string REQUIRED nullable Human-readable fallback
vehicle.current_color_changed bool REQUIRED TRUE means VIN colour ≠ actual colour; impacts insurance
job_scope.scope_type enum REQUIRED, STRICT ENUM §6
job_scope.panels_to_paint array REQUIRED when scope_type=panel_repair, STRICT ENUM §6
job_scope.denting_required bool REQUIRED TRUE bundles denting labour into quote
job_scope.damage_severity enum REQUIRED, STRICT ENUM §6
job_scope.match_oem_color_exactly bool REQUIRED TRUE means partner uses VIN-matched paint mix
job_scope.insurance_claim_intended bool REQUIRED Steers cashless workflow

Anti-fabrication preamble: Provider may not claim OEM-matched paint without using the actual VIN-mixed code. Body-prep skipping (no primer, no rust treatment) cannot be hidden by promised warranty.


SECTION 4 — PROVIDER TOOLS

Tool 1: search_body_shops

PURPOSE:      Up to 10 body shops capable of scope
SLA:          p50 ≤ 700ms, p95 ≤ 1800ms, p99 ≤ 3500ms
RATE LIMIT:   60 req/min
IDEMPOTENCY:  request_id; 120s cache
RETRY:        1 on 429, 2 on 5xx

Tool 2: book_assessment

PURPOSE:      Book mandatory in-person damage assessment for fixed quote
SLA:          p50 ≤ 1000ms, p95 ≤ 3000ms
RATE LIMIT:   30 req/min
IDEMPOTENCY:  request_id
RETRY:        No retry

Tool 3: get_assessment_quote

PURPOSE:      Post-assessment itemized quote
SLA:          p50 ≤ 600ms, p95 ≤ 1800ms
RATE LIMIT:   60 req/min
RETRY:        1 on 5xx

Tool 4: confirm_paint_booking

PURPOSE:      Lock paint job after quote approval
SLA:          p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT:   30 req/min
IDEMPOTENCY:  request_id
RETRY:        No retry

Tool 5: cancel_paint_booking

SLA:          p50 ≤ 700ms, p95 ≤ 2000ms
RATE LIMIT:   30 req/min
RETRY:        1 on 5xx

SECTION 5 — RESPONSE SHAPE

BodyShop

BodyShop:
  shop_id: { type: string, constraint: REQUIRED }
  name: { type: string, constraint: REQUIRED }
  shop_type:
    type: enum
    constraint: REQUIRED, STRICT ENUM §6
    values: [oem_authorised_body_shop, multi_brand_premium, brand_authorised_paint, independent_specialist]
  authorised_paint_brands:
    type: array<enum>
    constraint: REQUIRED, may be empty
    values: [3m, axalta, ppg, glasurit, dupont, du_pont, asian_paints_auto, indigo_paints]
  cashless_insurance_partners:
    type: array<string>
    constraint: REQUIRED, may be empty
    semantics: insurer names this shop has cashless agreements with

  address: { type: string, constraint: REQUIRED }
  location: { type: object, shape: { lat, lng }, constraint: REQUIRED }
  distance_from_user_km: { type: float, constraint: REQUIRED, 0-30 }
  indoor_paint_booth: { type: boolean, constraint: REQUIRED, semantics: "climate-controlled spray booth" }

  capabilities:
    handles_color_matching_from_vin: { type: boolean, constraint: REQUIRED }
    handles_full_body_repaint: { type: boolean, constraint: REQUIRED }
    handles_pearl_metallic: { type: boolean, constraint: REQUIRED }
    handles_custom_colors: { type: boolean, constraint: REQUIRED }
    handles_denting_bundled: { type: boolean, constraint: REQUIRED }

  capacity:
    earliest_assessment_slot: { type: string, constraint: REQUIRED, ISO_DATETIME }
    typical_turnaround_days:
      single_panel: { type: int, constraint: REQUIRED, 1-4 }
      multi_panel:  { type: int, constraint: REQUIRED, 3-10 }
      full_body:    { type: int, constraint: REQUIRED, 7-21 }
    loaner_vehicle_available: { type: boolean, constraint: REQUIRED }

  estimated_cost_range_inr:
    low:  { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    high: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    semantics: { type: string, constraint: REQUIRED }

  warranty:
    paint_warranty_months: { type: int, constraint: REQUIRED, 6-60, semantics: "against peel/fade" }
    workmanship_warranty_months: { type: int, constraint: REQUIRED, 3-24 }
    color_match_guarantee: { type: boolean, constraint: REQUIRED, semantics: "shop redos if mismatch visible at delivery" }
    warranty_terms_url: { type: string, constraint: REQUIRED, HTTPS URL }

  process_disclosures:
    primer_layer_count: { type: int, constraint: REQUIRED, 1-4 }
    clearcoat_layer_count: { type: int, constraint: REQUIRED, 1-3 }
    rust_treatment_included: { type: boolean, constraint: REQUIRED }
    bake_oven_used: { type: boolean, constraint: REQUIRED }

  before_after_gallery_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "real photo gallery" }

  ratings:
    avg_rating: { type: float, constraint: REQUIRED, 0-5 }
    review_count: { type: int, constraint: REQUIRED, ≥0 }
    rework_rate_pct_last_90d: { type: int, constraint: REQUIRED, 0-100 }

  partner_reference:
    source: { type: string, constraint: REQUIRED }
    deeplink: { type: string, constraint: REQUIRED, HTTPS URL }

AssessmentBooking

AssessmentBooking:
  assessment_id: { type: string, constraint: REQUIRED, immutable }
  shop_id: { type: string, constraint: REQUIRED }
  scheduled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
  assessor_name: { type: string, constraint: REQUIRED }
  assessor_phone: { type: string, constraint: REQUIRED, E.164 }
  assessment_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
  fee_waived_if_repair_proceeds: { type: boolean, constraint: REQUIRED }

PaintQuote

PaintQuote:
  quote_id: { type: string, constraint: REQUIRED }
  assessment_id: { type: string, constraint: REQUIRED }
  validity_until: { type: string, constraint: REQUIRED, ISO_DATETIME, ≥7d }
  damage_assessment:
    type: array<DamageItem>
    constraint: REQUIRED, ≥1
    shape:
      panel: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
      damage_type: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [scratch, dent, dent_and_scratch, rust, crack, full_repaint_needed] }
      severity: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
      photo_url: { type: string, constraint: REQUIRED, HTTPS URL }
      labour_hours: { type: float, constraint: REQUIRED, 0.5-40 }
  line_items:
    type: array<LineItem>
    constraint: REQUIRED, ≥1
    shape:
      sku: { type: string, constraint: REQUIRED }
      description: { type: string, constraint: REQUIRED }
      category: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
      total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
      necessity: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
  insurance_handling:
    cashless_eligible: { type: boolean, constraint: REQUIRED }
    insurer_pre_approval_required: { type: boolean, constraint: REQUIRED }
    estimated_deductible_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    estimated_depreciation_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    estimated_out_of_pocket_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
  totals:
    subtotal_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
    gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
    total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }

PaintBooking

PaintBooking:
  booking_id: { type: string, constraint: REQUIRED, immutable }
  quote_id: { type: string, constraint: REQUIRED }
  drop_off_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
  estimated_pickup: { type: string, constraint: REQUIRED, ISO_DATETIME }
  loaner_arranged: { type: boolean, constraint: REQUIRED }
  total_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
  insurance_path:
    type: enum
    constraint: REQUIRED, STRICT ENUM §6
    values: [cashless, reimbursement, no_claim]
  service_advisor_phone: { type: string, constraint: REQUIRED, E.164 }
  payment_due_at: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [50_percent_now_balance_on_pickup, on_pickup, insurance_cashless_then_deductible] }

CancellationResult

CancellationResult:
  booking_id: { type: string, constraint: REQUIRED }
  cancelled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
  cancellation_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
  refund_amount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
  refund_eta_days: { type: int, constraint: REQUIRED, 0-21 }

FORBIDDEN FIELDS

  • paid_placement_score, ad_bid, sponsored_rank, promotion_priority, kickback_amount
  • artificial_urgency_text
  • ai_generated_photo for before/after / damage assessment imagery (CRITICAL — real photos only)
  • commission_padded_price
  • paint_warranty_inflated
  • false_oem_match_claim

SECTION 6 — CONTROLLED VOCABULARIES

job_scope.scope_type:
  values:
    scratch_only:   "Single scratch repair (clearcoat only or single layer)"
    panel_repair:   "1-4 specific panels"
    multi_panel:    "5+ panels"
    full_body:      "Entire vehicle"
    custom_color_change: "Repaint to non-OEM colour"

job_scope.panels_to_paint:
  values:
    front_bumper, rear_bumper,
    bonnet, boot,
    left_front_door, left_rear_door, right_front_door, right_rear_door,
    left_front_fender, right_front_fender,
    left_rear_quarter, right_rear_quarter,
    roof,
    left_running_board, right_running_board

job_scope.damage_severity:
  values:
    minor:    "Surface scratch, no dent"
    moderate: "Scratch + minor dent OR deep scratch"
    major:    "Significant denting + paint loss"
    severe:   "Panel replacement may be required"

job_scope.preferred_paint_brand:
  values: { any, 3m, axalta, ppg, glasurit, dupont, asian_paints_auto, indigo_paints }

shop_type:
  values:
    oem_authorised_body_shop: "Vehicle OEM authorised body shop"
    multi_brand_premium: "Premium multi-brand body shop"
    brand_authorised_paint: "Paint brand authorised applicator (3M / PPG etc.)"
    independent_specialist: "Independent body shop"

damage_assessment.damage_type:
  values: { scratch, dent, dent_and_scratch, rust, crack, full_repaint_needed }

line_item.category:
  values: { labour, paint, primer, clearcoat, panel_replacement, denting, rust_treatment, masking, sublet }

line_item.necessity:
  values: { mandatory_for_safety, mandatory_for_warranty, recommended, optional }

insurance_path:
  values:
    cashless:        "Insurer pays partner directly; user pays deductible only"
    reimbursement:   "User pays partner; user files claim for refund"
    no_claim:        "User pays out of pocket; no claim filed"

payment_due_at:
  values: { 50_percent_now_balance_on_pickup, on_pickup, insurance_cashless_then_deductible }

SECTION 7 — TTBS DIMENSIONS

TIME (weight = 0.15):
  signals_used: [distance, earliest_assessment_slot, typical_turnaround_days]

TASTE (weight = 0.30):
  signals_used:
    - shop_type matching oem_authorised_only filter
    - authorised_paint_brands matching preferred_paint_brand
    - capabilities.handles_pearl_metallic / handles_color_matching_from_vin matching scope
  weighting:
    type: 0.30
    brand: 0.35
    capability: 0.35

BUDGET (weight = 0.25):
  signals_used:
    - estimated_cost_range_inr
    - insurance_handling.cashless_eligible (TRUE bonus — lower out-of-pocket)
  weighting:
    cost: 0.70
    cashless_bonus: 0.30

SAFETY (weight = 0.30):
  signals_used:
    - warranty.paint_warranty_months
    - warranty.workmanship_warranty_months
    - warranty.color_match_guarantee
    - process_disclosures.bake_oven_used (TRUE preferred for durability)
    - process_disclosures.rust_treatment_included (when damage_type includes rust)
    - ratings.rework_rate_pct_last_90d (LOWER better)
  weighting:
    paint_warranty: 0.25
    workmanship_warranty: 0.15
    color_match: 0.20
    bake_oven: 0.15
    rework_rate: 0.25

SECTION 8 — COMPLETION CONTRACT

POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
  "intent":           "auto.book_paint_job",
  "external_id":      "<booking_id>",
  "request_id":       "<request_id>",
  "amount_inr":       6400,    // NET (supplier-kept labour + paint margin)
  "gst_inr":          1152,
  "tips_inr":         0,
  "pass_through_inr": 0,       // none typically; sublet may apply rarely
  "closed_at":        "2026-05-22T15:00:00+05:30",
  "status":           "completed",
  "scope_performed": "panel_repair",
  "panels_painted_count": 2,
  "insurance_settled": true,
  "color_match_signed_off": true,
  "warranty_card_issued": true
}

HMAC, 5-min replay, NET-only commission.


SECTION 9 — WIDGET

PaintJobWidget (planned).

Field mapping:
  - BodyShop.name → header
  - shop_type + paint brand badges → subline 1
  - distance + typical_turnaround_days[scope] → subline 2
  - estimated_cost_range_inr → range pill
  - warranty.paint_warranty_months + color_match_guarantee → warranty badges
  - cashless_insurance_partners (when insurance_claim_intended) → cashless badges
  - before_after_gallery_url → expandable gallery
  - ratings.rework_rate_pct_last_90d → "X% rework rate" pill (lower=green)

SECTION 10 — CACHING POLICY

Call TTL
search_body_shops 120s
book_assessment NO CACHE
get_assessment_quote 5min
confirm_paint_booking NO CACHE
cancel_paint_booking NO CACHE
Shop static (paint brands, cashless partners, warranties) 6h

SECTION 11 — 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 (webhook) HMAC fail No
NO_SHOPS_IN_AREA 200 (empty) Valid, no matches n/a
PAINT_CODE_NOT_AVAILABLE 422 OEM paint code not in shop's stocked range No
PANEL_REPLACEMENT_NEEDED 200 (advisory in quote) Damage too severe; line item flags panel_replacement n/a
INSURER_NOT_PARTNERED 422 Cashless not possible; UI offers reimbursement path No
ASSESSMENT_FEE_DUE_FIRST 402 User must pay assessment fee before scheduling No
QUOTE_EXPIRED 410 (confirm) quote.validity_until passed No
INSURANCE_PRE_APPROVAL_FAILED 422 Insurer rejected cashless pre-approval No
CANCELLATION_FEE_DUE 200 (cancel) Non-zero fee n/a

SECTION 12 — SANDBOX → PRODUCTION CHECKLIST

[ ] All five tools implemented
[ ] At least 3 body shops covering different paint brands
[ ] handles_color_matching_from_vin verifiable via test VIN lookup
[ ] indoor_paint_booth claims backed by uploaded shop photos
[ ] cashless_insurance_partners list backed by uploaded MOU letters
[ ] All controlled vocabularies respected
[ ] HMAC signing verified
[ ] amount_inr is NET in CPC
[ ] color_match_signed_off in CPC reflects real user sign-off (not auto-set)
[ ] No forbidden fields
[ ] SLA p95 met
[ ] before_after_gallery_url returns real customer photos (not stock)
[ ] paint_warranty_months matches paint brand's published warranty
[ ] Compliance docs: GSTIN, shop license, paint brand authorisations, insurer cashless MOUs, privacy policy URL

SECTION 13 — ANTI-FABRICATION RULES

RULE 1: No paid_placement / ad / kickback. Rejects response.

RULE 2: authorised_paint_brands and cashless_insurance_partners claims
        require uploaded current-year authorisation/MOU documents.
        False claims = immediate suspension + brand/insurer relationship breach.

RULE 3: paint_warranty_months MUST match the paint brand's published warranty.
        Inflating to win rank = suspension after 2 incidents.

RULE 4: color_match_guarantee=true means partner redos colour at no charge if
        user signs off on mismatch at delivery. Declining a colour-match redo
        within window = suspension. TOMO requires color_match_signed_off in
        CPC; FALSE there → user filed grievance → opens warranty case.

RULE 5: before_after_gallery_url MUST contain real customer photos. Stock or
        AI-generated images = immediate suspension. TOMO field-tests via
        reverse image search on a sample.

RULE 6: estimated_cost_range_inr must reflect realistic bounds for the
        scope. Padding the high end to make low end look competitive,
        then quoting at the high end at assessment, = suspension.

RULE 7: damage_assessment.damage_type and severity must match real damage.
        Inflating severity to bill more = customer-harm + insurance-fraud
        risk = immediate suspension.

RULE 8: process_disclosures.primer_layer_count / clearcoat_layer_count /
        bake_oven_used must reflect actual process. Skipping primer layers
        and claiming 2-coat is grounds for immediate suspension when
        verified via partner audit.

RULE 9: rust_treatment_included=true requires actual rust converter / primer
        application when damage includes rust. TOMO samples user photos
        post-delivery vs partner's process record.

RULE 10: false_oem_match_claim — partners claiming OEM colour match while
         using close-but-not-exact paint mix is grounds for suspension.
         TOMO audits via spectrophotometer reading on a sample.

RULE 11: No artificial_urgency_text. Body work is rarely time-critical.

RULE 12: No "Top Pick" / "TOMO Recommended" badges. Source-blind TTBS only.

RULE 13: line_item.necessity must be honest. Marking optional cosmetic work
         as mandatory_for_safety = suspension.

VERSION HISTORY

v1.0.0 — 2026-05-12 — Initial spec. NET commission base. TASTE-dominant
                       (0.30) — brand & quality matter; SAFETY (0.30) catches
                       process-skipping (primer skip, no bake oven).