curl -X POST https://api.ringyo.ai/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"description": "Production webhook"
}'
const response = await fetch('https://api.ringyo.ai/v1/webhooks', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://your-app.com/webhooks/ringyo',
events: ['call.completed', 'call.recording.ready'],
description: 'Production webhook'
})
});
const webhook = await response.json();
// Save webhook.secret securely!
import requests
response = requests.post(
'https://api.ringyo.ai/v1/webhooks',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'url': 'https://your-app.com/webhooks/ringyo',
'events': ['call.completed', 'call.recording.ready'],
'description': 'Production webhook'
}
)
webhook = response.json()
# Save webhook['secret'] securely!
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0...",
"description": "Production webhook",
"status": "active",
"metadata": {},
"created_at": "2024-01-15T10:30:00Z"
}
{
"error": {
"code": "invalid_url",
"message": "Webhook URL must be HTTPS"
}
}
{
"error": {
"code": "webhook_limit_reached",
"message": "Maximum number of webhooks reached for your plan"
}
}
Webhooks
Create Webhook
Create a new webhook endpoint
POST
/
v1
/
webhooks
curl -X POST https://api.ringyo.ai/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"description": "Production webhook"
}'
const response = await fetch('https://api.ringyo.ai/v1/webhooks', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://your-app.com/webhooks/ringyo',
events: ['call.completed', 'call.recording.ready'],
description: 'Production webhook'
})
});
const webhook = await response.json();
// Save webhook.secret securely!
import requests
response = requests.post(
'https://api.ringyo.ai/v1/webhooks',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'url': 'https://your-app.com/webhooks/ringyo',
'events': ['call.completed', 'call.recording.ready'],
'description': 'Production webhook'
}
)
webhook = response.json()
# Save webhook['secret'] securely!
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0...",
"description": "Production webhook",
"status": "active",
"metadata": {},
"created_at": "2024-01-15T10:30:00Z"
}
{
"error": {
"code": "invalid_url",
"message": "Webhook URL must be HTTPS"
}
}
{
"error": {
"code": "webhook_limit_reached",
"message": "Maximum number of webhooks reached for your plan"
}
}
Request
Create a new webhook endpoint to receive real-time events from Ringyo AI.Headers
string
required
Bearer token for authentication. Format:
Bearer YOUR_API_KEYstring
required
Must be
application/jsonBody Parameters
string
required
The HTTPS URL to receive webhook events
array
required
Array of event types to subscribe to. Use
["*"] for all events.Available events:call.started- Call has been initiatedcall.ringing- Call is ringingcall.answered- Call was answeredcall.completed- Call ended successfullycall.failed- Call failedcall.recording.ready- Recording is availablecall.transcript.ready- Transcript is availableagent.created- New agent createdagent.updated- Agent was updatedagent.deleted- Agent was deleted
string
A secret key for signing webhook payloads. Auto-generated if not provided.
string
A description for this webhook endpoint
object
Custom key-value pairs for your reference
Response
string
Unique identifier for the webhook
string
The webhook URL
array
Subscribed event types
string
The webhook signing secret (only shown on creation)
string
Webhook status:
active, inactive, failingstring
ISO 8601 timestamp
curl -X POST https://api.ringyo.ai/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"description": "Production webhook"
}'
const response = await fetch('https://api.ringyo.ai/v1/webhooks', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://your-app.com/webhooks/ringyo',
events: ['call.completed', 'call.recording.ready'],
description: 'Production webhook'
})
});
const webhook = await response.json();
// Save webhook.secret securely!
import requests
response = requests.post(
'https://api.ringyo.ai/v1/webhooks',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'url': 'https://your-app.com/webhooks/ringyo',
'events': ['call.completed', 'call.recording.ready'],
'description': 'Production webhook'
}
)
webhook = response.json()
# Save webhook['secret'] securely!
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/ringyo",
"events": ["call.completed", "call.recording.ready"],
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0...",
"description": "Production webhook",
"status": "active",
"metadata": {},
"created_at": "2024-01-15T10:30:00Z"
}
{
"error": {
"code": "invalid_url",
"message": "Webhook URL must be HTTPS"
}
}
{
"error": {
"code": "webhook_limit_reached",
"message": "Maximum number of webhooks reached for your plan"
}
}
Verifying Webhooks
Use thesecret to verify incoming webhooks:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your webhook handler:
app.post('/webhooks/ringyo', (req, res) => {
const signature = req.headers['x-ringyo-signature'];
if (!verifyWebhook(JSON.stringify(req.body), signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
});
Error Codes
| Code | Description |
|---|---|
invalid_url | URL must be a valid HTTPS endpoint |
invalid_events | One or more event types are invalid |
webhook_limit_reached | Maximum webhooks for your plan |
url_unreachable | Could not reach the webhook URL |