Overview

Asterisk ARI (Asterisk REST Interface) allows you to connect Peachdesk AI voice agents to your existing Asterisk PBX. ARI provides a WebSocket-based event model for controlling calls via Stasis applications, giving Peachdesk full control over call flow and audio streaming. This guide focuses on the Peachdesk-specific configuration. For general Asterisk installation and administration, refer to the official Asterisk documentation.

Prerequisites

Before setting up the ARI integration, ensure you have:
  • A running Asterisk instance — 20.18.0, 22.8.0 or 23.2.0 or later
  • ARI module enabled in Asterisk
  • chan_websocket (WebSocket channel driver) enabled in your Asterisk build
  • Network connectivity between your Peachdesk instance and Asterisk
  • Peachdesk AI instance running and accessible
If you compiled Asterisk from source, ensure chan_websocket is included during the build. This module is required for external media streaming between Asterisk and Peachdesk. Refer to the Asterisk build system documentation for details on enabling modules.
The version floor is set by transport_data, not by chan_websocket. The channel driver arrived in 20.15.0 / 21.10.0 / 22.5.0, but Peachdesk passes per-call routing parameters through the transport_data option, which arrived in 20.18.0 / 22.8.0 / 23.2.0. An older Asterisk ignores it, so the media socket opens with no routing parameters and Peachdesk closes it — the call connects and stays silent.

Asterisk Configuration

The following Asterisk configuration files need to be set up to work with Peachdesk. These are minimal examples focused on the Peachdesk integration — refer to the Asterisk documentation for full configuration details.

Enable ARI (ari.conf)

Create an ARI user that Peachdesk will use to authenticate:
The username (section name, e.g., peachdesk) and password here must match the Stasis App Name and App Password you configure in Peachdesk.

Enable the HTTP Server (http.conf)

ARI requires the Asterisk HTTP server to be enabled:

Configure the Stasis Dialplan (extensions.conf)

Route incoming calls to your Stasis application so Peachdesk can handle them:
Replace peachdesk with the app name you configured in ari.conf and in Peachdesk.

Configure External Media Streaming (websocket_client.conf)

Peachdesk uses Asterisk’s external media streaming to send and receive audio over WebSocket. Configure a WebSocket client connection that points to your Peachdesk instance:
The section name (e.g., peachdesk) is the WebSocket Client Name you’ll enter in the Peachdesk telephony configuration. This name tells Asterisk which WebSocket connection to use for external media streaming during calls.
protocols must be media. Peachdesk accepts the media socket with the media subprotocol, and Asterisk’s WebSocket client rejects any response protocol that is not in its own configured list — so any other value fails the handshake and the call connects with no audio. Use wss:// and tls_enabled = yes when Peachdesk is behind TLS termination, and leave the URI without a query string: Peachdesk appends the per-call routing parameters itself.
Refer to the Asterisk WebSocket documentation for additional websocket_client.conf options and TLS configuration.

Configuration in Peachdesk

Step 1: Navigate to Telephony Settings

  1. Navigate to /telephony-configurations and click Add configuration
  2. Select Asterisk ARI as your provider

Step 2: Enter Your ARI Credentials

Configure the following fields:

Step 3: Save and Add Extensions

  1. Click Save Configuration
  2. Open the configuration you just created and add each SIP extension that should be reachable as a phone number (e.g. 8000). For inbound, you’ll assign a workflow to each extension separately — see Inbound Calling below.
  3. Create a test workflow and initiate a test call to verify the connection.

Inbound Calling

Unlike other telephony providers that use HTTP webhooks for inbound calls, ARI delivers inbound calls as StasisStart events on the ARI WebSocket. Peachdesk automatically detects these events and activates the workflow assigned to the called extension.

How It Works

  1. An external call arrives at Asterisk and the dialplan routes it to Stasis(peachdesk)
  2. Asterisk fires a StasisStart event over the ARI WebSocket with the channel in Ring state and the dialed extension in the dialplan context
  3. Peachdesk looks up the called extension in your telephony configuration’s phone numbers, finds the assigned workflow, validates quota, and creates a workflow run
  4. The call is answered, bridged to an external media channel, and your voice agent workflow begins
Workflow assignment is per extension, so different extensions on the same Asterisk can route to different agents. The same mechanism carries PSTN calls arriving over a SIP trunk — the DID takes the place of the extension. See SIP trunks for the trunk-specific dialplan and number handling.

Setting Up Inbound Calls

Step 1: Configure the Asterisk dialplan Ensure your dialplan routes the extensions you care about into the Stasis application. Either route a specific extension:
…or use a pattern that catches every extension you’ll register in Peachdesk:
Replace peachdesk with the app name you configured in ari.conf and in Peachdesk. Step 2: Add the extension as a phone number in Peachdesk
  1. Go to /telephony-configurations and open your Asterisk ARI configuration
  2. In the Phone numbers section, add a phone number whose address is the SIP extension (e.g. 8000)
  3. Set its Inbound workflow to the agent that should answer
  4. Save
    Adding the extension in Peachdesk doesn’t change Asterisk’s dialplan — that’s what Step 1 is for. The Peachdesk entry tells the StasisStart handler which workflow to run when a call to that extension reaches the Stasis app.
Repeat Step 2 for each extension that should reach a voice agent. Step 3: Test an inbound call Place a call to one of the extensions you configured. You should see the assigned workflow activate and the voice agent respond.

Inbound Call Context

When an inbound call activates a workflow, the following context is available to your workflow:

SIP Trunks (Bridgei2p)

Everything above assumes the numbers you dial are endpoints registered on your own Asterisk. To reach the PSTN you need a SIP trunk, and Asterisk — not Peachdesk — is the SIP stack that talks to it. Peachdesk drives the trunk through the same ARI configuration you set up above. This section uses Bridgei2p as the worked example, because it is a digest-authenticated registration trunk with no REST API, no webhooks and no media streaming of its own — the plainest possible case. Any other registration-based trunk follows the same shape; only the host, credentials and DID format change.

What changes when a trunk is involved

Step 1: Register the trunk (pjsip.conf)

Bridgei2p authenticates with a SIP username and password (digest auth) against cloudflo.bridgei2p.com, which resolves to 20.193.182.13. You need five PJSIP objects: a transport, an auth, a registration, an AOR, an endpoint, and an identify so inbound calls from the carrier’s IP are matched to that endpoint.
Reload and confirm the registration before going further:
The endpoint section name — bridgei2p here — is the value you enter as SIP Trunk Endpoint in Peachdesk. They must match exactly.
Pin match to the carrier’s signalling IP and firewall port 5060 plus your RTP range to it. An identify that matches too broadly lets anyone who can reach your Asterisk present calls as the trunk.

Step 2: Route inbound DIDs into Stasis (extensions.conf)

Inbound calls land in the endpoint’s context. Peachdesk matches the called number against the phone numbers you registered, comparing them in E.164 form, so normalise the DID in the dialplan before handing the call over. That way the DID is stored once, canonically, whatever shape the carrier happens to signal.
Replace peachdesk with your Stasis app name, and 91 with your country’s dial code. Watch a live call to see what the carrier actually sends you:

Step 3: Point Peachdesk at the trunk

  1. Open your Asterisk ARI configuration at /telephony-configurations
  2. Set SIP Trunk Endpoint to the PJSIP endpoint name (bridgei2p)
  3. Set Outbound Number Format to the digit shape the trunk accepts (see the table below)
  4. Set Trunk Country (ISO-2) if — and only if — you chose national or national_zero
  5. Save
Outbound calls then originate as PJSIP/<number>@bridgei2p instead of PJSIP/<number>. Leaving SIP Trunk Endpoint empty preserves the original behaviour exactly, so an existing ARI deployment that dials local extensions is unaffected. Outbound Number Format decides what digits reach the trunk. Using +91 98765 43210 as the example: Two details worth knowing:
  • A dial target that already names a channel technology (PJSIP/6001, SIP/6001, PJSIP/123@othertrunk) is passed through untouched — the trunk and format settings never rewrite it. Internal extensions keep working alongside the trunk.
  • national and national_zero strip the country dial code only when what remains is still a full-length national number, so a 10-digit Indian mobile that happens to begin 91 is left intact.

Step 4: Register each DID in Peachdesk

The dialplan gets the call into Stasis; the Peachdesk phone-number row decides which agent answers it.
  1. Open your ARI configuration and go to Phone numbers
  2. Add one row per DID, with the address in E.164 form: +918043071383
  3. Set its Inbound workflow
  4. If you also place outbound calls, mark the DID as the default caller ID so it is presented on the trunk
Repeat per DID. A DID with no Inbound workflow assigned is hung up on arrival, and so is a DID that reaches Stasis without a matching row — check the Peachdesk logs for no matching phone number registered for config when that happens.
Store DIDs in E.164 and normalise in the dialplan (Step 2), not the other way round. If you instead store the DID in the carrier’s raw shape, inbound routing only works while the carrier keeps signalling that exact shape — a carrier-side change silently stops routing every inbound call.
Bridgei2p authenticates the trunk, not the individual DID, so the caller ID you present on outbound has to be a number the carrier has assigned you. from_user on the endpoint (Step 1) forces the SIP From user to your trunk account, which is what most registration trunks require.

Before you commit to this

Three constraints are worth knowing before a production cutover rather than during one.
Asterisk must be built with chan_websocket. Peachdesk streams call audio over an external-media WebSocket, and chan_websocket is not in the distribution packages (apt install asterisk) and not in a stock FreePBX image. You need Asterisk 21 or later built from source with the module enabled. Verify with asterisk -rx "module show like chan_websocket" before anything else — if it is missing, calls connect and then have no audio.
Credential rotation on Bridgei2p is a manual runbook. Trunks cannot be deleted from the portal, and passwords are rotated by raising a support ticket rather than self-service. Plan a maintenance window: request the new password, update bridgei2p-auth in pjsip.conf, run asterisk -rx "pjsip reload", and confirm pjsip show registrations reads Registered again. Calls in flight during the reload are unaffected, but new calls fail while the registration is down. Keep the old password until the new registration is confirmed.
Per-call carrier cost is not available. Bridgei2p exposes no CDR or pricing API, and neither does Asterisk, so Peachdesk cannot ask what a call cost. Calls placed over ARI are estimated at the TELEPHONY_FALLBACK_USD_PER_MIN rate (a backend environment variable, default 0.0063) for their connected duration and stamped telephony_cost_source = configured_rate — honest about being an estimate, but only as accurate as the rate you set. Set it to your actual Bridgei2p per-minute rate in USD. Left at 0, telephony cost reads as an unmeasured $0 and every ARI call looks more profitable than it is.

Trunk troubleshooting

  • asterisk -rx "pjsip show registrations" — a Rejected state with 401/403 means the username or password is wrong; the trunk is digest-authenticated and the username is case-sensitive
  • Confirm your Asterisk’s public IP is the one Bridgei2p has allow-listed for the account
  • asterisk -rx "pjsip set logger on" and watch the REGISTER/response exchange
  • Check outbound UDP 5060 is not blocked by a cloud security group
  • The SIP Trunk Endpoint in Peachdesk must exactly match the type = endpoint section name in pjsip.conf
  • With the field empty, Peachdesk dials PJSIP/<number>, which only works for endpoints registered on your own Asterisk — that is the symptom that means the field was never set
  • asterisk -rx "pjsip show endpoint bridgei2p" to confirm the endpoint exists and is Not in use rather than Unavailable
  • Almost always the digit format. Turn on pjsip set logger on, place a call, and read the INVITE request URI
  • Try each Outbound Number Format value in turn — e164, strip_plus, national, national_zero
  • A 403 on an otherwise correct number usually means the caller ID you presented is not a number the carrier has assigned to your account
  • asterisk -rvvv during a live inbound call — the NoOp in your trunk context prints the exact DID Asterisk received
  • If nothing prints, the identify section is not matching the carrier’s IP, so the call is not landing in from-bridgei2p at all
  • If it prints but no agent answers, the DID reaching Stasis and the address stored in Peachdesk disagree — the dialplan rewrite in Step 2 is what reconciles them
  • Peachdesk logs no matching phone number registered for config for exactly this case

Troubleshooting

  • Verify the ARI endpoint URL is correct and reachable from your Peachdesk instance
  • Check that the Asterisk HTTP server is running (http.conf has enabled = yes)
  • Ensure firewall rules allow traffic on the ARI port (default: 8088)
  • Confirm the ARI module is loaded: run module show like res_ari in the Asterisk CLI
  • Verify the Stasis App Name matches the ARI user section name in ari.conf
  • Check the App Password matches the password in ari.conf
  • Ensure there are no extra spaces in the credentials
  • Verify chan_websocket is loaded: run module show like chan_websocket in the Asterisk CLI
  • Check that websocket_client.conf is correctly configured with the right Peachdesk URI
  • Ensure the WebSocket Client Name in Peachdesk matches the section name in websocket_client.conf
  • Verify network connectivity and firewall rules allow WebSocket traffic between Asterisk and Peachdesk
  • Ensure the dialplan routes calls to Stasis(your_app_name)
  • Verify the app name in the dialplan matches the ARI user in ari.conf
  • Check Asterisk CLI for errors: asterisk -rvvv
  • Confirm the ARI WebSocket connection is active
  • Verify the called extension is added as a phone number under your ARI configuration in /telephony-configurations and has an Inbound workflow assigned
  • Confirm the workflow exists and belongs to the same organization as the ARI config
  • Check that your organization has available quota
  • Review Peachdesk logs for warnings like “no matching phone number registered for config” or “has no inbound_workflow_id assigned”
  • Check the URI in websocket_client.conf points to the correct Peachdesk host and port
  • Verify the Peachdesk instance is running and accepting WebSocket connections
  • If using TLS, ensure certificates are correctly configured on both sides

Best Practices

  • Keep your Asterisk instance on the same network or a low-latency connection to Peachdesk for optimal audio quality
  • Use strong passwords for ARI authentication
  • Restrict ARI access to known IP addresses using firewall rules
  • Monitor Asterisk logs alongside Peachdesk logs when debugging call issues
  • Keep Asterisk updated to the latest stable version for security and compatibility

Further Reading