AVR Core includes an optional HTTP web service that enables call initialization, metadata propagation, and dynamic Speech-to-Speech (STS) routing.
When enabled, the HTTP server runs alongside the AudioSocket TCP server and does not alter the classic AVR execution model.
The HTTP Web Service allows avr-core to:
If the HTTP service is disabled, AVR Core continues to operate exclusively as an AudioSocket server, preserving full backward compatibility.
The HTTP server is enabled by setting the HTTP_PORT environment variable.
| Variable | Description | Required |
|---|---|---|
HTTP_PORT |
Port used to expose the HTTP service | No |
PORT |
AudioSocket TCP port | Yes (default: 5001) |
HTTP_PORT=6001
PORT=5001
[INFO]: AVR HTTP Server listening on port 6001
[INFO]: AVR AudioSocket Server listening on port 5001
GET /healthBasic health check endpoint.
Response
200 OK{ "status": "ok" }
POST /callCall initialization endpoint, typically invoked from the Asterisk dialplan using the CURL() function.
This endpoint is responsible for:
{
"uuid": "935652e3-7c59-4edc-b17f-9646a9c2a265",
"payload": {
"from": "2000",
"to": "5001",
"uniqueid": "1770758888.32",
"channel": "PJSIP/2000-00000013"
}
}
| Field | Description |
|---|---|
uuid |
Unique identifier correlating HTTP, AudioSocket, and STS |
payload |
Free-form object containing call metadata |
All key/value pairs inside payload:
call_initiated webhookUpon receiving POST /call, AVR Core performs the following steps:
Starting from STS_URL, AVR Core appends all payload fields as query parameters.
Example:
STS_URL = ws://localhost:6030
becomes:
ws://localhost:6030/?from=2000&to=5001&uniqueid=1770758888.32&channel=...
call_initiated)If WEBHOOK_URL is configured, AVR Core sends an HTTP webhook with:
type = call_initiatedpayload received from /callIf the webhook HTTP response contains a sts_url field:
STS_URL is overriddenThis mechanism enables fully dynamic STS routing.
Note
STS_URLmust still be configured, as it acts as a base and fallback value.
{
"sts_url": "ws://localhost:6030/?from=2000&to=5001&uniqueid=1770758888.32&channel=PJSIP%2F2000-00000013",
"override": false
}
| Field | Description |
|---|---|
sts_url |
Final STS WebSocket URL used for the call |
override |
true if provided by webhook, false if locally derived |
The following example:
POST /call with call metadataexten => 5001,1,Answer()
same => n,Ringing()
same => n,Wait(1)
same => n,Set(UUID=${SHELL(uuidgen | tr -d '\n')})
same => n,Set(JSON_BODY={"uuid":"${UUID}","payload":{"from":"${CALLERID(num)}","to":"${EXTEN}","uniqueid":"${UNIQUEID}","channel":"${CHANNEL}"}})
same => n,Set(CURLOPT(httpheader)=Content-Type: application/json)
same => n,Set(JSON_RESPONSE=${CURL(http://avr-core:6001/call,${JSON_BODY})})
same => n,NoOp(JSON_BODY: ${JSON_BODY})
same => n,NoOp(JSON_RESPONSE: ${JSON_RESPONSE})
same => n,Set(DENOISE(rx)=on)
same => n,Dial(AudioSocket/avr-core:5001/${UUID})
same => n,Hangup()
http://avr-core:6001 → http://<avr-core-host>:<HTTP_PORT>AudioSocket/avr-core:5001 → AudioSocket/<avr-core-host>:<PORT>When STS_URL uses ws:// or wss://, AVR Core connects via WebSocket and passes metadata as query parameters.
ws://localhost:6030/?from=2000&to=5001&uniqueid=1770758888.32&channel=PJSIP%2F2000-00000013
[INFO]: Connecting to STS WebSocket: ws://localhost:6030/?from=2000&to=5001&uniqueid=1770758888.32&channel=PJSIP%2F2000-00000013
wss.on("connection", (clientWs, request) => {
const url = new URL(request.url, `http://${request.headers.host}`);
const from = url.searchParams.get("from");
const to = url.searchParams.get("to");
const uniqueid = url.searchParams.get("uniqueid");
const channel = url.searchParams.get("channel");
console.log({ from, to, uniqueid, channel });
});
call_initiated{
"uuid": "935652e3-7c59-4edc-b17f-9646a9c2a265",
"type": "call_initiated",
"timestamp": "2026-01-01T12:00:00.000Z",
"payload": {
"from": "2000",
"to": "5001",
"uniqueid": "1770758888.32",
"channel": "PJSIP/2000-00000013"
}
}
If the webhook responds with:
{
"sts_url": "ws://localhost:6030?uuid=935652e3-7c59-4edc-b17f-9646a9c2a265"
}
AVR Core will use that URL for the current call.
const express = require("express");
const app = express();
app.use(express.json());
app.post("/events", (req, res) => {
if (req.body.type === "call_initiated") {
return res.json({
sts_url: `ws://localhost:6030?uuid=${req.body.uuid}`,
});
}
res.sendStatus(200);
});
app.listen(process.env.PORT || 9000);
[INFO]: Webhook response received: {"sts_url":"ws://localhost:6030?uuid=..."}
[INFO]: Overriding STS URL: ws://localhost:6030?uuid=...
Dynamic STS routing allows you to:
use a single AVR Core instance with multiple STS backends
route calls based on:
from)to)correlate AVR events with Asterisk CDRs via:
uniqueidchannelThe HTTP endpoints do not provide built-in authentication.
It is strongly recommended to: