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
| Status | Who triggers | Description | UI State |
|---|
pending | System | Job created, about to dispatch | ”Finding a mechanic…” |
dispatching | System | Actively searching for mechanics | ”Searching nearby mechanics…” |
accepted | Mechanic | A mechanic accepted the job | Show mechanic info |
en_route | Mechanic | Mechanic is driving to location | Show map + ETA |
arrived | Mechanic | Mechanic has arrived | ”Mechanic has arrived” |
in_progress | Mechanic | Work has started | Show live line items |
completed | Mechanic | Work finished, final price set | Show payment screen |
paid | System (webhook) | Payment captured successfully | Show receipt |
cancelled | Customer/Mechanic | Job cancelled | Show cancellation |
no_mechanic_found | System | No 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:
| Tier | Search Radius | Timeout | Max Mechanics Contacted |
|---|
| 1 | 3 km | 30 seconds | 20 |
| 2 | 7 km | 30 seconds | 20 |
| 3 | 15 km | 45 seconds | 30 |
How it works:
- System finds available, verified mechanics within Tier 1 radius
- Sends
job:offer Socket.io event to each mechanic
- First mechanic to call
POST /jobs/{id}/accept wins (others get job:taken)
- If no one accepts within the timeout, expands to Tier 2, then Tier 3
- If all tiers exhaust → status becomes
no_mechanic_found
The customer sees the job status change from pending → dispatching 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"
}'
| Field | Type | Values |
|---|
description | string | Free text |
quantity | integer | 1+ |
unit_price | number | In paisa (₹150 = 15000) |
type | string | part, 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 status | Fee | Who can cancel |
|---|
pending | Free | Customer |
dispatching | Free | Customer |
accepted | Free | Customer 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
- Create job → Show searching animation
- Listen for
job:status → Update UI based on status
- On
accepted → Show mechanic info, start tracking
job:join → Join job room for location updates
- Listen for
location:updated → Animate map marker + show ETA
- Listen for
job:line-item-added → Show added parts/labor
- On
completed → Show final price, open payment flow
- On
paid → Show receipt, prompt for rating
Mechanic App Flow
- Listen for
job:offer → Show accept/decline dialog (with timer)
- On
job:taken → Dismiss dialog if another mechanic accepted
- Accept → Navigate to job detail, start sending
location:update
- Transition through states →
en-route → arrive → start → complete
- Add line items during
arrived/in_progress
- On
paid → Show completion, prompt for rating