Webhooks
Create custom integrations with Elixion webhooks
Webhooks
Webhooks allow you to integrate Elixion with external systems by sending HTTP requests when events occur. Build custom integrations, trigger external workflows, and sync data.
Overview
How Webhooks Work
Event Occurs → Elixion → HTTP POST → Your Endpoint
↓
Issue Created → {"event": "issue.created", ...}
Status Changed → {"event": "issue.updated", ...}
Sprint Started → {"event": "sprint.started", ...}
Creating Webhooks
Basic Setup
- Navigate to Settings > Integrations > Webhooks
- Click + New Webhook
- Configure:
- Name
- URL
- Events
- Secret (optional)
- Save and test
Configuration
Webhook: Deploy Notifier
────────────────────────
URL: https://api.example.com/elixion-webhook
Method: POST
Content-Type: application/json
Authentication:
☑ Include secret header
Header: X-Webhook-Secret
Secret: ••••••••••••
Events:
☑ issue.created
☑ issue.updated
☐ issue.deleted
☑ sprint.started
☑ sprint.completed
☐ comment.created
Active: ✓ Yes
Events
Available Events
| Event | Trigger |
|-------|---------|
| issue.created | New issue created |
| issue.updated | Issue modified |
| issue.deleted | Issue deleted |
| issue.moved | Issue changed project |
| comment.created | New comment |
| sprint.started | Sprint begins |
| sprint.completed | Sprint ends |
| project.created | New project |
| user.joined | User joins team |
| deployment.completed | Deploy finished |
Event Filtering
Filter events by conditions:
events:
- event: issue.updated
filters:
- field: status
changed_to: Done
- field: priority
values: [Critical, High]
- event: issue.created
filters:
- field: project
values: [AUTH, CORE]
Payload Format
Standard Payload
{
"id": "evt_123456",
"event": "issue.updated",
"timestamp": "2024-01-15T10:30:00Z",
"workspace": {
"id": "ws_abc",
"name": "Engineering"
},
"data": {
"issue": {
"id": "issue_xyz",
"key": "AUTH-123",
"title": "Login validation",
"type": "Story",
"status": "Done",
"priority": "High",
"assignee": {
"id": "user_123",
"name": "Alice",
"email": "alice@example.com"
},
"project": {
"id": "proj_abc",
"key": "AUTH",
"name": "Authentication"
}
},
"changes": [
{
"field": "status",
"old_value": "In Progress",
"new_value": "Done"
}
],
"actor": {
"id": "user_456",
"name": "Bob"
}
}
}
Event-Specific Payloads
issue.created:
{
"event": "issue.created",
"data": {
"issue": { /* full issue object */ },
"actor": { /* who created it */ }
}
}
sprint.started:
{
"event": "sprint.started",
"data": {
"sprint": {
"id": "sprint_123",
"name": "Sprint 15",
"goal": "Complete authentication",
"start_date": "2024-01-08",
"end_date": "2024-01-19",
"issues_count": 15,
"points": 45
},
"project": { /* project object */ }
}
}
Security
Webhook Secrets
Verify webhook authenticity:
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(
f"sha256={expected}",
signature
)
# In your handler
signature = request.headers.get('X-Elixion-Signature')
if not verify_webhook(request.body, signature, WEBHOOK_SECRET):
return Response(status=401)
Headers
Included headers:
| Header | Description |
|--------|-------------|
| X-Elixion-Signature | HMAC signature |
| X-Elixion-Event | Event type |
| X-Elixion-Delivery | Unique delivery ID |
| X-Elixion-Timestamp | Event timestamp |
IP Allowlisting
Elixion webhook IPs:
52.xxx.xxx.xxx/32
52.xxx.xxx.xxx/32
Handling Webhooks
Basic Handler
// Express.js example
app.post('/webhook', express.json(), (req, res) => {
const event = req.body;
switch (event.event) {
case 'issue.created':
handleNewIssue(event.data.issue);
break;
case 'issue.updated':
handleIssueUpdate(event.data);
break;
case 'sprint.completed':
handleSprintEnd(event.data.sprint);
break;
}
res.status(200).json({ received: true });
});
Async Processing
For long-running tasks:
app.post('/webhook', (req, res) => {
// Acknowledge immediately
res.status(200).json({ received: true });
// Process async
queue.add('process-webhook', req.body);
});
Idempotency
Handle duplicate deliveries:
const processedEvents = new Set();
app.post('/webhook', (req, res) => {
const deliveryId = req.headers['x-elixion-delivery'];
if (processedEvents.has(deliveryId)) {
return res.status(200).json({ duplicate: true });
}
processedEvents.add(deliveryId);
// Process event...
});
Testing
Test Delivery
Send test webhook:
- Open webhook settings
- Click Test Webhook
- Select sample event
- Review delivery
Delivery Logs
View webhook history:
Recent Deliveries
─────────────────
Delivery ID Event Status Time
──────────────────────────────────────────────────────
del_abc123 issue.updated ✓ 200 2.3s
del_abc122 sprint.completed ✓ 200 1.8s
del_abc121 issue.created ✗ 500 -
del_abc120 comment.created ✓ 200 0.9s
[View Details] [Retry Failed]
Debugging
View delivery details:
Delivery: del_abc121
Status: ✗ Failed (500)
Request:
POST https://api.example.com/webhook
Headers: { ... }
Body: { "event": "issue.created", ... }
Response:
Status: 500 Internal Server Error
Body: { "error": "Database connection failed" }
Retry: [Retry Now] [Schedule]
Retry Policy
Automatic Retries
Failed webhooks are retried:
Retry Schedule:
1st retry: 1 minute
2nd retry: 5 minutes
3rd retry: 30 minutes
4th retry: 2 hours
5th retry: 12 hours
Success Criteria
Webhook considered successful if:
- HTTP status 2xx
- Response within 30 seconds
Disable on Failure
After repeated failures:
- 10 consecutive failures
- Webhook auto-disabled
- Admin notified
Use Cases
CI/CD Trigger
# Trigger deployment on merge
event: issue.updated
condition: status == "Done" AND labels.includes("deploy")
action: POST to CI/CD system
Slack Custom Bot
// Custom Slack formatting
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
if (event === 'issue.created' && data.issue.priority === 'Critical') {
slack.postMessage({
channel: '#urgent',
text: `🚨 Critical issue: ${data.issue.key}`,
attachments: [/* custom formatting */]
});
}
});
External Analytics
// Track metrics externally
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
analytics.track({
event: `elixion.${event}`,
properties: {
project: data.issue?.project?.key,
type: data.issue?.type,
user: data.actor?.id
}
});
});
Next: Dashboards - Visual insights