Skip to content

Webhooks ​

Send Nadi alerts to any HTTP endpoint.

Overview ​

Webhooks allow you to:

  • Integrate with custom systems
  • Trigger automated workflows
  • Connect to unsupported platforms
  • Build custom alerting logic

Setup ​

1. Create Webhook ​

  1. Go to Settings → Integrations
  2. Click Add Webhook
  3. Enter your webhook URL
  4. Configure options
  5. Click Save

2. Test ​

Click Test to send a sample payload.

Webhook Configuration ​

Basic Settings ​

SettingDescription
URLEndpoint to receive alerts
MethodHTTP method (POST, PUT)
HeadersCustom headers to include
SecretSigning secret for verification

Authentication ​

Bearer Token ​

yaml
headers:
  Authorization: "Bearer your-token"

API Key ​

yaml
headers:
  X-API-Key: "your-api-key"

Custom Header ​

yaml
headers:
  X-Custom-Auth: "your-value"

Payload Format ​

Standard Payload ​

json
{
  "event": "issue.new",
  "timestamp": "2024-01-15T10:30:00Z",
  "project": {
    "id": "abc123",
    "name": "my-app",
    "environment": "production"
  },
  "issue": {
    "id": "xyz789",
    "title": "TypeError: Cannot read property 'name' of undefined",
    "level": "error",
    "culprit": "app/services/UserService.php:45",
    "firstSeen": "2024-01-15T10:25:00Z",
    "lastSeen": "2024-01-15T10:30:00Z",
    "eventCount": 23,
    "userCount": 12,
    "url": "https://nadi.pro/issues/xyz789"
  },
  "event": {
    "id": "evt123",
    "message": "Cannot read property 'name' of undefined",
    "tags": {
      "environment": "production",
      "release": "1.2.3"
    }
  }
}

Event Types ​

EventDescription
issue.newNew issue created
issue.regressionResolved issue recurred
issue.resolvedIssue marked resolved
issue.ignoredIssue marked ignored
issue.assignedIssue assigned to user
alert.thresholdThreshold exceeded
alert.performancePerformance degraded

Customizing Payload ​

Transform the payload to match your system:

yaml
webhook:
  url: "https://api.example.com/alerts"
  transform:
    title: "{{ issue.title }}"
    severity: "{{ issue.level }}"
    link: "{{ issue.url }}"

Signature Verification ​

Verify Requests ​

Nadi signs webhooks with your secret:

X-Nadi-Signature: sha256=abc123...

Verification Code ​

python
import hmac
import hashlib

def verify_signature(payload, signature, secret):
    expected = 'sha256=' + hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)
javascript
const crypto = require('crypto')

function verifySignature(payload, signature, secret) {
  const expected =
    'sha256=' +
    crypto.createHmac('sha256', secret).update(payload).digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  )
}
php
function verifySignature($payload, $signature, $secret) {
    $expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expected, $signature);
}

Retry Behavior ​

Automatic Retries ​

Failed webhooks are retried:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours

Success Criteria ​

Webhook is considered successful when:

  • HTTP status 2xx returned
  • Response received within 30 seconds

Failure Handling ​

After max retries:

  • Webhook is disabled
  • You receive notification
  • Events are logged

Integration Examples ​

PagerDuty ​

yaml
url: "https://events.pagerduty.com/v2/enqueue"
headers:
  Content-Type: "application/json"
transform:
  routing_key: "your-routing-key"
  event_action: "trigger"
  payload:
    summary: "{{ issue.title }}"
    severity: "critical"
    source: "nadi"

Opsgenie ​

yaml
url: "https://api.opsgenie.com/v2/alerts"
headers:
  Authorization: "GenieKey your-key"
transform:
  message: "{{ issue.title }}"
  priority: "P1"
  source: "Nadi"

Discord ​

yaml
url: "https://discord.com/api/webhooks/xxx/yyy"
transform:
  content: "🔴 **{{ issue.title }}**\n{{ issue.url }}"

Custom API ​

yaml
url: "https://api.yourcompany.com/incidents"
headers:
  Authorization: "Bearer {{ env.API_TOKEN }}"
  X-Source: "nadi"
transform:
  title: "{{ issue.title }}"
  severity: "{{ issue.level }}"
  service: "{{ project.name }}"
  details:
    url: "{{ issue.url }}"
    events: "{{ issue.eventCount }}"

Testing ​

Manual Test ​

  1. Click Test on the webhook
  2. Review the sent payload
  3. Check your endpoint received it

Debug Mode ​

Enable debug logging:

  1. Go to webhook settings
  2. Enable Debug Mode
  3. View request/response logs

Request Inspector ​

Use tools like:

Troubleshooting ​

Webhook Not Firing ​

  1. Check URL is correct
  2. Verify endpoint is reachable
  3. Check alert rules are active
  4. Review webhook logs

Invalid Signature ​

  1. Verify secret matches
  2. Check payload encoding
  3. Ensure body isn't modified

Timeouts ​

  1. Optimize endpoint performance
  2. Return 202 and process async
  3. Check network connectivity

Best Practices ​

Security ​

  1. Use HTTPS endpoints
  2. Verify signatures
  3. Rotate secrets periodically
  4. Validate payload structure

Reliability ​

  1. Return 2xx quickly
  2. Process async for heavy work
  3. Implement idempotency
  4. Log webhook receipts

Performance ​

  1. Respond within 30 seconds
  2. Queue for processing
  3. Handle retries gracefully

Next Steps ​

Released under the MIT License.