Webhook Management
Create and manage webhooks through your dashboard or via API endpoints.
Create Webhook
Create a new webhook endpoint to receive event notifications.
POST/api/v1/webhooks
Required permission: webhooks:write
Request Body
{
"url": "https://yourapp.com/webhooks/julypay",
"events": [
"transaction.completed",
"transaction.failed",
"wallet.credited",
"wallet.debited"
],
"api_key_id": 123,
"description": "Main webhook endpoint"
}Copy
Response Example
{
"success": true,
"message": "Webhook created successfully",
"data": {
"id": 456,
"url": "https://yourapp.com/webhooks/julypay",
"events": [
"transaction.completed",
"transaction.failed",
"wallet.credited",
"wallet.debited"
],
"secret": "whsk_abc123...",
"is_active": true,
"created_at": "2025-01-12T10:30:00Z"
}
}Copy
Available Events
Subscribe to these events to receive notifications:
Event | Description | When Triggered |
|---|---|---|
transaction.created | Transaction Created | When a new transaction is initiated |
transaction.completed | Transaction Completed | When a transaction is successfully completed |
transaction.failed | Transaction Failed | When a transaction fails or is cancelled |
transaction.pending | Transaction Pending | When a transaction requires approval |
wallet.credited | Wallet Credited | When funds are added to wallet |
wallet.debited | Wallet Debited | When funds are deducted from wallet |
deposit.completed | Deposit Completed | When a deposit is successful |
deposit.failed | Deposit Failed | When a deposit fails |
withdrawal.completed | Withdrawal Completed | When a withdrawal is successful |
withdrawal.failed | Withdrawal Failed | When a withdrawal fails |
send_money.completed | Send Money Completed | When money transfer is successful |
send_money.failed | Send Money Failed | When money transfer fails |
Webhook Payload
All webhook events will be sent as HTTP POST requests with this structure:
{
"id": "evt_abc123",
"type": "transaction.completed",
"created": 1642000000,
"data": {
"id": 12345,
"reference": "SM_1642000000_123",
"external_reference": "REL_ABC123",
"type": "payment_sent",
"amount": 50000,
"fee_amount": 3000,
"net_amount": 47000,
"currency": "UGX",
"status": "completed",
"description": "Payment for services",
"created_at": "2025-01-12T10:30:00Z",
"completed_at": "2025-01-12T10:31:00Z",
"failed_at": null,
"metadata": {
"recipient_phone": "256701234567",
"recipient_name": "John Doe",
"provider": "MTN",
"api_triggered": true
}
},
"api_version": "2025-01"
}Copy
Webhook Security
All webhook requests are signed with a secret key to ensure authenticity. Verify the signature to confirm the request is from JulyPay.
Request Headers
User-Agent: JulyPay-Webhooks/1.0
Content-Type: application/json
X-JulyPay-Event: transaction.completed
X-JulyPay-Signature: sha256=abc123...
X-JulyPay-Delivery: 789
X-JulyPay-Timestamp: 1642000000Copy
Signature Verification (PHP)
function verifyWebhookSignature($payload, $signature, $secret) {
$expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expectedSignature, $signature);
}
// Usage
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_JULYPAY_SIGNATURE'];
$secret = 'your_webhook_secret';
if (verifyWebhookSignature($payload, $signature, $secret)) {
// Process webhook
$event = json_decode($payload, true);
// Handle the event...
} else {
// Invalid signature
http_response_code(400);
exit('Invalid signature');
}Copy
Webhook Management
List Webhooks
GET /api/v1/webhooks
Get Webhook
GET /api/v1/webhooks/{id}
Update Webhook
PUT /api/v1/webhooks/{id}
Delete Webhook
DELETE /api/v1/webhooks/{id}
Test Webhook
POST /api/v1/webhooks/{id}/test
Get Deliveries
GET /api/v1/webhooks/{id}/deliveries
Best Practices
✓ Do
-
• Verify webhook signatures to ensure authenticity
-
• Respond with HTTP 200 status code for successful processing
-
• Handle webhook retries gracefully (idempotency)
-
• Process webhooks asynchronously when possible
-
• Log webhook events for debugging and auditing
✗ Don't
-
• Take longer than 30 seconds to respond
-
• Expose your webhook secret in client-side code
-
• Process the same event multiple times without checking
-
• Rely on webhook order for critical business logic
-
• Use webhooks for real-time user interfaces
Retry Policy
If your webhook endpoint doesn't respond with a 2xx status code, we'll retry the delivery with exponential backoff:
Attempt | Delay | Total Time |
|---|---|---|
1st retry | 1 minute | 1 minute |
2nd retry | 5 minutes | 6 minutes |
3rd retry | 15 minutes | 21 minutes |
4th retry | 1 hour | 1 hour 21 minutes |
5th retry | 6 hours | 7 hours 21 minutes |
After 5 failed attempts, the webhook will be automatically disabled. You can re-enable it from your dashboard.