sautikit
PricingDevelopersBlogAbout
Sign inStart building

Run a call center without the platform: inbound queues and outbound dialling

Build an inbound queue and outbound dialler for a call center using Dial, Conference, and voice-action webhooks.

use-casecall-centerdialconferencerouting

Next Steps

  • DialDialAction connects the caller to one or more numbers/SIP endpoints. Number/SIP URIs are subject to the same destination authorisation as POST /v1/calls. URL must be on the allow-list when dialling
  • ConferenceConferenceAction places the caller into a named conference room. Field set tracks the live PBX webhooks docs (Conference verb) at https://webrtc.helloduty.com/admin#docs:webhooks and the canonical
  • GetDigitsGetDigitsAction collects DTMF from the caller, optionally with a nested `<Say>` / `<Play>` prompt. Mirrors the PBX `<GetDigits>` verb.
  • CallsEvery phone call in Sautikit is a call record with a direction (inbound or outbound), a sequence of lifecycle states, and an optional recording. Cost is debited at hangup based on answered duration.
sautikit

Programmable voice infrastructure for Africa. Buy numbers, place calls, and bill per second, all in KES, via API.

Product

NumbersCalls & routingRecordingsWallet & billingPricing

Developers

DocumentationAPI referenceQuickstartAI promptChangelog

Company

AboutBlogCareersConsole

© 2026 Sautikit. All rights reserved.

Sautikit provides voice API services for application developers. Numbers provisioned on this platform are not configured for emergency calling (e.g. 999 / 112). Do not use Sautikit numbers as a replacement for a primary phone line.

Summary

A call center on Sautikit is a combination of inbound call routing and outbound dialling, both controlled by voice-action webhooks. For inbound calls, your webhook receives the call, checks agent availability, and either dials an agent directly or drops the caller into a hold conference room until an agent is ready. For outbound calls, your server initiates a POST /v1/calls and uses a webhook to connect the answered call to an agent. No proprietary call center platform is required; the logic lives in your application.

Who this is for

  • Companies building or replacing a call center software layer on top of programmable telephony.
  • Development teams that need to integrate call routing with an existing CRM or ticketing system.
  • Startups that want a lightweight inbound queue and callback flow without a full contact center platform.
  • Teams building outbound dialling campaigns for sales, collections, or appointment reminders.

How it works

Inbound queue

Inbound queue flow
Inbound call center queue flowCustomer dials → routing webhook → check agent availability. If agent free: dial agent directly. If no agent: hold in conference room. Agent joins → both talk.Customer dials Sautikit numberPOST to routing webhookCheck agent availabilityAgent available?yes →Dial agent directly→ noHold in ConferencestartOnEnter: falseAgent + Customer talking
If no agent is available, the customer waits in a named conference hold room. When an agent frees up, your server dials them out and joins them to the same room.

Outbound campaign

Outbound call flow
Outbound call flowPOST /v1/calls/originate → platform dials remote party → POSTs to voice_callback_url on each step → call.hangup with wallet debit.POST /v1/calls/originate{ "to": "+254722000001", "from": "+254700000001", "voice_callback_url": "…" }Platform dials the remote partyPOST {voice_callback_url} on each stepcall.hangup → cost debited from wallet

Agent SIP endpoints

Agents can be reached via SIP URI (sip:agent@yourpbx.example.com) or ordinary phone numbers. Using SIP avoids per-minute costs on agent-side minutes if your agents use a softphone on the same SIP trunk.

API surface

Endpoints you call:

  • POST /v1/calls: place an outbound call (to contact or to agent).
  • GET /v1/calls/{call_sid}: retrieve call metadata, duration, and status.
  • GET /v1/calls: list calls for reporting and queue dashboards.

Voice actions used:

  • Say: queue position announcements, hold messages.
  • Play: hold music audio file.
  • Dial: connect caller to an agent's number or SIP URI.
  • Conference: hold queue and agent bridge room.
  • GetDigits: optional IVR pre-routing (department selection).
  • Redirect: re-route a call while it is in progress.
  • Hangup: end the call, update your CRM status.

Example

Inbound routing webhook

import express from "express";
import { findAvailableAgent, enqueueCall, dequeueCall } from "./agent-store";
 
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
 
// Sautikit calls this when a customer dials your number
app.post("/calls/inbound", async (req, res) => {
  const callId = req.body.CallId;
  const agent = await findAvailableAgent();
 
  if (agent) {
    // Agent is free: dial directly
    agent.markBusy();
    return res.json({
      actions: [
        { say: { text: "Connecting you to an agent." } },
        {
          dial: {
            number: agent.phoneNumber,
            callerId: req.body.To,
            timeout: 30,
          },
        },
      ],
    });
  }
 
  // No agent: put caller in a named hold conference
  await enqueueCall(callId);
  return res.json({
    actions: [
      { say: { text: "All agents are currently with other customers. Please hold." } },
      {
        conference: {
          name: `queue-${callId}`,
          startOnEnter: false,
          waitUrl: "https://yourapp.example.com/hold-music",
          statusEventsCallbackUrl: "https://yourapp.example.com/calls/queue-events",
          statusEvents: "join leave end",
          endOnExit: true,
        },
      },
    ],
  });
});
 
// Your background queue worker calls this when an agent becomes available
app.post("/calls/connect-agent", async (req, res) => {
  const { customerCallId, agentNumber } = req.body;
 
  // Dial the agent; when they answer, join the customer's conference
  const agentCallResponse = await fetch("https://api.sautikit.com/v1/calls", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SAUTIKIT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: agentNumber,
      from: process.env.SAUTIKIT_NUMBER,
      action_url: `https://yourapp.example.com/calls/agent-join?queue=${customerCallId}`,
    }),
  });
 
  res.json({ ok: true });
});
 
// When the agent answers, join the customer's hold conference
app.post("/calls/agent-join", (req, res) => {
  const customerCallId = req.query.queue;
  return res.json({
    actions: [
      {
        conference: {
          name: `queue-${customerCallId}`,
          startOnEnter: true,
          endOnExit: true,
          beep: false,
        },
      },
    ],
  });
});
 
app.listen(3000);

Place an outbound campaign call

curl -X POST "https://api.sautikit.com/v1/calls" \
  -H "Authorization: Bearer $SAUTIKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to":         "+254711222333",
    "from":       "+254700000001",
    "action_url": "https://yourapp.example.com/calls/outbound-answer",
    "status_url": "https://yourapp.example.com/calls/outbound-status"
  }'

Pricing notes

A call center workload involves multiple call legs per interaction:

  • Inbound customer leg: billed per minute from answer to hangup.
  • Outbound agent dial leg: each Dial or POST /v1/calls to an agent number is a separate outbound call billed at the destination rate.
  • Conference hold time: the inbound leg continues to accrue per-minute billing while the caller sits in a hold conference waiting for an agent. Keep hold times short to control cost.

Agents reached via SIP (sip: URIs to your own PBX or softphone) are billed at the SIP termination rate rather than the mobile/landline termination rate, which is typically lower for on-premises deployments.

For outbound campaigns, factor in answer rates. Only answered calls proceed to the action_url and get connected to an agent. Unanswered calls (no-answer, busy) are billed only for the ring duration, typically 20–40 seconds.

Next steps

  • Dial voice action reference: caller ID, timeout, and SIP dialling.
  • Conference voice action reference: hold queue setup, statusEvents.
  • Conference calling use case: multi-party bridges.
  • Calls concept: call lifecycle and SID references.
  • IVR use case: add a department-selection menu before routing.