Create a Simple Webhook in Laravel
Hello learners, in many time or scenario, you heard the term called webhook. So what is a webhhok? According to Redhat.com:
What is a webhook?
A webhook is a lightweight, event-driven communication that automatically sends data between applications via HTTP. Triggered by specific events, webhooks automate communication between application programming interfaces (APIs) and can be used to activate workflows, such as in GitOps environments.
At its core, a webhook is primarily an HTTP POST request sent to a predefined URL on a server when a specific (yes specific) event occurs. Webhhok has some characteristics. These are:
Event-driven – A webhook is triggered when a specific event happens, such as a payment being processed, a new user signing up, or a file being uploaded.
Payload – The request typically includes a JSON (or sometimes XML) payload with data related to the event.
Security – Webhooks often use secret tokens, API keys, or signatures to verify that the request is legitimate.
Response Handling – The server receiving the webhook may respond with a success (200 OK) or failure (e.g., 400, 500), and the sender might retry failed attempts.
Let’s learn about implementation of a simple webhook in Laravel. In Laravel, handling a webhook typically involves:
Defining a route to receive the webhook request.
Creating a controller to process the request.
Verifying the request (if required).
Processing the payload and provide responding appropriately.
Step 1: Define the Webhook Route
First, in routes/api.php
or routes/web.php
file, define a POST route:
use App\Http\Controllers\WebhookController; use Illuminate\Support\Facades\Route; Route::post('/webhook', [WebhookController::class, 'handleWebhook']);
Step 2: Create a Webhook Controller
Now we have to create that Webhook controller. Run the below command to create the controller:
php artisan make:controller WebhookController
Then, in app/Http/Controllers/WebhookController.php
file we will write the required logic.
- In handleWebhook method we are receiving a request.
- We are saving full request body in our log file for future reference.
- We may need to validate our request for sanitization and also for authentication or authorization purposes.
- We are storing the event in a variable
- Finally, based on event type, we are doing our necessary works and giving a success or error response.
namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\Response; class WebhookController extends Controller { public function handleWebhook(Request $request) { // Log request for debugging \Log::info('Webhook received:', $request->all()); // Validate signature (if required) // if ($request->header('X-Signature') !== 'your-secret-token') { // return response()->json(['error' => 'Unauthorized'], 403); // } // Process the webhook payload $event = $request->input('event'); // Example payload key if ($event === 'user.created') { // Handle user creation event } elseif ($event === 'payment.success') { // Handle payment success event } // Respond to webhook sender return response()->json(['status' => 'success'], 200); } }
Step 3: Test Your Webhook
You can use Postman or cURL to test the webhook:
curl -X POST https://yourdomain.com/webhook \ -H "Content-Type: application/json" \ -d '{"event": "user.created", "user": {"id": 1, "name": "John"}}'
Or, if you’re testing locally with Laravel’s built-in server, use:
curl -X POST http://127.0.0.1:8000/webhook \ -H "Content-Type: application/json" \ -d '{"event": "user.created", "user": {"id": 1, "name": "John"}}'
Step 4: Securing the Webhook (Optional)
To verify requests, many webhook providers send an HMAC signature in headers (e.g., X-Signature
). You can validate it like this:
$signature = $request->header('X-Signature'); $secret = 'your-secret-key'; $expectedSignature = hash_hmac('sha256', $request->getContent(), $secret); if (!hash_equals($expectedSignature, $signature)) { return response()->json(['error' => 'Invalid signature'], 403); }
Step 5: Logging Webhook Requests (For Debugging)
If you want to log incoming webhooks for debugging, add this to handleWebhook()
:
\Log::info('Webhook received:', $request->all());
When producing (sending) and consuming (receiving) webhooks, there are several important considerations to ensure reliability, security, and scalability.
Producing Webhooks (Sending Webhooks)
If our Laravel app sends webhooks to other services, we should consider:
Retry Mechanism for Reliability
The receiving server might be down or slow. We should implement retry logic with exponential backoff mechanism.
Example: Retry after 10s, then 30s, then 1m, then 5m, etc.
Store failed webhooks in a queue job and retry later.
Example: Queueing Webhooks in Laravel
Laravel’s queue system ensures reliability.
Event-Driven Architecture
Instead of sending webhooks directly inside controllers, we can use Laravel Events & Listeners.
Example: If a user registers, fire a
UserRegistered
event and let listeners handle webhook sending.
Example: Dispatching an Event
Secure Webhooks with Signatures
Webhooks should include an HMAC signature in the headers.
The receiver can verify the signature to ensure it’s authentic.
Example: Signing a Webhook in Laravel
Include the signature in headers when sending:
Handling Delivery Failures
Log every webhook request, whether successful or failed.
Use a database table to track webhook status (
pending
,failed
,success
).
Example: Creating a sample Webhook Logs Table
If our Laravel app receives webhooks, we should consider:
Validate Incoming Webhooks
Check HTTP headers for an authentication token or HMAC signature.
See below example:
if (!hash_equals($expectedSignature, $signature)) {
return response()->json(['error' => 'Invalid signature'], 403);
}
Respond Quickly
Webhook providers expect a fast response (200 OK) within a few seconds.
If processing takes time, we can queue the job and return
200 OK
immediately.
Example: Queueing Webhook Processing
Idempotency (Avoid Duplicate Processing)
Some providers send the same webhook multiple times to ensure delivery.
Store received webhook event IDs in a database to avoid duplicate processing.
Example: Checking for Duplicate Webhooks
Logging for Debugging
Store all webhook requests in a log file or a database table for debugging.
Sample Laravel logging:
Check logs in
storage/logs/laravel.log
.
Other common security best practices
Use HTTPS to prevent data interception.
Whitelist webhook sources (only allow requests from trusted IPs).
Rate limiting: Protect your API from spammy webhook requests.
Example: Laravel Rate Limiting
In app/Http/Middleware/ThrottleRequests.php
:
Apply it to your webhook route:
At a glance summary
✅ Feature | 📤 Producing Webhooks | 📥 Consuming Webhooks |
---|---|---|
Retry Mechanism | Yes (queue & backoff) | No (depends on provider) |
Event-Driven | Yes (use events) | No (direct call) |
Signature Check | Yes (HMAC signing) | Yes (validate) |
Response Time | N/A | Fast! (200 OK immediately) |
Duplicate Handling | No (provider’s job) | Yes (check event ID) |
Logging | Yes | Yes |
Security | API keys, HTTPS | HTTPS, IP whitelisting |
Hope this article will help you to teach about a complete Laravel example for webhook producer and consumer. 🚀