Webhook Configuration
Setting up webhooks, event types, payload examples
Webhooks
Configure webhooks to receive real-time notifications when events occur in Verk. Build event-driven integrations and automate workflows.
Overview
Webhooks send HTTP POST requests to your server when specific events happen:
- Task created, updated, or completed
- Project changes
- Member actions
- Comment activity
- File uploads
Use webhooks to:
- Sync data with external systems
- Trigger automation workflows
- Send notifications to other tools
- Update dashboards in real-time
Prerequisites
Requirements:
- Public HTTPS endpoint to receive webhooks
- API key with
webhooks:writepermission - Ability to verify webhook signatures
Plan availability:
- Free: 2 webhooks
- Pro: 50 webhooks
- Enterprise: Unlimited
Creating Webhooks
Via API
POST /webhooks
curl -X POST "https://api.verk.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhook",
"events": ["task.created", "task.updated"],
"secret": "your_webhook_secret_12345"
}'
Via Dashboard
- Navigate to Settings → Integrations → Webhooks
- Click "+ Create Webhook"
- Configure:
- URL: Your endpoint URL (must be HTTPS)
- Events: Select which events to receive
- Secret: Generate or provide signing secret
- Description: Optional notes
- Click "Create"
- Test webhook with sample payload
Event Types
Task Events
task.created
Triggered when a new task is created.
{
"event": "task.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "task_123",
"title": "Implement login feature",
"status": "todo",
"priority": "high",
"projectId": "proj_456",
"creatorId": "user_789",
"createdAt": "2024-01-15T10:30:00Z"
}
}
task.updated
Triggered when task is modified.
task.deleted
Triggered when task is deleted.
task.completed
Triggered when task status changes to "done".
Project Events
project.created
New project created.
project.updated
Project details modified.
project.deleted
Project deleted.
Member Events
member.added
User joined organization.
member.removed
User left or was removed.
member.role_changed
User role updated.
Comment Events
comment.created
New comment on task.
comment.updated
Comment edited.
comment.deleted
Comment removed.
File Events
file.uploaded
New file uploaded.
file.deleted
File deleted.
Webhook Payload
All webhooks follow this structure:
{
"event": "event.type",
"timestamp": "ISO8601 timestamp",
"webhookId": "webhook_123",
"deliveryId": "delivery_456",
"data": {
...event-specific data...
},
"organization": {
"id": "org_789",
"name": "Acme Inc"
}
}
Verifying Webhooks
Signature Verification
Verk signs all webhooks with your secret:
Header:
X-Verk-Signature: sha256=abc123...
Verify signature (Node.js):
const crypto = require('crypto')
function verifyWebhook(payload, signature, secret) {
const expectedSignature =
'sha256=' +
crypto.createHmac('sha256', secret).update(payload).digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)
}
// Express.js example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-verk-signature']
const payload = req.body.toString()
if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature')
}
// Process webhook...
res.status(200).send('OK')
})
Verify signature (Python):
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected = 'sha256=' + hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
Handling Webhooks
Responding to Webhooks
Requirements:
- Return
200 OKwithin 5 seconds - Process asynchronously if needed
- Don't perform long-running operations
Example handler:
app.post('/webhook', async (req, res) => {
// Verify signature first
if (!verifyWebhook(req.body, req.headers['x-verk-signature'])) {
return res.status(401).send('Unauthorized')
}
// Acknowledge receipt immediately
res.status(200).send('OK')
// Process asynchronously
processWebhookAsync(req.body)
})
async function processWebhookAsync(payload) {
const { event, data } = payload
switch (event) {
case 'task.created':
await handleTaskCreated(data)
break
case 'task.updated':
await handleTaskUpdated(data)
break
// ... other events
}
}
Retry Logic
Verk retry policy:
- Initial attempt: Immediate
- Retry 1: After 1 minute
- Retry 2: After 5 minutes
- Retry 3: After 15 minutes
- Retry 4: After 1 hour
- Retry 5: After 3 hours
- Retry 6: After 6 hours
Webhook disabled after:
- 6 failed attempts
- Manual re-enable required
- Check webhook logs for errors
Idempotency
Handle duplicate webhooks gracefully:
const processedDeliveries = new Set()
async function handleWebhook(payload) {
const { deliveryId } = payload
// Check if already processed
if (processedDeliveries.has(deliveryId)) {
console.log('Duplicate delivery, skipping')
return
}
// Process webhook
await processEvent(payload)
// Mark as processed
processedDeliveries.add(deliveryId)
}
Webhook Management
List Webhooks
curl -X GET "https://api.verk.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY"
Update Webhook
curl -X PATCH "https://api.verk.com/v1/webhooks/webhook_123" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["task.created", "task.completed"]
}'
Delete Webhook
curl -X DELETE "https://api.verk.com/v1/webhooks/webhook_123" \
-H "Authorization: Bearer YOUR_API_KEY"
Webhook Logs
View delivery history:
- Settings → Integrations → Webhooks
- Click webhook
- View "Delivery Log"
See:
- Timestamp
- Event type
- Response status
- Response time
- Retry attempts
Use Cases
Slack Notifications
Send task updates to Slack:
async function handleTaskCreated(task) {
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `New task created: ${task.title}`,
attachments: [
{
color: task.priority === 'high' ? 'danger' : 'good',
fields: [
{ title: 'Project', value: task.projectName },
{ title: 'Assignee', value: task.assigneeName },
{ title: 'Due Date', value: task.dueDate },
],
},
],
}),
})
}
Database Sync
Sync Verk tasks to your database:
async function syncTaskToDatabase(task) {
await db.tasks.upsert({
where: { verkId: task.id },
update: {
title: task.title,
status: task.status,
updatedAt: task.updatedAt,
},
create: {
verkId: task.id,
title: task.title,
status: task.status,
createdAt: task.createdAt,
},
})
}
Email Notifications
Send custom email notifications:
async function handleTaskAssigned(task) {
const assignee = await getUser(task.assigneeId)
await sendEmail({
to: assignee.email,
subject: `New task assigned: ${task.title}`,
body: `You've been assigned a new ${task.priority} priority task.`,
})
}
Troubleshooting
Webhook Not Receiving Events
Check:
- Webhook is active (not disabled)
- Events are selected
- URL is publicly accessible
- Firewall allows Verk IPs
- SSL certificate is valid
Test: Click "Send Test" in webhook settings to verify endpoint.
Webhook Disabled
Causes:
- 6 consecutive failures
- Endpoint returning errors
- Timeout (>5 seconds)
Fix:
- Review delivery logs
- Fix endpoint issues
- Re-enable webhook
- Monitor for success
Signature Verification Fails
Check:
- Using correct secret
- Comparing raw request body
- Using timing-safe comparison
- Secret hasn't been rotated
Best Practices
Verify Signatures Always verify webhook signatures to ensure authenticity.
Respond Quickly Return 200 OK within 5 seconds. Process asynchronously if needed.
Handle Duplicates
Use deliveryId to implement idempotency.
Monitor Failures Set up alerts for webhook failures.
Use HTTPS Always use HTTPS endpoints for security.
Rotate Secrets Change webhook secrets periodically (quarterly).
Log Everything Keep detailed logs of all webhook deliveries for debugging.
Graceful Degradation Have fallback mechanisms if webhooks fail.
Related Documentation
- API Reference - Complete API docs
- API Keys - Authentication
- SDK - Client libraries
- Customization - Advanced integration
Need webhook help? Contact developer support for assistance.