Quickstart
This quickstart walks the full inbound path: a caller dials your number, the routing brain resolves it to a call flow, the flow checks business hours and offers the caller to a queue, and an available agent is bridged.
Every step below is a real call against the public /v1 API, authenticated with an API key (x-api-key: sk_…).
Before you start
Section titled “Before you start”You’ll want:
- An account (your tenant). Multi-tenant and white-label accounts are described in Multi-Tenant & White-Label.
- An API key with the
schedules,queues,users,flows, andnumbersscopes (or*). See Authentication. - A SIP domain for your account (the realm used for device authentication).
- At least one DID (inbound number) pointed at your account, or provision one in step 5 below.
The path we’re building
Section titled “The path we’re building”Caller → DID (number) → Call Flow ├─ timeCondition (business hours) │ ├─ in_hours → enqueue (Support queue) │ └─ out_of_hours → voicemail └─ queue → available agent (bridged)-
Create a business-hours schedule.
Terminal window curl -X POST https://api.sip.io/v1/schedules \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{"name": "Support hours", "timezone": "America/New_York","rules": [{ "kind": "weekly", "dow": 1, "start_time": "09:00", "end_time": "17:00" },{ "kind": "weekly", "dow": 2, "start_time": "09:00", "end_time": "17:00" },{ "kind": "weekly", "dow": 3, "start_time": "09:00", "end_time": "17:00" },{ "kind": "weekly", "dow": 4, "start_time": "09:00", "end_time": "17:00" },{ "kind": "weekly", "dow": 5, "start_time": "09:00", "end_time": "17:00" },{ "kind": "date", "start_date": "2026-07-04", "is_closed": 1 }]}'# → { "ok": true, "id": "sch_…" }dowis0–6(Sun–Sat). Rules replace as a full set on every write. See Business Hours for overnight intervals, date ranges, and holiday fallback. -
Create a queue.
Terminal window curl -X POST https://api.sip.io/v1/queues \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{"name": "Support", "strategy": "longest_idle","agent_ring_timeout_sec": 20, "max_wait_sec": 600, "wrap_up_sec": 10,"announce_position": 1, "moh_mode": "stream","schedule_id": "sch_…","timeout_dest_kind": "voicemail", "timeout_dest_id": "vm_…"}'# → { "ok": true, "id": "q_…" }See Queues & ACD for strategies, tiers, and the reserve/confirm fence.
-
Create an agent and add them to the queue.
Terminal window curl -X POST https://api.sip.io/v1/users \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{ "username": "1001", "display_name": "Dana", "is_agent": 1 }'# → { "ok": true, "id": "us_…" }curl -X POST https://api.sip.io/v1/queues/q_…/members \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{ "user_id": "us_…", "tier_level": 1, "mode": "static" }' -
Register a device for the agent.
Terminal window curl -X POST https://api.sip.io/v1/devices \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{ "user_id": "us_…", "auth_username": "1001", "password": "a-strong-password", "transport": "tls" }'# → { "ok": true, "id": "dev_…" }The password is hashed to
ha1on the way in and never stored or returned in the clear. Point any softphone at your SIP domain with1001/ the password you set. See Authentication. -
Build and publish the call flow.
The flow is a JSON node-graph. This one checks hours, then offers an IVR that enqueues to Support, falling back to voicemail after hours.
Terminal window curl -X POST https://api.sip.io/v1/flows \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{"name": "Support line", "publish": true,"graph": {"start": "hours","nodes": [{ "id": "hours", "type": "timeCondition", "data": { "kind": "timeCondition", "scheduleId": "sch_…" } },{ "id": "welcome", "type": "menu", "data": { "kind": "menu", "promptText": "Press 1 for support", "maxDigits": 1, "timeoutSec": 5 } },{ "id": "supQ", "type": "enqueue", "data": { "kind": "enqueue", "queueId": "q_…" } },{ "id": "vm", "type": "voicemail", "data": { "kind": "voicemail", "mailboxId": "vm_…" } }],"edges": [{ "id": "e1", "source": "hours", "target": "welcome", "sourceHandle": "in_hours" },{ "id": "e2", "source": "hours", "target": "vm", "sourceHandle": "out_of_hours" },{ "id": "e3", "source": "welcome", "target": "supQ", "sourceHandle": "digit:1" },{ "id": "e4", "source": "welcome", "target": "vm", "sourceHandle": "timeout" }]}}'# → { "ok": true, "id": "flow_…", "version": 1 }publish: trueis lint-gated: a broken graph returns422with the specific errors instead of going live. See Call Flows. -
Point your number at the flow.
Terminal window curl -X POST https://api.sip.io/v1/numbers \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{ "e164": "12025550123", "dest_kind": "flow", "dest_id": "flow_…", "max_channels": 10 }'Already have the DID provisioned?
PATCH /v1/numbers/{id}instead. See Numbers & Extensions. -
Bring the agent online.
Terminal window curl -X POST https://api.sip.io/v1/agents/state \-H 'x-api-key: sk_…' -H 'content-type: application/json' \-d '{ "userId": "us_…", "event": "available", "queues": [{ "queueId": "q_…", "level": 1 }] }'See Agents & Presence.
-
Call your number.
- In hours: the caller hears the menu, presses
1, joins the Support queue with hold music and position announcements, and is bridged to Dana when she’s free. - After hours / on a holiday: the
timeConditionroutes straight to voicemail.
- In hours: the caller hears the menu, presses
What just happened
Section titled “What just happened”- the SIP signaling layer received the INVITE and asked the edge runtime
/routewhat to do. /routematched the DID, ran admission control (CAC), and returned aflowdirective.- the media engine ran the flow via the
/flowcommand loop, driven step-by-step by a per-call CallSessionEngine. - The
timeConditionnode resolved against your schedule, theenqueuenode handed the caller to the per-account PresenceEngine (the ACD brain), and the reserve→confirm→release fence bridged the agent.
Next: read Core Concepts, or jump into the guides.