curl --request POST \
--url https://api.goyappr.com/sip-endpoints \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "After-hours",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"slug": "after-hours",
"allowed_source_ips": [
"203.0.113.0/24"
]
}
'import requests
url = "https://api.goyappr.com/sip-endpoints"
payload = {
"name": "After-hours",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"slug": "after-hours",
"allowed_source_ips": ["203.0.113.0/24"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'After-hours',
inbound_agent_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
slug: 'after-hours',
allowed_source_ips: ['203.0.113.0/24']
})
};
fetch('https://api.goyappr.com/sip-endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goyappr.com/sip-endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'After-hours',
'inbound_agent_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'slug' => 'after-hours',
'allowed_source_ips' => [
'203.0.113.0/24'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.goyappr.com/sip-endpoints"
payload := strings.NewReader("{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.goyappr.com/sip-endpoints")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/sip-endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "After-hours",
"slug": "after-hours-bz3r3mtypuwuw8tpdw3x392s",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"is_active": true,
"last_call_at": "2023-11-07T05:31:56Z",
"allowed_source_ips": [
"203.0.113.0/24"
],
"sip_uri": "sip:after-hours-bz3r3mtypuwuw8tpdw3x392s@yappr-byoc.sip.telnyx.com",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}Create SIP Endpoint
Create a new BYOC SIP endpoint. Returns a sip_uri that the customer
pastes into their own telephony platform — no authentication setup
required at the SIP layer. The slug (random 24-char suffix in the
URI) is the bearer credential.
Rate limit: 20 creates per company per day.
curl --request POST \
--url https://api.goyappr.com/sip-endpoints \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "After-hours",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"slug": "after-hours",
"allowed_source_ips": [
"203.0.113.0/24"
]
}
'import requests
url = "https://api.goyappr.com/sip-endpoints"
payload = {
"name": "After-hours",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"slug": "after-hours",
"allowed_source_ips": ["203.0.113.0/24"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'After-hours',
inbound_agent_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
slug: 'after-hours',
allowed_source_ips: ['203.0.113.0/24']
})
};
fetch('https://api.goyappr.com/sip-endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goyappr.com/sip-endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'After-hours',
'inbound_agent_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'slug' => 'after-hours',
'allowed_source_ips' => [
'203.0.113.0/24'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.goyappr.com/sip-endpoints"
payload := strings.NewReader("{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.goyappr.com/sip-endpoints")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/sip-endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"After-hours\",\n \"inbound_agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"slug\": \"after-hours\",\n \"allowed_source_ips\": [\n \"203.0.113.0/24\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "After-hours",
"slug": "after-hours-bz3r3mtypuwuw8tpdw3x392s",
"inbound_agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"is_active": true,
"last_call_at": "2023-11-07T05:31:56Z",
"allowed_source_ips": [
"203.0.113.0/24"
],
"sip_uri": "sip:after-hours-bz3r3mtypuwuw8tpdw3x392s@yappr-byoc.sip.telnyx.com",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}BYOC SIP — bring your own telephony, no SIP setup
A SIP endpoint lets you route inbound calls from your own telephony platform to a Yappr agent without buying a Yappr-managed phone number. Use it when you already have a business line and want unanswered or escalated calls to land on AI instead of voicemail. On create, the server generates a high-entropy slug (a 1–12 char prefix derived from yourname + a hyphen + 24 random characters ≈ 120 bits of
entropy) and returns the full URI. The slug is the bearer credential — it’s
the only thing protecting the endpoint from being dialed by strangers, so
treat the URI like an API key.
Hand the sip_uri to the customer. They paste it into their PBX or CPaaS
as the destination for the relevant route — no username or password, just
the URI string.
Configuration on the customer’s side
Three universal facts they’ll need:- URI — the value of
sip_urifrom the response, e.g.sip:after-hours-bz3r3mtypuwuw8tpdw3x392s@yappr-byoc.sip.telnyx.com - Authentication — none
- Transport — UDP/TCP/TLS all work; codecs G711/G722 supported
Caller-ID trust
For calls arriving via SIP endpoints, the calling-party number comes from whichever upstream system you point at us — and that upstream is under your control. By default Yappr does not use that number for lead-memory lookups or returning-caller recognition. If your upstream is trustworthy (e.g. you operate it directly), you can opt an agent in via the dashboard.Optional: source-IP allowlist
Passallowed_source_ips as a JSON array of CIDRs/IPs to restrict which
network sources can reach the endpoint. Useful when the customer’s PBX
has a fixed egress IP. Omit (or pass null) to accept from any source.
Rate limit
A company can create up to 20 SIP endpoints per day.Rotating access
There is no rotate-password endpoint — the slug itself is the secret. To rotate, delete the endpoint (the URI immediately returns 404) and create a new one with a fresh slug.Authorizations
Your Yappr API key (e.g. ypr_live_...). Generate one in the dashboard under Settings → API Keys.
Body
Human-readable label, shown in the dashboard.
"After-hours"
Agent that should answer calls routed to this endpoint.
Optional human-readable prefix (max 12 chars). Server
appends a hyphen and a 24-char random suffix to produce
the final slug. Lowercase letters/digits/single hyphens.
Auto-derived from name if omitted.
"after-hours"
Optional list of CIDRs/IPs that may dial this endpoint.
null (default) accepts any source.
Response
SIP endpoint created. Hand the sip_uri to the customer.
A BYOC SIP endpoint. Customers paste the returned sip_uri into their
own telephony system — calls dialed to that URI are routed to the
Yappr agent identified by inbound_agent_id. No authentication is
required at the SIP layer; the slug embedded in the URI is the
bearer credential.
Security model: the slug includes ~120 bits of entropy in its random suffix, so guessing is intractable. Treat the full URI like an API key — anyone with it can dial the agent. To revoke access, delete the endpoint (which makes the URI immediately return 404) and create a new one.
Optional defense in depth: set allowed_source_ips to restrict which
source IPs (or CIDRs) can reach the endpoint. Calls from any other
source are rejected pre-answer.
Show child attributes
Show child attributes