API reference

Install DotSIP, open the web admin, connect real SIP, and decide each call from your own HTTP API.

Two HTTP contracts matter in production. Both are JSON POST requests from the DotSIP machine to an endpoint you run. Both use User-Agent: DotSIP-Route/1, Accept: application/json, and Content-Type: application/json; charset=utf-8. The body is at most 65536 bytes. Status 400 or higher fails the exchange.

Route request

Sent to the route selected for this call. The default id is route-tools. An extension outbound route or a SIP channel inbound route is used when that row exists. The request also includes dialed, route, and caller.groups. See Routes.

{
  "format": "dotsip.route",
  "format_version": 1,
  "direction": "inbound",
  "call_id": "string",
  "sip_account": { "id": "string", "name": "string" },
  "sip_phone": null,
  "dialed": "string or null",
  "route": "route-tools",
  "caller": {
    "number": "string or null",
    "name": "string or null",
    "rights": null,
    "groups": []
  }
}

Route result

actionRequired fieldsWhat happens
answeroptional agentPicks up. An agent starts only when agent is set. Optional rights, user, prompt.
transferphoneTransfers to that extension on this machine.
hangupnoneRejects the call. Do not send error on a deliberate hangup.
{
  "format": "dotsip.route-result",
  "format_version": 1,
  "action": "answer",
  "agent": "agent-main",
  "rights": "right-1"
}

Tool call

Sent after the agent’s tool router selects a tool that is on the agent and allowed by the call right.

{
  "format": "dotsip.tool-call",
  "format_version": 1,
  "call_id": "string",
  "tool": "lookup-order",
  "arguments": {},
  "caller": { "number": "string or null", "name": "string or null", "rights": "right-1" }
}
{
  "ok": true,
  "result": {},
  "prompt": "optional instruction for the rest of this call"
}

ok true is success. Missing ok is not ok. rights on this body is ignored. prompt and agent are applied as on Tools.

Route endpoint

PHP, Python, and Node.js answer with the same agent.

<?php
header("Content-Type: application/json");
$body = json_decode(file_get_contents("php://input"), true);
if (!is_array($body) || (isset($body["format"]) ? $body["format"] : "") !== "dotsip.route") {
    http_response_code(400);
    echo json_encode(array("error" => "bad request"));
    return;
}
echo json_encode(array(
    "format" => "dotsip.route-result",
    "format_version" => 1,
    "action" => "answer",
    "agent" => "agent-main",
    "rights" => "right-1",
));

Order of a call

  1. A SIP call arrives on an account.
  2. DotSIP POSTs dotsip.route to the selected route. The default is route-tools.
  3. Your result is one action, or a commands list. One action is answer, transfer, or hangup. A command list can also play a recording, wait, collect digits, or call a webhook. See Recordings and DTMF.
  4. On answer with an agent, OpenAI Live starts with that agent’s live model and the API key stored on that model.
  5. Tools are the intersection of the agent’s tools and the rights ID.
  6. Each model tool call is a POST of dotsip.tool-call.
  7. A tool result may include prompt and agent. A rights field on that result is ignored.