Create subscriptions
Create a delivery rule for one practice and one trigger type. A webhook subscription sends encrypted event notifications to an HTTPS endpoint that you control. Create separate subscriptions when you need different practices, triggers, or destinations.
The create response is the only response that includes secret_key. Store that key securely and associate it with the returned subscription id; your receiver uses both values to select the correct key and decrypt each delivery. If the key is lost or exposed, delete the subscription and create a replacement.
See the Webhooks and subscriptions guide for receiver headers, Fernet decryption, and the end-to-end workflow.
curl --request POST \
--url https://api.prod.peerlogic.com/api/subscriptions/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"trigger": {
"trigger_type": "missed_call"
}
}
'import requests
url = "https://api.prod.peerlogic.com/api/subscriptions/"
payload = {
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"trigger": { "trigger_type": "missed_call" }
}
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: 'Missed-call events',
description: 'Notify our integration when a call is missed',
destination: 'https://partner.example.com/webhooks/peerlogic',
practice_id: '<PRACTICE_ID>',
subscription_type: 'webhook',
trigger: {trigger_type: 'missed_call'}
})
};
fetch('https://api.prod.peerlogic.com/api/subscriptions/', 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.prod.peerlogic.com/api/subscriptions/",
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' => 'Missed-call events',
'description' => 'Notify our integration when a call is missed',
'destination' => 'https://partner.example.com/webhooks/peerlogic',
'practice_id' => '<PRACTICE_ID>',
'subscription_type' => 'webhook',
'trigger' => [
'trigger_type' => 'missed_call'
]
]),
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.prod.peerlogic.com/api/subscriptions/"
payload := strings.NewReader("{\n \"name\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\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.prod.peerlogic.com/api/subscriptions/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prod.peerlogic.com/api/subscriptions/")
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\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<SUBSCRIPTION_ID>",
"created_at": "2026-09-15T19:18:09Z",
"modified_at": "2026-09-15T19:18:09Z",
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"extra": null,
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"is_active": true,
"system_message": null,
"trigger": {
"trigger_type": "missed_call"
},
"secret_key": "<FERNET_SECRET_KEY>"
}{
"errors": [
{
"practice_id": "Invalid"
}
]
}{
"detail": "'Authorization' header is required"
}{
"message": "No permissions assigned to permit access to this endpoint."
}Authorizations
Bearer access token issued by Peerlogic.
Body
A customer-defined name for the subscription.
1 - 128The practice whose events produce deliveries.
1Use webhook to deliver events to an HTTPS endpoint.
webhook, email, sms, noop Condition that produces a delivery for this subscription.
Show child attributes
Show child attributes
A customer-defined description of the subscription.
255The HTTPS endpoint that receives webhook deliveries. Required when subscription_type is webhook.
1 - 255Optional customer-defined value for a webhook subscription.
255Response
The subscription was created. Webhook responses include a secret_key that is not returned by later read or list requests.
The Fernet key used to decrypt webhook request bodies. Returned only by this create response. Store it securely; it cannot be retrieved or changed later.
Customer-defined name used to identify the subscription.
1 - 128Practice whose activity is evaluated for this subscription.
1Delivery channel used by the subscription. Customer webhook integrations use webhook.
webhook, email, sms, noop Condition that produces a delivery for this subscription.
Show child attributes
Show child attributes
The unique subscription ID. Webhook deliveries include this value in X-Subscription-ID.
Whether the subscription can produce deliveries.
Time when the subscription was created.
Time when the subscription was last changed.
A delivery or verification status that may require attention.
Customer-defined explanation of the workflow this subscription supports.
255Delivery destination. Webhook destinations must be HTTPS URLs.
1 - 255Optional customer-defined value available for webhook subscriptions.
255Was this page helpful?
curl --request POST \
--url https://api.prod.peerlogic.com/api/subscriptions/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"trigger": {
"trigger_type": "missed_call"
}
}
'import requests
url = "https://api.prod.peerlogic.com/api/subscriptions/"
payload = {
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"trigger": { "trigger_type": "missed_call" }
}
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: 'Missed-call events',
description: 'Notify our integration when a call is missed',
destination: 'https://partner.example.com/webhooks/peerlogic',
practice_id: '<PRACTICE_ID>',
subscription_type: 'webhook',
trigger: {trigger_type: 'missed_call'}
})
};
fetch('https://api.prod.peerlogic.com/api/subscriptions/', 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.prod.peerlogic.com/api/subscriptions/",
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' => 'Missed-call events',
'description' => 'Notify our integration when a call is missed',
'destination' => 'https://partner.example.com/webhooks/peerlogic',
'practice_id' => '<PRACTICE_ID>',
'subscription_type' => 'webhook',
'trigger' => [
'trigger_type' => 'missed_call'
]
]),
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.prod.peerlogic.com/api/subscriptions/"
payload := strings.NewReader("{\n \"name\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\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.prod.peerlogic.com/api/subscriptions/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prod.peerlogic.com/api/subscriptions/")
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\": \"Missed-call events\",\n \"description\": \"Notify our integration when a call is missed\",\n \"destination\": \"https://partner.example.com/webhooks/peerlogic\",\n \"practice_id\": \"<PRACTICE_ID>\",\n \"subscription_type\": \"webhook\",\n \"trigger\": {\n \"trigger_type\": \"missed_call\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<SUBSCRIPTION_ID>",
"created_at": "2026-09-15T19:18:09Z",
"modified_at": "2026-09-15T19:18:09Z",
"name": "Missed-call events",
"description": "Notify our integration when a call is missed",
"destination": "https://partner.example.com/webhooks/peerlogic",
"extra": null,
"practice_id": "<PRACTICE_ID>",
"subscription_type": "webhook",
"is_active": true,
"system_message": null,
"trigger": {
"trigger_type": "missed_call"
},
"secret_key": "<FERNET_SECRET_KEY>"
}{
"errors": [
{
"practice_id": "Invalid"
}
]
}{
"detail": "'Authorization' header is required"
}{
"message": "No permissions assigned to permit access to this endpoint."
}