Handle Webhook Events
Process webhook payloads in your application
Handle Webhook Events
Learn how to receive and process webhook events from Plexy.
Webhook payload structure
Every webhook event has a consistent structure:
{
"id": "evt_1234567890",
"type": "payment.succeeded",
"created": 1679529600,
"data": {
"id": "pay_abc123",
"amount": 5000,
"currency": "USD",
"status": "succeeded"
}
}| Field | Description |
|---|---|
id | Unique event identifier |
type | Event type (e.g., payment.succeeded) |
created | Unix timestamp when event occurred |
data | Event-specific payload |
Basic webhook handler
const express = require('express');
const app = express();
app.post('/webhooks/plexy', express.json(), (req, res) => {
const event = req.body;
switch (event.type) {
case 'payment.succeeded':
const payment = event.data;
console.log(`Payment ${payment.id} succeeded`);
// Update order status, send confirmation email, etc.
break;
case 'payment.failed':
const failedPayment = event.data;
console.log(`Payment ${failedPayment.id} failed`);
// Notify customer, retry payment, etc.
break;
case 'refund.succeeded':
const refund = event.data;
console.log(`Refund ${refund.id} processed`);
// Update inventory, notify customer, etc.
break;
default:
console.log(`Unhandled event type: ${event.type}`);
}
res.status(200).json({ received: true });
});from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/plexy', methods=['POST'])
def handle_webhook():
event = request.json
if event['type'] == 'payment.succeeded':
payment = event['data']
print(f"Payment {payment['id']} succeeded")
# Update order status, send confirmation email, etc.
elif event['type'] == 'payment.failed':
payment = event['data']
print(f"Payment {payment['id']} failed")
# Notify customer, retry payment, etc.
elif event['type'] == 'refund.succeeded':
refund = event['data']
print(f"Refund {refund['id']} processed")
# Update inventory, notify customer, etc.
return jsonify({'received': True}), 200func handleWebhook(w http.ResponseWriter, r *http.Request) {
var event map[string]interface{}
json.NewDecoder(r.Body).Decode(&event)
eventType := event["type"].(string)
data := event["data"].(map[string]interface{})
switch eventType {
case "payment.succeeded":
log.Printf("Payment %s succeeded", data["id"])
// Update order status, send confirmation email, etc.
case "payment.failed":
log.Printf("Payment %s failed", data["id"])
// Notify customer, retry payment, etc.
case "refund.succeeded":
log.Printf("Refund %s processed", data["id"])
// Update inventory, notify customer, etc.
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]bool{"received": true})
}Best practices
Return quickly
Return a 200 response immediately, then process the event asynchronously:
app.post('/webhooks/plexy', (req, res) => {
// Acknowledge receipt immediately
res.status(200).send('OK');
// Process asynchronously
processEventAsync(req.body);
});Handle duplicates
Events may be delivered more than once. Use the event id to ensure idempotency:
async function processEvent(event) {
// Check if already processed
const existing = await db.events.findOne({ eventId: event.id });
if (existing) {
return; // Already processed
}
// Process and record
await handleEvent(event);
await db.events.insert({ eventId: event.id, processedAt: new Date() });
}Log all events
Log every webhook for debugging and auditing:
app.post('/webhooks/plexy', (req, res) => {
console.log('Webhook received:', JSON.stringify(req.body));
// ... handle event
});See also
- Webhook Types - All available events
- Secure Webhooks - Verify signatures
- Troubleshoot - Debug delivery issues