- JavaScript 70.3%
- Lua 29.7%
Adds a Node.js bridge server using Asterisk ARI for call origination, DTMF relay, and hangup control. Includes a WebSocket gateway for pushing live call events to Roblox, a REST API secured with API key + JWT session tokens, a Roblox Lua client module, an example door button script, and Asterisk ari.conf/extensions.conf templates. |
||
|---|---|---|
| asterisk | ||
| roblox | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
SIPBlox
SIPBlox connects an Asterisk PBX to Roblox so that real telephony and in-game logic can drive each other. A player presses a button in-game, Asterisk places a real call through a SIP trunk, and a relay on the other end opens a door. A call comes in on a real line, and Roblox can react to it live. It's the glue between a PBX and a game server.
Built for door relays, intercoms, in-game payphones, and anything else where "press a button in Roblox, something happens on a real phone line" is the goal.
Why SIPBlox exists
Roblox has no SIP or RTP stack, so it can never speak directly to a PBX. SIPBlox sits in between: Asterisk handles all the actual telephony over ARI (the Asterisk REST Interface), and Roblox talks to SIPBlox over plain HTTPS and WebSockets, which HttpService already supports. Roblox never needs to know anything about SIP, trunks, or codecs. It just calls an API.
How it fits together
Roblox game server --HTTPS--> SIPBlox API --ARI--> Asterisk --SIP trunk--> PSTN / relay hardware
<--WS------ live events <--------
- Roblox authenticates with SIPBlox using a shared API key and gets back a short-lived session token.
- Roblox calls
/api/call/originateto place a call through Asterisk, for example dialing into a door relay extension. - SIPBlox uses ARI to originate the channel, answer it, and track it for the lifetime of the call.
- Roblox can send DTMF tones, trigger a dedicated door relay shortcut, or hang up, all over plain HTTP.
- Every call event Asterisk fires (answered, DTMF received, hung up) gets pushed straight back to Roblox over a WebSocket, so the game can react in real time instead of polling.
What's in this repo
| Path | What it is |
|---|---|
src/server.js |
Entry point. Boots the HTTP server, connects to Asterisk over ARI, attaches the WebSocket gateway. |
src/ari.js |
All Asterisk call control: originate, send DTMF, hang up, the door relay shortcut, channel tracking. |
src/routes.js |
The REST API Roblox talks to. |
src/auth.js |
API key validation for Roblox and JWT session tokens for everything after that. |
src/wsGateway.js |
WebSocket endpoint that streams live call events to connected Roblox servers. |
roblox/SIPBlox.lua |
Drop-in ModuleScript for Roblox. Handles auth and wraps every API call. |
roblox/DoorButtonExample.server.lua |
Working example wiring a ClickDetector to originate a call and trigger a door relay. |
asterisk/ari.conf.example |
ARI user config for Asterisk. |
asterisk/extensions.conf.example |
Dialplan routing calls into the Stasis app SIPBlox listens on. |
.env.example |
Every environment variable SIPBlox needs, with safe placeholder values. |
Requirements
- Asterisk 18 or newer with ARI enabled
- Node.js 18 or newer
- A SIP trunk or PJSIP endpoint wired up to whatever relay or intercom hardware you're controlling
- A Roblox experience with
HttpServiceenabled and outbound HTTP requests allowed in game settings
Getting it running
1. Install dependencies
npm install
2. Configure environment variables
Copy .env.example to .env and fill it in with your own values — Asterisk ARI credentials, a Roblox API key you generate yourself, and a JWT secret.
cp .env.example .env
3. Wire up Asterisk
Drop the example configs into your Asterisk install, adjusting extensions, trunk names, and credentials to match your setup:
asterisk/ari.conf.example→/etc/asterisk/ari.confasterisk/extensions.conf.example→ merge into/etc/asterisk/extensions.conf
Then reload:
asterisk -rx "core reload"
4. Start SIPBlox
npm start
By default it listens on the port set in .env and immediately connects to Asterisk over ARI.
Wiring up Roblox
Place roblox/SIPBlox.lua in ReplicatedStorage as a ModuleScript named SIPBlox. Update BASE_URL and ROBLOX_KEY inside it to match your deployment.
local SIPBlox = require(game.ReplicatedStorage.SIPBlox)
local client = SIPBlox.new(tostring(player.UserId), tostring(game.PlaceId))
local result = client:originateCall("PJSIP/door_relay", "9001", "from-internal", player.Name)
client:openDoor(result.channelId)
task.wait(3)
client:hangup(result.channelId)
See roblox/DoorButtonExample.server.lua for a complete, working version of this wired to a ClickDetector.
API reference
| Method | Path | What it does |
|---|---|---|
POST |
/api/session |
Exchange a Roblox API key for a short-lived session token |
POST |
/api/call/originate |
Place a call out through Asterisk |
POST |
/api/call/:channelId/dtmf |
Send DTMF digits on an active call |
POST |
/api/call/:channelId/hangup |
Hang up an active call |
POST |
/api/door/:channelId/open |
Send the configured door relay DTMF tone |
GET |
/api/calls |
List currently active channel IDs |
WS |
/ws |
Live event feed: call started, call ended, DTMF received |
All endpoints except /api/session require a Bearer session token in the Authorization header.
Configuration reference
Every variable lives in .env.example. The ones worth knowing about:
ARI_URL,ARI_USERNAME,ARI_PASSWORD,ARI_APP— how SIPBlox connects to Asterisk's REST interfaceROBLOX_API_KEY— the shared secret Roblox uses to request a session tokenJWT_SECRET— signs the session tokens issued after thatDOOR_EXTENSION_CONTEXT— the dialplan context calls get originated intoDOOR_RELAY_DTMF— the digit sent when/api/door/:channelId/openis hitDEFAULT_TRUNK— your default outbound trunk name
Security notes
- Never commit
.env. It's already in.gitignore. - Run SIPBlox behind TLS in production — Roblox
HttpServicewill refuse plain HTTP. - Scope the dialplan context SIPBlox originates into so it can only reach the extensions and trunks it actually needs.
- Rotate
ROBLOX_API_KEYandJWT_SECRETif either ever leaks.
License
SIPBlox is licensed under the GNU General Public License v3.0. See LICENSE for the full text.