curl --request POST \
--url https://api.goyappr.com/calls \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "phone",
"to": "+972501234567",
"from": "+972551234567",
"variables": {
"LeadName": "David Cohen",
"OrderNumber": "ORD-1234"
},
"metadata": {
"appointment_id": "ghl-apt-abc123",
"calendar_id": "ghl-cal-xyz789",
"contact_id": "ghl-contact-def456"
},
"allowed_origins": [
"https://app.example.com"
]
}
'import requests
url = "https://api.goyappr.com/calls"
payload = {
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "phone",
"to": "+972501234567",
"from": "+972551234567",
"variables": {
"LeadName": "David Cohen",
"OrderNumber": "ORD-1234"
},
"metadata": {
"appointment_id": "ghl-apt-abc123",
"calendar_id": "ghl-cal-xyz789",
"contact_id": "ghl-contact-def456"
},
"allowed_origins": ["https://app.example.com"]
}
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({
agent_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
type: 'phone',
to: '+972501234567',
from: '+972551234567',
variables: {LeadName: 'David Cohen', OrderNumber: 'ORD-1234'},
metadata: {
appointment_id: 'ghl-apt-abc123',
calendar_id: 'ghl-cal-xyz789',
contact_id: 'ghl-contact-def456'
},
allowed_origins: ['https://app.example.com']
})
};
fetch('https://api.goyappr.com/calls', 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/calls",
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([
'agent_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'type' => 'phone',
'to' => '+972501234567',
'from' => '+972551234567',
'variables' => [
'LeadName' => 'David Cohen',
'OrderNumber' => 'ORD-1234'
],
'metadata' => [
'appointment_id' => 'ghl-apt-abc123',
'calendar_id' => 'ghl-cal-xyz789',
'contact_id' => 'ghl-contact-def456'
],
'allowed_origins' => [
'https://app.example.com'
]
]),
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/calls"
payload := strings.NewReader("{\n \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\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/calls")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/calls")
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 \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"call_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "dnc_blocked",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"message": "<string>",
"dnc_reason": "<string>",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z"
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "<string>",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"created_at": "2023-11-07T05:31:56Z"
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"queue_position": 123,
"queued_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"message": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Create Outbound Call
Place an outbound phone call using a Yappr agent (default), or — with type: "web" — mint a short-lived browser session token for an in-browser voice call via the @goyappr/client SDK. A phone call requires $3+ balance and an active Yappr phone number; if server capacity is fully utilized it is queued automatically and returns HTTP 202. A web session does not place a call and is not queued — it returns a token the visitor’s browser uses to connect.
curl --request POST \
--url https://api.goyappr.com/calls \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "phone",
"to": "+972501234567",
"from": "+972551234567",
"variables": {
"LeadName": "David Cohen",
"OrderNumber": "ORD-1234"
},
"metadata": {
"appointment_id": "ghl-apt-abc123",
"calendar_id": "ghl-cal-xyz789",
"contact_id": "ghl-contact-def456"
},
"allowed_origins": [
"https://app.example.com"
]
}
'import requests
url = "https://api.goyappr.com/calls"
payload = {
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "phone",
"to": "+972501234567",
"from": "+972551234567",
"variables": {
"LeadName": "David Cohen",
"OrderNumber": "ORD-1234"
},
"metadata": {
"appointment_id": "ghl-apt-abc123",
"calendar_id": "ghl-cal-xyz789",
"contact_id": "ghl-contact-def456"
},
"allowed_origins": ["https://app.example.com"]
}
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({
agent_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
type: 'phone',
to: '+972501234567',
from: '+972551234567',
variables: {LeadName: 'David Cohen', OrderNumber: 'ORD-1234'},
metadata: {
appointment_id: 'ghl-apt-abc123',
calendar_id: 'ghl-cal-xyz789',
contact_id: 'ghl-contact-def456'
},
allowed_origins: ['https://app.example.com']
})
};
fetch('https://api.goyappr.com/calls', 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/calls",
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([
'agent_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'type' => 'phone',
'to' => '+972501234567',
'from' => '+972551234567',
'variables' => [
'LeadName' => 'David Cohen',
'OrderNumber' => 'ORD-1234'
],
'metadata' => [
'appointment_id' => 'ghl-apt-abc123',
'calendar_id' => 'ghl-cal-xyz789',
'contact_id' => 'ghl-contact-def456'
],
'allowed_origins' => [
'https://app.example.com'
]
]),
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/calls"
payload := strings.NewReader("{\n \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\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/calls")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/calls")
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 \"agent_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"type\": \"phone\",\n \"to\": \"+972501234567\",\n \"from\": \"+972551234567\",\n \"variables\": {\n \"LeadName\": \"David Cohen\",\n \"OrderNumber\": \"ORD-1234\"\n },\n \"metadata\": {\n \"appointment_id\": \"ghl-apt-abc123\",\n \"calendar_id\": \"ghl-cal-xyz789\",\n \"contact_id\": \"ghl-contact-def456\"\n },\n \"allowed_origins\": [\n \"https://app.example.com\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"call_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "dnc_blocked",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"message": "<string>",
"dnc_reason": "<string>",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z"
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "<string>",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"created_at": "2023-11-07T05:31:56Z"
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"to": "<string>",
"from": "<string>",
"queue_position": 123,
"queued_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"message": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Authorizations
Your Yappr API key (e.g. ypr_live_...). Generate one in the dashboard under Settings → API Keys.
Body
Call channel. Omit or "phone" places a normal outbound phone call (requires to and from).
"web" mints a short-lived, single-use browser session token instead of dialing — no call is
placed until the visitor's browser connects via the @goyappr/client SDK. For "web", only
agent_id is used (to/from are ignored) and the 201 response is a session object.
phone, web Destination phone number in strict E.164 format.
Validation rules (enforced at API and DB layers):
- Must match
^\+[1-9][0-9]{7,14}$— leading+, 8–15 digits, no spaces or dashes. - Israeli numbers (
+972…) must be exactly 12 or 13 characters total (+972followed by an 8-digit landline or 9-digit mobile). - Must differ from
from.
Malformed numbers are rejected with 400 INVALID_TO_NUMBER — no row is written to the database, no carrier dial is attempted, and no capacity is consumed.
"+972501234567"
An active number in your workspace, in strict E.164 format: bought from Yappr, or registered from your own Telnyx account on a carrier account — then the call runs on your Telnyx account, which bills you for its phone minutes. Same validation rules as to. Malformed numbers are rejected with 400 INVALID_FROM_NUMBER.
"+972551234567"
Key-value pairs injected as template variables into the agent's system prompt (e.g. {{LeadName}}).
Show child attributes
Show child attributes
{
"LeadName": "David Cohen",
"OrderNumber": "ORD-1234"
}
Arbitrary key-value data attached to the call log record. Forwarded in real-time to every tool webhook as call_metadata so tool receivers (Make.com scenarios, n8n workflows, custom edge functions) can route updates back to the right CRM record without a secondary GET /calls/{id} fetch. Ideal for carrying IDs like appointment_id, contact_id, calendar_id. Not injected into the agent's system prompt.
Flow agents — contract callout. Flow agents can reference {{metadata.<key>}} tokens inside args_template values. Missing keys render to an empty string at runtime with no save-time or dispatch-time warning, so always check the agent's flow_config.metadata.custom_metadata_keys before placing the call and ensure every key in that array is supplied here.
Reserved keys. The five platform-supplied tokens (id, direction, agent_number, user_number, agent_name) are emitted by the platform at call start and cannot be overridden — using any of them as a key here is a 400 INVALID_METADATA_RESERVED_KEY. Pick a different name for your custom field.
{
"appointment_id": "ghl-apt-abc123",
"calendar_id": "ghl-cal-xyz789",
"contact_id": "ghl-contact-def456"
}
Web sessions only (type: web). Optional list of browser origins permitted to use the minted session (e.g. https://app.example.com).
["https://app.example.com"]
Response
Call blocked because the destination is on the company's Do-Not-Call list.
A call_logs row is recorded with status: "dnc_blocked" (so analytics +
webhooks pick it up), but no carrier leg is established and no minutes
are charged. To allow this number again, remove its DNC entry via
DELETE /do-not-call/{id}.