Skip to main content

Overview

A job in MechZie follows a strict state machine from creation to payment. Understanding these states is critical for building the correct UI flows.

State Machine

Status Reference

StatusWho triggersDescriptionUI State
pendingSystemJob created, about to dispatch”Finding a mechanic…”
dispatchingSystemActively searching for mechanics”Searching nearby mechanics…”
acceptedMechanicA mechanic accepted the jobShow mechanic info
en_routeMechanicMechanic is driving to locationShow map + ETA
arrivedMechanicMechanic has arrived”Mechanic has arrived”
in_progressMechanicWork has startedShow live line items
completedMechanicWork finished, final price setShow payment screen
paidSystem (webhook)Payment captured successfullyShow receipt
cancelledCustomer/MechanicJob cancelledShow cancellation
no_mechanic_foundSystemNo mechanic available in any tier”No mechanics available”

Creating a Job

curl -X POST https://mechzie-api-production.run.app/api/v1/jobs \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "service_category_id": "uuid-of-category",
    "pickup_address": "MG Road, Bangalore, Karnataka",
    "pickup_lat": 12.9716,
    "pickup_lng": 77.5946,
    "vehicle_id": "uuid-of-vehicle",
    "description": "Engine not starting, battery might be dead",
    "photo_urls": ["https://s3.../photo1.jpg"]
  }'
Required fields: service_category_id, pickup_address, pickup_lat, pickup_lng Optional fields: vehicle_id, description, photo_urls
If the customer has unpaid cancellation fees, job creation returns 402 PAYMENT_REQUIRED. The customer must pay the fee first via POST /payments/create-order.

Dispatch System

After job creation, the system automatically dispatches to nearby mechanics in expanding tiers:
TierSearch RadiusTimeoutMax Mechanics Contacted
13 km30 seconds20
27 km30 seconds20
315 km45 seconds30
How it works:
  1. System finds available, verified mechanics within Tier 1 radius
  2. Sends job:offer Socket.io event to each mechanic
  3. First mechanic to call POST /jobs/{id}/accept wins (others get job:taken)
  4. If no one accepts within the timeout, expands to Tier 2, then Tier 3
  5. If all tiers exhaust → status becomes no_mechanic_found
The customer sees the job status change from pendingdispatching almost immediately. They receive job:status events via Socket.io as the state changes. Show a loading/searching animation during dispatching.

Mechanic Actions (State Transitions)

Each transition is a simple POST:
# Accept the job (mechanic)
POST /api/v1/jobs/{id}/accept

# Start driving to customer
POST /api/v1/jobs/{id}/en-route

# Arrived at location
POST /api/v1/jobs/{id}/arrive

# Start working
POST /api/v1/jobs/{id}/start

# Finish the job
POST /api/v1/jobs/{id}/complete

# Decline the job (during dispatch)
POST /api/v1/jobs/{id}/decline
All require Authorization: Bearer ACCESS_TOKEN. Invalid transitions return 409 INVALID_TRANSITION.

Line Items (Parts & Labor)

Mechanics can add charges during arrived or in_progress status:
curl -X POST https://mechzie-api-production.run.app/api/v1/jobs/{id}/line-items \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Spark plug (NGK BKR6E)",
    "quantity": 2,
    "unit_price": 15000,
    "type": "part"
  }'
FieldTypeValues
descriptionstringFree text
quantityinteger1+
unit_pricenumberIn paisa (₹150 = 15000)
typestringpart, labor, or other
When completed, final_price = base_price + SUM(quantity × unit_price for all line items). The customer receives a job:line-item-added Socket.io event in real-time.

Cancellation Rules

curl -X PATCH https://mechzie-api-production.run.app/api/v1/jobs/{id}/cancel \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cancel_reason": "Found alternative help"
  }'

Fee Schedule

Cancel from statusFeeWho can cancel
pendingFreeCustomer
dispatchingFreeCustomer
acceptedFreeCustomer or Mechanic
en_route₹50 (5000 paisa)Customer or Mechanic
arrived₹50 (5000 paisa)Customer or Mechanic
in_progress₹50 (5000 paisa)Customer or Mechanic
When a cancellation fee is charged, the customer cannot create new jobs until they pay it. Check for outstanding fees: GET /api/v1/payments/unpaid-fees.

Checking Unpaid Fees

GET /api/v1/payments/unpaid-fees
Authorization: Bearer ACCESS_TOKEN
Response:
{
  "hasFees": true,
  "amount": 5000
}

Listing Jobs

GET /api/v1/jobs?page=1&limit=20&status=completed
Authorization: Bearer ACCESS_TOKEN
Response:
{
  "data": [...],
  "page": 1,
  "limit": 20,
  "total": 42
}
Filter by status: pending, dispatching, accepted, en_route, arrived, in_progress, completed, paid, cancelled, no_mechanic_found.

Frontend Integration Summary

Customer App Flow

  1. Create job → Show searching animation
  2. Listen for job:status → Update UI based on status
  3. On accepted → Show mechanic info, start tracking
  4. job:join → Join job room for location updates
  5. Listen for location:updated → Animate map marker + show ETA
  6. Listen for job:line-item-added → Show added parts/labor
  7. On completed → Show final price, open payment flow
  8. On paid → Show receipt, prompt for rating

Mechanic App Flow

  1. Listen for job:offer → Show accept/decline dialog (with timer)
  2. On job:taken → Dismiss dialog if another mechanic accepted
  3. Accept → Navigate to job detail, start sending location:update
  4. Transition through statesen-routearrivestartcomplete
  5. Add line items during arrived/in_progress
  6. On paid → Show completion, prompt for rating