Dispatch optimization and automated follow-up for field-service shops. Circuit takes a day's worth of jobs and a crew of technicians and works out who goes where, in what order — then writes the customer messages the shop keeps meaning to send.
Urgent work first, then oldest first. Each job goes to the eligible technician it adds the least drive time to, which also builds a nearest-neighbour route for that tech's day. A tech is only eligible if:
Deterministic and keyless — same input, same routes, every time. That makes it auditable, and it means a heavier solver can slot in later without changing a single caller.
Completing a job schedules the messages that actually drive repeat revenue — a review request the next day, and a maintenance reminder on the right cadence for the trade:
Circuit drafts and schedules. Sending is a channel adapter you point at your own email or SMS provider — the software never messages your customers on its own.
/optimize is open and stateless — it routes a
crew and returns the plan without storing anything.
curl -s https://circuit.forthecommongood.ai/optimize \
-H 'content-type: application/json' -d '{
"technicians": [
{ "tech_id": "t1", "name": "Ana", "skills": ["hvac"], "home_lat": 39.74, "home_lon": -104.99 },
{ "tech_id": "t2", "name": "Beau", "skills": ["hvac","plumbing"], "home_lat": 39.68, "home_lon": -105.08 }
],
"jobs": [
{ "job_id": "j1", "service_type": "hvac", "lat": 39.75, "lon": -105.00, "priority": 1 },
{ "job_id": "j2", "service_type": "plumbing", "lat": 39.69, "lon": -105.07 },
{ "job_id": "j3", "service_type": "hvac", "lat": 39.73, "lon": -104.97 }
]
}'
Returns each tech's ordered stops with travel and service minutes, their day totals, and any job that couldn't be placed.
POST /optimizeroute a crew, statelessGET /jobs?status=the job boardGET /techniciansthe crewGET /followupsthe scheduled message queuePOST /jobsbook work · keyPOST /dispatchroute the board + save · keyPOST /jobs/{id}/completeclose out + spawn follow-ups · key