Webhooks
Webhooks notify your server when events occur in your Fyber account. Use them to trigger actions like fulfilling orders, sending emails, or updating your database.
Setup
- Go to Fyber Console > Developer > Webhooks
- Add your endpoint URL (e.g.,
https://yoursite.com/webhooks/fyber) - Select the events you want to receive
- Copy your webhook secret (
whsec_...)
Verify Signatures
Always verify webhook signatures to ensure requests come from Fyber.
JavaScript
javascript
import express from 'express';
import { Fyber } from '@fyber.one/sdk-js';
const app = express();
app.post('/webhooks/fyber', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['fyber-signature'];
const webhookSecret = 'whsec_your_webhook_secret';
let event;
try {
event = Fyber.webhooks.verify(
req.body.toString(),
signature,
webhookSecret
);
} catch (err) {
console.error('Webhook verification failed:', err.message);
return res.status(400).send('Invalid signature');
}
// Handle the event
switch (event.type) {
case 'checkout.session.completed':
handleCheckoutComplete(event.data.object);
break;
case 'payment.succeeded':
handlePaymentSucceeded(event.data.object);
break;
// ... handle other events
}
res.json({ received: true });
});PHP
php
<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_FYBER_SIGNATURE'];
$webhookSecret = 'whsec_your_webhook_secret';
try {
$event = Fyber::verifyWebhook($payload, $signature, $webhookSecret);
switch ($event['type']) {
case 'checkout.session.completed':
handleCheckoutComplete($event['data']['object']);
break;
case 'payment.succeeded':
handlePaymentSucceeded($event['data']['object']);
break;
}
http_response_code(200);
echo json_encode(['received' => true]);
} catch (Fyber\Exceptions\FyberException $e) {
http_response_code(400);
echo 'Invalid signature';
}C#
csharp
[HttpPost("webhook")]
public IActionResult HandleWebhook()
{
var payload = new StreamReader(Request.Body).ReadToEnd();
var signature = Request.Headers["fyber-signature"].ToString();
var webhookSecret = "whsec_your_webhook_secret";
try
{
var webhookEvent = FyberClient.VerifyWebhook(payload, signature, webhookSecret);
switch (webhookEvent.Type)
{
case "checkout.session.completed":
HandleCheckoutComplete(webhookEvent.Data);
break;
case "payment.succeeded":
HandlePaymentSucceeded(webhookEvent.Data);
break;
}
return Ok();
}
catch (FyberException)
{
return BadRequest("Invalid signature");
}
}Flutter
dart
try {
final event = Fyber.verifyWebhook(
payload: rawBody,
signature: request.headers['fyber-signature']!,
secret: 'whsec_your_webhook_secret',
);
switch (event['type']) {
case 'payment.succeeded':
handlePaymentSucceeded(event['data']['object']);
break;
}
} on FyberException catch (e) {
print('Invalid webhook: ${e.message}');
}Event Types
Checkout Events
| Event | Description |
|---|---|
checkout.session.completed | Customer completed checkout |
checkout.session.expired | Session expired without payment |
Payment Events
| Event | Description |
|---|---|
payment.succeeded | Payment completed successfully |
payment.failed | Payment was declined |
payment.canceled | Payment was canceled/voided |
Refund Events
| Event | Description |
|---|---|
refund.created | Refund initiated |
refund.succeeded | Refund completed |
refund.failed | Refund failed |
Token Events
| Event | Description |
|---|---|
token.created | Card saved successfully |
token.deleted | Saved card removed |
Subscription Events
| Event | Description |
|---|---|
subscription.created | Subscription started |
subscription.payment_succeeded | Recurring payment successful |
subscription.payment_failed | Recurring payment failed |
subscription.trial_ending | Trial ends in 3 days |
subscription.canceled | Subscription ended |
Installment Events
| Event | Description |
|---|---|
installment.plan_created | Plan activated |
installment.payment_succeeded | Scheduled payment completed |
installment.payment_failed | Scheduled payment failed |
installment.plan_completed | All payments completed |
installment.plan_defaulted | Customer defaulted |
Event Object
json
{
"id": "evt_abc123",
"object": "event",
"type": "payment.succeeded",
"data": {
"object": {
"id": "pay_xyz789",
"amount": 5000,
"currency": "JMD",
"status": "succeeded"
}
},
"createdAt": "2024-01-15T10:30:00Z"
}Best Practices
Respond Quickly
Return a 2xx response immediately, then process the event asynchronously:
javascript
app.post('/webhooks/fyber', async (req, res) => {
// Verify signature first
const event = Fyber.webhooks.verify(...);
// Respond immediately
res.json({ received: true });
// Process asynchronously
await processEventAsync(event);
});Handle Duplicates
Events may be delivered more than once. Use the event ID to deduplicate:
javascript
const processedEvents = new Set();
function handleEvent(event) {
if (processedEvents.has(event.id)) {
return; // Already processed
}
processedEvents.add(event.id);
// Process event...
}Retry Failed Deliveries
If your endpoint returns a non-2xx response, Fyber retries:
- 1st retry: 5 minutes
- 2nd retry: 30 minutes
- 3rd retry: 2 hours
- 4th retry: 24 hours
After 4 failed attempts, the webhook is marked as failed.
Test Webhooks Locally
Use a tool like ngrok to expose your local server:
bash
ngrok http 3000
# Use the ngrok URL as your webhook endpointWebhook Logs
View webhook delivery history in the Fyber Console under Developer > Webhooks > Logs.