Appearance
Webhooks API
Manage webhook endpoints for receiving real-time event notifications.
List Webhooks
http
GET /api/v1/webhooksResponse
json
{
"data": [
{
"id": "wh_123",
"url": "https://your-app.com/webhooks/converra",
"events": ["optimization.completed", "prompt.updated"],
"description": "Production webhook",
"status": "active",
"createdAt": "2025-01-15T10:00:00Z"
}
]
}Create Webhook
http
POST /api/v1/webhooksRequest Body
json
{
"url": "https://your-app.com/webhooks/converra",
"events": ["optimization.completed", "prompt.updated", "insights.generated"],
"description": "Production webhook"
}Required Fields
| Field | Type | Description |
|---|---|---|
url | string | HTTPS endpoint URL |
events | string[] | Events to subscribe to |
Optional Fields
| Field | Type | Description |
|---|---|---|
description | string | Human-readable description |
Response
json
{
"id": "wh_456",
"url": "https://your-app.com/webhooks/converra",
"events": ["optimization.completed", "prompt.updated", "insights.generated"],
"secret": "whsec_abc123...",
"status": "active",
"createdAt": "2025-01-20T14:30:00Z"
}Save Your Secret
The secret is only returned once at creation. Store it securely for signature verification.
Status: 201 Created
Delete Webhook
http
DELETE /api/v1/webhooks/:idResponse
json
{
"success": true,
"message": "Webhook deleted"
}Status: 200 OK
Available Events
| Event | Description | Payload |
|---|---|---|
prompt.updated | Prompt content changed | { promptId, promptName, updateType, variantId?, appliedAt } |
prompt.deleted | Prompt was deleted | { promptId, deletedAt } |
optimization.started | Optimization began | { optimizationId, promptId, status, settings, startedAt } |
optimization.completed | Optimization finished | { optimizationId, promptId, results, duration, completedAt } |
optimization.stopped | Optimization stopped manually | { optimizationId, promptId, reason, stoppedAt } |
insights.generated | New insights available | { conversationId, promptId, insightsId, summary, sentiment } |
conversation.created | New conversation logged | { conversationId, promptId, status, createdAt } |
Webhook Payload Format
All webhook payloads follow this structure:
json
{
"id": "evt_789",
"type": "optimization.completed",
"timestamp": "2025-01-20T14:30:00Z",
"data": {
"optimizationId": "opt_456",
"promptId": "prompt_123",
"results": {
"winner": "variant_2",
"improvementPercentage": 15.3
},
"duration": 847,
"completedAt": "2025-01-20T14:30:00Z"
}
}Signature Verification
All webhooks include an X-Converra-Signature header for verification.
Verification Process
- Get the raw request body (not parsed JSON)
- Compute HMAC-SHA256 using your webhook secret
- Compare with the signature header
Example (Node.js)
typescript
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Example (Express)
typescript
app.post('/webhooks/converra', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-converra-signature'] as string;
if (!verifyWebhook(req.body.toString(), signature, process.env.WEBHOOK_SECRET!)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body.toString());
// Handle event...
res.status(200).json({ received: true });
});Use Raw Body
Always use the raw request body for signature verification. Parsed JSON may have different formatting.
Retry Policy
Failed webhook deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts, the webhook is marked as failing and notifications are paused.
SDK Usage
typescript
// List webhooks
const webhooks = await converra.webhooks.list();
// Create webhook
const webhook = await converra.webhooks.create({
url: 'https://your-app.com/webhooks/converra',
events: ['optimization.completed', 'prompt.updated'],
description: 'Production webhook'
});
// Save the secret!
console.log('Webhook secret:', webhook.secret);
// Delete webhook
await converra.webhooks.delete('wh_123');Error Responses
Invalid URL
json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid webhook URL",
"details": {
"url": "Must be a valid HTTPS URL"
}
}
}Webhook Not Found
json
{
"error": {
"code": "NOT_FOUND",
"message": "Webhook not found"
}
}Related
- SDK Webhooks - SDK webhook handler utilities
- Settings - Account configuration
