Webhooks API Reference
Receive real-time notifications about events in your Waffy integration. Configure secure webhook endpoints to stay updated on payments, contracts, and user activities.
Overview
Webhooks allow your application to receive real-time notifications when events occur in your Waffy integration. Instead of polling our API, webhooks push event data to your endpoints immediately when something happens.
Instant notifications when events occur
HMAC signature verification and HTTPS required
Automatic retries with exponential backoff
POSTCreate Webhook
Register a new webhook endpoint to receive event notifications
Endpoint
Request Body
{
"url": "https://your-app.com/webhooks/waffy",
"events": [
"payment.completed",
"payment.failed",
"contract.signed",
"contract.milestone.completed",
"user.verified"
],
"description": "Main webhook for production environment",
"enabled": true,
"secret": "your-webhook-secret-key",
"metadata": {
"environment": "production",
"version": "v1"
}
}Response (201 Created)
{
"success": true,
"data": {
"webhook_id": "wh_1a2b3c4d5e6f7g8h",
"url": "https://your-app.com/webhooks/waffy",
"events": [
"payment.completed",
"payment.failed",
"contract.signed",
"contract.milestone.completed",
"user.verified"
],
"status": "active",
"secret": "whsec_1a2b3c4d5e6f7g8h...",
"created_at": "2024-01-15T10:30:00Z",
"last_delivery": null,
"successful_deliveries": 0,
"failed_deliveries": 0
},
"meta": {
"request_id": "req_1a2b3c4d5e6f",
"timestamp": "2024-01-15T10:30:00Z"
}
}Available Events
Complete list of events you can subscribe to
Payment Events
payment.createdNew payment initiatedpayment.processingPayment is being processedpayment.completedPayment successfully completedpayment.failedPayment failed or was declinedContract Events
contract.createdNew contract createdcontract.signedContract signed by all partiescontract.milestone.completedContract milestone marked completecontract.completedAll contract milestones completedcontract.cancelledContract was cancelledUser Events
user.createdNew user account createduser.verifiedUser completed KYC verificationuser.updatedUser information updatedWebhook Payload Structure
Example of how webhook events are delivered to your endpoint
Payment Completed Event
{
"id": "evt_1a2b3c4d5e6f7g8h",
"type": "payment.completed",
"created": "2024-01-15T10:32:15Z",
"data": {
"object": {
"payment_id": "pay_1a2b3c4d5e6f7g8h",
"amount": 1000.00,
"currency": "USD",
"status": "completed",
"payer": {
"user_id": "usr_1a2b3c4d5e6f",
"email": "payer@example.com"
},
"recipient": {
"user_id": "usr_7g8h9i0j1k2l",
"email": "recipient@example.com"
},
"transaction_id": "txn_9i8h7g6f5e4d",
"completed_at": "2024-01-15T10:32:15Z",
"metadata": {
"order_id": "ord_abc123"
}
}
},
"request": {
"id": "req_original_1a2b3c4d5e6f",
"idempotency_key": "idem_xyz789"
},
"pending_webhooks": 1,
"api_version": "2024-01-01"
}Contract Milestone Completed Event
{
"id": "evt_2b3c4d5e6f7g8h9i",
"type": "contract.milestone.completed",
"created": "2024-01-15T14:22:30Z",
"data": {
"object": {
"contract_id": "ctr_1a2b3c4d5e6f",
"milestone_id": "mls_1a2b3c4d",
"title": "Design Approval",
"amount": 1500.00,
"currency": "USD",
"completed_by": "usr_dev456",
"completed_at": "2024-01-15T14:22:30Z",
"deliverables": [
{
"name": "Design Mockups",
"url": "https://files.example.com/mockups.pdf"
}
],
"payment_status": "released"
}
},
"pending_webhooks": 2,
"api_version": "2024-01-01"
}Webhook Security
Verify webhook authenticity with HMAC signatures
Signature Verification
Waffy signs webhook payloads with your webhook secret using HMAC-SHA256. The signature is included in the Waffy-Signature header.
// Node.js example
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
const expectedHeader = `sha256=${expectedSignature}`;
return crypto.timingSafeEqual(
Buffer.from(signature, 'utf8'),
Buffer.from(expectedHeader, 'utf8')
);
}
// Usage in Express.js
app.post('/webhooks/waffy', express.raw({type: 'application/json'}), (req, res) => {
const payload = req.body;
const signature = req.headers['waffy-signature'];
const secret = process.env.WAFFY_WEBHOOK_SECRET;
if (!verifyWebhookSignature(payload, signature, secret)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
// Process the webhook event
switch (event.type) {
case 'payment.completed':
handlePaymentCompleted(event.data.object);
break;
case 'contract.milestone.completed':
handleMilestoneCompleted(event.data.object);
break;
// Handle other event types...
}
res.status(200).send('OK');
});GETList Webhooks
Retrieve all webhook endpoints for your account
Endpoint
Response (200 OK)
{
"success": true,
"data": [
{
"webhook_id": "wh_1a2b3c4d5e6f7g8h",
"url": "https://your-app.com/webhooks/waffy",
"events": [
"payment.completed",
"payment.failed",
"contract.signed"
],
"status": "active",
"created_at": "2024-01-15T10:30:00Z",
"last_delivery": "2024-01-15T14:22:30Z",
"successful_deliveries": 42,
"failed_deliveries": 2
}
],
"pagination": {
"total": 1,
"count": 1,
"per_page": 20,
"current_page": 1,
"total_pages": 1
}
}Delivery & Retry Policy
Retry Policy
• Webhooks are retried up to 3 times on failure
• Exponential backoff: 1s, 10s, 100s delays
• HTTP 200-299 responses are considered successful
• Timeout after 30 seconds
Best Practices
• Respond with HTTP 200 status code quickly
• Implement idempotency using the event ID
• Always verify the webhook signature
• Process webhooks asynchronously when possible
Common Errors
400 Bad Request - Invalid URL
{
"success": false,
"error": {
"code": "INVALID_WEBHOOK_URL",
"message": "Webhook URL must be HTTPS and publicly accessible",
"details": {
"url": "http://localhost:3000/webhooks",
"requirements": ["HTTPS required", "Must be publicly accessible"]
}
}
}422 Unprocessable Entity - Invalid Events
{
"success": false,
"error": {
"code": "INVALID_EVENTS",
"message": "One or more event types are not supported",
"details": {
"invalid_events": ["payment.refunded", "user.deleted"],
"supported_events": ["payment.completed", "payment.failed", "..."]
}
}
}Webhook Testing Tool
Test your webhook endpoint with sample events
Webhook Guide
Complete guide to implementing webhooks