Create Webhook
curl --request POST \
--url https://api.example.com/webhooks \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"events": [
{}
],
"name": "<string>",
"description": "<string>",
"companyId": "<string>",
"headers": [
{}
]
}
'import requests
url = "https://api.example.com/webhooks"
payload = {
"url": "<string>",
"events": [{}],
"name": "<string>",
"description": "<string>",
"companyId": "<string>",
"headers": [{}]
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: '<string>',
events: [{}],
name: '<string>',
description: '<string>',
companyId: '<string>',
headers: [{}]
})
};
fetch('https://api.example.com/webhooks', 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.example.com/webhooks",
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([
'url' => '<string>',
'events' => [
[
]
],
'name' => '<string>',
'description' => '<string>',
'companyId' => '<string>',
'headers' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"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.example.com/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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.example.com/webhooks")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"signingSecret": "<string>",
"url": "<string>",
"events": [
{}
],
"isActive": true
}Webhooks
Create Webhook
POST
/
webhooks
Create Webhook
curl --request POST \
--url https://api.example.com/webhooks \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"events": [
{}
],
"name": "<string>",
"description": "<string>",
"companyId": "<string>",
"headers": [
{}
]
}
'import requests
url = "https://api.example.com/webhooks"
payload = {
"url": "<string>",
"events": [{}],
"name": "<string>",
"description": "<string>",
"companyId": "<string>",
"headers": [{}]
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: '<string>',
events: [{}],
name: '<string>',
description: '<string>',
companyId: '<string>',
headers: [{}]
})
};
fetch('https://api.example.com/webhooks', 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.example.com/webhooks",
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([
'url' => '<string>',
'events' => [
[
]
],
'name' => '<string>',
'description' => '<string>',
'companyId' => '<string>',
'headers' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"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.example.com/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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.example.com/webhooks")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"companyId\": \"<string>\",\n \"headers\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"signingSecret": "<string>",
"url": "<string>",
"events": [
{}
],
"isActive": true
}Creates a new webhook configuration for receiving event notifications.
Overview
Create a webhook to receive real-time HTTP notifications when events occur in your InstaView account. The signing secret is returned only once during creation—store it securely.Authentication
string
required
Bearer token with
write:webhooks scopeRequest Body
string
required
The HTTPS endpoint URL to receive webhook notifications. Maximum 2048 characters.
array
required
Array of event type strings to subscribe to:
"ANALYSIS_COMPLETED"- Analysis finished successfully"ANALYSIS_FAILED"- Analysis processing failed"PING"- Test event for connectivity"CONVERSATION_COMPLETED"- The call finished and analysis is available"CONVERSATION_FAILED"- A technical failure prevented the call"CONVERSATION_STARTED"- A call attempt began"CONVERSATION_RESCHEDULED"- A follow-up call attempt has been scheduled"CONVERSATION_CANCELLED"- The conversation ended without completing"SOURCING_COMPLETED"- Sourcing run finished with scored candidates"SOURCING_FAILED"- Sourcing run terminated with an error"ENRICH_COMPLETED"- Enrichment run completed"ENRICH_FAILED"- Enrichment run terminated with an error
"INTERVIEW_COMPLETED" and siblings — which register exactly the same subscription. See
Event name vocabulary.string
Human-readable name for the webhook. Maximum 255 characters.
string
Description of what this webhook is used for.
string
Company ID to associate this webhook with. If omitted, webhook will receive events for all companies accessible by the API key. Useful for ATS integrations managing multiple companies with different subdomains.
array
Custom headers to include in webhook requests. Maximum 50 headers.Each header object:
name(string, required): Header name (1-255 characters)value(string, required): Header value (1-4096 characters)
Response
Returns the created webhook configuration with the signing secret.The
signingSecret is only returned once during creation. Store it securely
immediately. If you lose it, you must delete and recreate the webhook.string
Unique identifier for the webhook
string
HMAC signing secret for verifying webhook signatures (hex-encoded, 64 characters)
string
The endpoint URL
array
Array of subscribed event type labels
boolean
Whether the webhook is active (always
true for new webhooks)Example Request
curl -X POST https://api.instaview.sk/webhooks \
-H "Authorization: Bearer sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/webhooks/instaview",
"name": "Production Webhook",
"description": "Receives conversation completion notifications",
"events": ["CONVERSATION_COMPLETED", "ANALYSIS_COMPLETED"],
"headers": [
{ "name": "Authorization", "value": "Bearer your-internal-token" }
]
}'
const response = await fetch('https://api.instaview.sk/webhooks', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.INSTAVIEW_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://api.example.com/webhooks/instaview',
name: 'Production Webhook',
description: 'Receives conversation completion notifications',
events: ["CONVERSATION_COMPLETED", "ANALYSIS_COMPLETED"],
headers: [
{ name: 'Authorization', value: 'Bearer your-internal-token' }
]
})
});
const data = await response.json();
// IMPORTANT: Store this securely - only shown once!
console.log('Signing secret:', data.signingSecret);
response = requests.post(
'https://api.instaview.sk/webhooks',
headers={
'Authorization': f'Bearer {os.environ["INSTAVIEW_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'url': 'https://api.example.com/webhooks/instaview',
'name': 'Production Webhook',
'description': 'Receives conversation completion notifications',
'events': ["CONVERSATION_COMPLETED", "ANALYSIS_COMPLETED"],
'headers': [
{'name': 'Authorization', 'value': 'Bearer your-internal-token'}
]
}
)
data = response.json()
# IMPORTANT: Store this securely - only shown once!
print(f'Signing secret: {data["signingSecret"]}')
Example Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"apiKeyId": "api-key-uuid",
"companyId": "company-uuid",
"url": "https://api.example.com/webhooks/instaview",
"name": "Production Webhook",
"description": "Receives conversation completion notifications",
"headers": [
{
"name": "Authorization",
"isMasked": true
}
],
"events": [
"conversation.completed",
"analysis.completed"
],
"vocabulary": "NEUTRAL",
"isActive": true,
"maxRetries": 3,
"timeoutMs": 30000,
"consecutiveFailures": 0,
"circuitOpenedAt": null,
"signingSecret": "<64-character hex string — returned only here>",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
Error Responses
400 - Validation Error
400 - Validation Error
{
"statusCode": 400,
"message": "Validation failed",
"errors": ["url must be a valid URL"],
"traceId": "4b1f0c9d2e6a47f8b3c5d7e9a1b2c3d4"
}
403 - Insufficient Permissions
403 - Insufficient Permissions
{
"statusCode": 403,
"message": "Insufficient permissions. Required scopes: write:webhooks",
"traceId": "4b1f0c9d2e6a47f8b3c5d7e9a1b2c3d4",
"timestamp": "2026-08-03T10:30:00.000Z"
}
Best Practices
- Store the signing secret immediately - It’s only returned once
- Include the ping event for testing - You can remove it later
- Use HTTPS endpoints - HTTP is only allowed for localhost
- Add authentication headers - Protect your webhook endpoint
Related
Webhooks Guide
Learn about signature verification and payloads
Test Webhook
Test your webhook endpoint