Webhooks

Webhooks allow you to receive real-time notifications when transactions and other events occur in your account. Configure webhook endpoints to automatically receive HTTP POST requests when specific events happen.

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.

Updated on