Skip to main content

Field Services

Voice for dispatch-driven businesses — HVAC, plumbing, electrical, pest control, security, vehicle rental, etc.

Why it matters

  • Every missed call is a lost job. Route to the right dispatcher instantly, fall back to AI when nobody's free.
  • Click-to-Call velocity — dispatchers return leads from inside your scheduler, not their personal phones.
  • Activity Logging — every call written to the job record for audit and coaching.
  • On-call rotations — dial plans that change by hour-of-day and on-call roster.

Pattern: business-hour routing with AI overflow

Dial plan that does this

await ds.dialPlans.create(
{
name: 'Main dispatch line',
entry_node: 'hours',
nodes: [
{
id: 'hours',
type: 'schedule',
config: { schedule_id: 'sch_business_hours', open: 'ring_dispatch', closed: 'ai_intake' },
},
{
id: 'ring_dispatch',
type: 'ring_all_users',
config: { timeout: 25, next: 'ai_intake' },
},
{
id: 'ai_intake',
type: 'internal_dial',
config: { target_id: 'va_dispatch_ai' },
},
],
},
{ dialstackAccount: account.id }
);

The AI Voice App fires a webhook to your on-call rotation system when it captures an after-hours job. Full Voice App setup: Voice Apps.

Pattern: dispatcher click-to-call from the job screen

Give dispatchers a button on every job card that dials the customer. Alice's own endpoints ring first, then DialStack dials the customer and bridges the audio.

import { useDialstack } from '@dialstack/sdk/react';

function JobCard({ job, dispatcher }) {
const { api } = useDialstack();

return (
<button
onClick={() =>
api.calls.create({
from: dispatcher.id,
to: job.customer_phone,
})
}
>
Call {job.customer_name}
</button>
);
}

Full behavior (ring-all endpoints, dial string formats, errors): Click-to-Call.

Pattern: log every call to the job record

if (event.type === 'call.end') {
const job = await db.jobs.findOne({ customer_phone: event.data.from_number });
if (job) {
await db.jobActivity.insert({
job_id: job.id,
call_id: event.data.call_id,
user_id: event.data.user_id,
direction: event.data.direction,
duration: event.data.duration_seconds,
status: event.data.status,
ended_at: event.data.ended_at,
});
}
}

Full event surface: Activity Logging.

Build this with DialStack