Skip to main content

Call Center Setup Guide

This guide walks you through setting up a fully functional call center using the Semaswift Voice API.

Overview​

A typical call center setup involves:

  1. Creating agents (call center operators)
  2. Setting up queues (routing rules)
  3. Configuring DIDs (phone numbers), optionally with sticky routing for returning callers
  4. Defining business hours
  5. Setting up IVR menus

Prerequisites​

  • Semaswift account with Voice module enabled
  • Admin or Supervisor role
  • At least one DID (phone number) provisioned

Step 1: Create Agents​

Agents are users who handle calls. Create agents with their queue assignments:

POST /api/v2/voice/agents
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"user_id": "usr_123456",
"extension": "1001",
"queues": ["queue_support", "queue_sales"],
"max_concurrent_calls": 2,
"wrap_up_time": 30
}

Step 2: Configure Queues​

Queues define how calls are routed to agents:

POST /api/v2/voice/queues
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"name": "Support Queue",
"strategy": "round_robin",
"timeout": 30,
"max_wait_time": 300,
"music_on_hold": "default",
"announce_position": true,
"announce_hold_time": true
}

Queue Strategies​

StrategyDescription
round_robinDistribute evenly among available agents
least_recentRoute to agent who hasn't taken a call longest
fewest_callsRoute to agent with fewest calls today
randomRandom available agent
ring_allRing all available agents

Step 3: Assign DIDs​

Connect phone numbers to queues:

POST /api/v2/voice/dids
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"number": "+1-555-123-4567",
"destination_type": "queue",
"destination_id": "queue_support",
"fallback_destination": "voicemail"
}

Route returning callers to their agent (optional)​

Outbound teams often reach a customer's voicemail, and the customer calls straight back. With sticky routing, a customer who missed an agent's call is connected to that agent instead of the first free agent in the queue.

Enable it per DID:

PATCH /api/v1/voice/dids/{id}
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"stickyRouting": {
"enabled": true,
"lookbackHours": 24,
"ringSeconds": 15,
"fallbackQueueId": 12,
"announcementSoundId": 41,
"fallbackSoundId": 42
}
}
FieldDefaultDescription
enabledfalseTurns sticky routing on for this DID
lookbackHours24How far back to look for a missed outbound call (1–168)
ringSeconds15How long the agent's phone rings before falling back (5–60)
fallbackQueueId—Queue for callers whose agent is unavailable or does not answer. Required when enabled
announcementSoundIdnoneOptional sound played before ringing the agent, e.g. "Connecting you to the agent who called you"
fallbackSoundIdnoneOptional sound played before transferring to the fallback queue

The queue and sounds must belong to your organization. Upload sounds through the Voice sounds API first.

How a call is routed. Business hours are checked first, so a closed line still plays its out-of-hours message. Otherwise Semaswift finds the most recent outbound call to the caller's number within lookbackHours. Only that call counts, and only if the customer did not pick it up (no answer, busy or cancelled):

Most recent outbound callWhat happens
Placed by an agent who is availableThe agent's phone rings for ringSeconds. If they don't answer, the caller goes to fallbackQueueId
Placed by an agent who is offline, paused, on another call or in wrap-upStraight to fallbackQueueId, without ringing
Placed by a campaign with no agent attached (progressive, predictive, power, robocall)The campaign's queue, or fallbackQueueId if the campaign has none
Answered by the customer, or no outbound call in the windowThe DID's normal destination (IVR, queue or agent)

Sticky routing never blocks a call. If it can't decide, for example because the caller ID is withheld, the call follows the DID's normal destination.

Checking the outcome. Each routed call's call log records the result under metadata.sticky_routing:

{
"sticky_routing": {
"matched_call_log_id": 98123,
"outcome": "connected"
}
}

outcome is one of connected (the agent answered), no_answer (the agent was rung but didn't answer, so the call went to the queue), agent_unavailable or campaign_queue.

Preview campaign calls are dialled by the agent, so they count as that agent's calls.

To turn sticky routing off, send "stickyRouting": {"enabled": false}.

Step 4: Configure Business Hours​

Set when your call center is open:

POST /api/v2/voice/business-hours
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"name": "Standard Hours",
"timezone": "America/New_York",
"schedule": {
"monday": {"open": "09:00", "close": "17:00"},
"tuesday": {"open": "09:00", "close": "17:00"},
"wednesday": {"open": "09:00", "close": "17:00"},
"thursday": {"open": "09:00", "close": "17:00"},
"friday": {"open": "09:00", "close": "17:00"},
"saturday": null,
"sunday": null
},
"closed_message": "We are currently closed. Our hours are Monday-Friday 9AM-5PM EST."
}

Step 5: Set Up IVR (Optional)​

Create an interactive voice menu:

POST /api/v2/voice/ivr
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
"name": "Main Menu",
"greeting": "Welcome to Acme Support. Press 1 for Sales, 2 for Support, or 0 for an operator.",
"options": [
{"digit": "1", "destination_type": "queue", "destination_id": "queue_sales"},
{"digit": "2", "destination_type": "queue", "destination_id": "queue_support"},
{"digit": "0", "destination_type": "extension", "destination_id": "1001"}
],
"timeout_destination": "queue_support",
"invalid_destination": "replay"
}

Testing Your Setup​

  1. Check agent status: Agents should show as "available"
  2. Test inbound call: Call your DID and verify routing
  3. Monitor queue: Watch real-time queue statistics
  4. Review CDRs: Check call detail records for issues

Real-Time Monitoring​

Connect to WebSocket for live updates:

const ws = new WebSocket('wss://realtime.semaswift.africa/connection/websocket');

ws.onopen = () => {
ws.send(JSON.stringify({
subscribe: {
channel: 'voice:queue_support'
}
}));
};

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Queue update:', data);
};

Next Steps​

  • Agent Management - Detailed agent operations
  • Configure call recordings in the Voice API settings
  • Generate call reports through the Voice API