Skip to content

Webhooks

Webhooks enable real-time notifications to external systems when events occur in your ERP, supporting integrations and automated workflows.

Overview

Webhooks enable you to:

  • Send real-time notifications
  • Integrate with external systems
  • Trigger automated workflows
  • Sync data with other platforms
  • Monitor webhook delivery
  • Handle retry logic

Accessing Webhooks

Navigate to Settings → Integrations → Webhooks from the main menu.

Webhook Overview

Active Webhooks

Webhooks

Active Webhooks:
┌────────────────────────────────────────────────────────────────┐
│ Name              │ URL                │ Events │ Deliveries  │
├────────────────────────────────────────────────────────────────┤
│ Order Sync        │ api.partner.com    │ 3      │ 5,678 (99%) │
│ Inventory Update  │ warehouse.sys.com  │ 2      │ 12,345 (98%)│
│ Customer CRM      │ crm.company.com    │ 4      │ 2,345 (100%)│
│ Accounting Sync   │ quickbooks.api     │ 5      │ 8,901 (99%) │
│ Slack Notifications│hooks.slack.com    │ 6      │ 3,456 (100%)│
└────────────────────────────────────────────────────────────────┘

Delivery Statistics (Last 30 Days):
├─ Total Deliveries: 32,725
├─ Successful: 32,456 (99.2%)
├─ Failed: 269 (0.8%)
└─ Average Latency: 234ms

[+ Create Webhook]

Creating Webhooks

Webhook Configuration

Create Webhook

Basic Information:
├─ Name: [Order Sync to Partner]
├─ Description: [Sends order data to partner fulfillment system]
├─ Status: [Active ▼]
└─ Version: [v1 ▼]

Endpoint Configuration:
├─ URL: [https://api.partner.com/webhooks/orders]
├─ Method: [POST ▼]
└─ Content Type: [application/json ▼]

Authentication:
├─ Type: [Bearer Token ▼]
│  ├─ None
│  ├─ Bearer Token
│  ├─ Basic Auth
│  ├─ API Key Header
│  └─ HMAC Signature
└─ Token/Credentials: [••••••••••••••••]

Headers (Optional):
├─ X-Source: angage-erp
├─ X-Environment: production
└─ [+ Add Header]

Events to Send:
├─ [x] order.created
├─ [x] order.updated
├─ [x] order.shipped
├─ [ ] order.cancelled
├─ [ ] order.completed
└─ [Show All Events]

[Test Webhook] [Save Webhook]

Available Events

Event Categories

Webhook Events

Sales Events:
├─ order.created - New order placed
├─ order.updated - Order modified
├─ order.confirmed - Order confirmed
├─ order.shipped - Order shipped
├─ order.delivered - Order delivered
├─ order.cancelled - Order cancelled
├─ invoice.created - Invoice generated
├─ invoice.sent - Invoice emailed
├─ payment.received - Payment recorded
└─ payment.refunded - Refund processed

Customer Events:
├─ customer.created - New customer
├─ customer.updated - Customer modified
├─ customer.deleted - Customer removed
└─ contact.created - New contact added

Product Events:
├─ product.created - New product
├─ product.updated - Product modified
├─ product.deleted - Product removed
└─ inventory.updated - Stock changed

Purchase Events:
├─ purchase_order.created - New PO
├─ purchase_order.approved - PO approved
├─ purchase_order.received - Goods received
└─ bill.created - Vendor bill entered

Event Filters

Event Filtering

Webhook: Order Sync to Partner

Event: order.created

Filters (only trigger when):
├─ Order Total > $[100]
├─ AND Order Source = [Online ▼]
├─ AND Ship Method = [Standard, Express ▼]
└─ [+ Add Filter]

Sample Matching:
├─ Order $150, Online, Express → ✓ Triggers
├─ Order $50, Online, Express → ✗ Below minimum
├─ Order $200, Phone, Standard → ✗ Wrong source
└─ Order $500, Online, Ground → ✗ Wrong ship method

[Save Filters]

Payload Configuration

Payload Template

Webhook Payload

Event: order.created

Payload Format: [JSON ▼]

Payload Template:
┌────────────────────────────────────────────────────────────────┐
│ {                                                              │
│   "event": "order.created",                                    │
│   "timestamp": "{webhook.timestamp}",                          │
│   "data": {                                                    │
│     "order_id": "{order.id}",                                  │
│     "order_number": "{order.number}",                          │
│     "customer": {                                              │
│       "id": "{customer.id}",                                   │
│       "name": "{customer.name}",                               │
│       "email": "{customer.email}"                              │
│     },                                                         │
│     "items": [                                                 │
│       {                                                        │
│         "sku": "{item.sku}",                                   │
│         "name": "{item.name}",                                 │
│         "quantity": "{item.quantity}",                         │
│         "price": "{item.price}"                                │
│       }                                                        │
│     ],                                                         │
│     "totals": {                                                │
│       "subtotal": "{order.subtotal}",                          │
│       "tax": "{order.tax}",                                    │
│       "shipping": "{order.shipping}",                          │
│       "total": "{order.total}"                                 │
│     }                                                          │
│   }                                                            │
│ }                                                              │
└────────────────────────────────────────────────────────────────┘

[Use Default Template] [Preview with Sample Data]

Available Variables

Webhook Variables

System Variables:
├─ {webhook.id} - Webhook delivery ID
├─ {webhook.timestamp} - ISO 8601 timestamp
├─ {webhook.event} - Event name
└─ {webhook.attempt} - Retry attempt number

Order Variables:
├─ {order.id} - Internal order ID
├─ {order.number} - Order number
├─ {order.date} - Order date
├─ {order.status} - Order status
├─ {order.subtotal} - Subtotal amount
├─ {order.tax} - Tax amount
├─ {order.shipping} - Shipping amount
├─ {order.total} - Total amount
└─ {order.notes} - Order notes

Customer Variables:
├─ {customer.id} - Customer ID
├─ {customer.code} - Customer code
├─ {customer.name} - Company name
├─ {customer.email} - Email address
└─ {customer.phone} - Phone number

Line Item Variables (array):
├─ {item.sku} - Product SKU
├─ {item.name} - Product name
├─ {item.quantity} - Quantity ordered
├─ {item.price} - Unit price
└─ {item.total} - Line total

Delivery & Retry

Delivery Settings

Delivery Configuration

Webhook: Order Sync to Partner

Timeout Settings:
├─ Connection Timeout: [10] seconds
├─ Response Timeout: [30] seconds
└─ Consider success if HTTP: [200-299 ▼]

Retry Policy:
├─ [x] Enable automatic retries
├─ Max Retries: [5]
├─ Retry Intervals:
│  ├─ 1st retry: 1 minute
│  ├─ 2nd retry: 5 minutes
│  ├─ 3rd retry: 30 minutes
│  ├─ 4th retry: 2 hours
│  └─ 5th retry: 12 hours
└─ Backoff: [Exponential ▼]

Failure Handling:
├─ After all retries fail: [Notify admin ▼]
├─ Notification email: [[email protected]]
├─ [x] Log failed payloads
└─ [ ] Pause webhook after 10 consecutive failures

[Save Delivery Settings]

Delivery Log

Webhook Delivery Log

Webhook: Order Sync to Partner
Time Period: [Last 7 Days ▼]

Summary:
├─ Total Deliveries: 567
├─ Successful: 561 (98.9%)
├─ Failed: 6 (1.1%)
└─ Avg Response Time: 234ms

Recent Deliveries:
┌────────────────────────────────────────────────────────────────┐
│ Time        │ Event         │ Status  │ Response│ Duration    │
├────────────────────────────────────────────────────────────────┤
│ 10:45:32 AM │ order.created │ ✓ 200   │ OK      │ 189ms       │
│ 10:43:15 AM │ order.shipped │ ✓ 200   │ OK      │ 234ms       │
│ 10:40:01 AM │ order.created │ ✓ 200   │ OK      │ 201ms       │
│ 10:35:22 AM │ order.updated │ ⚠️ 500  │ Retry 1 │ 5,023ms     │
│ 10:30:45 AM │ order.created │ ✓ 200   │ OK      │ 178ms       │
└────────────────────────────────────────────────────────────────┘

[View Details] [Retry Failed] [Export Log]

Delivery Detail

Delivery Detail

Delivery ID: whd_abc123def456
Webhook: Order Sync to Partner
Event: order.created
Record: SO-2026-0892

Timeline:
├─ Jan 22, 10:35:22 AM - Triggered
├─ Jan 22, 10:35:22 AM - Attempt 1: Failed (500)
├─ Jan 22, 10:36:22 AM - Attempt 2: Failed (500)
├─ Jan 22, 10:41:22 AM - Attempt 3: Success (200)
└─ Total Duration: 6 minutes

Request:
├─ URL: https://api.partner.com/webhooks/orders
├─ Method: POST
├─ Headers: [View]
└─ Payload: [View]

Response (Attempt 3):
├─ Status: 200 OK
├─ Duration: 234ms
├─ Headers: [View]
└─ Body: {"status": "received", "id": "12345"}

[Resend] [View Full Payload]

Testing

Test Webhook

Test Webhook

Webhook: Order Sync to Partner
Endpoint: https://api.partner.com/webhooks/orders

Test Options:
├─ Event: [order.created ▼]
├─ Sample Data: [Recent Order ▼]
│  ├─ Recent Order (SO-2026-0892)
│  ├─ Sample Data (generated)
│  └─ Custom (enter JSON)
└─ Include signature: [x]

Payload Preview:
┌────────────────────────────────────────────────────────────────┐
│ {                                                              │
│   "event": "order.created",                                    │
│   "timestamp": "2026-01-22T15:30:00Z",                        │
│   "data": {                                                    │
│     "order_id": "ord_abc123",                                  │
│     "order_number": "SO-2026-0892",                            │
│     ...                                                        │
│   }                                                            │
│ }                                                              │
└────────────────────────────────────────────────────────────────┘

[Send Test]

Test Result:
├─ Status: ✓ 200 OK
├─ Duration: 234ms
├─ Response: {"status": "received"}
└─ Webhook is working correctly!

Security

Webhook Signatures

Webhook Security

Signature Verification:

Each webhook includes a signature header for verification:
X-Angage-Signature: sha256=abc123...

Signing Secret: whsec_••••••••••••••••

Verification Code (Python):
┌────────────────────────────────────────────────────────────────┐
│ import hmac                                                    │
│ import hashlib                                                 │
│                                                                │
│ def verify_signature(payload, signature, secret):              │
│     expected = hmac.new(                                       │
│         secret.encode(),                                       │
│         payload.encode(),                                      │
│         hashlib.sha256                                         │
│     ).hexdigest()                                              │
│     return hmac.compare_digest(f"sha256={expected}", signature)│
└────────────────────────────────────────────────────────────────┘

Additional Security:
├─ [x] Include timestamp in signature
├─ [x] Reject requests older than 5 minutes
├─ [x] Require HTTPS endpoints
└─ [ ] IP allowlist for receiving servers

[Regenerate Secret]

Best Practices

Configuration

  • Use HTTPS endpoints
  • Implement signature verification
  • Set appropriate timeouts
  • Configure retry policies

Handling

  • Respond quickly (< 30s)
  • Return 2xx for success
  • Process asynchronously
  • Implement idempotency

Monitoring

  • Monitor delivery rates
  • Set up failure alerts
  • Review logs regularly
  • Test after changes

Troubleshooting

Common Issues

Webhook not triggering

  • Verify webhook is active
  • Check event subscriptions
  • Review filter conditions
  • Test with sample data

Delivery failures

  • Check endpoint URL
  • Verify authentication
  • Review error responses
  • Check firewall rules

Duplicate deliveries

  • Implement idempotency
  • Check retry settings
  • Use delivery IDs
  • Verify success responses

Related Documentation

Learn about API Settings for bi-directional integration.

Angage ERP Documentation