Webshop synchronisatie
In dit voorbeeld bouwen we een webhook endpoint dat productwijzigingen van Boom automatisch verwerkt in een webshop. Geen polling, geen cronjobs — je webshop is altijd up-to-date.
Hoe het werkt
┌──────────┐ product.updated ┌──────────────┐ UPDATE products ┌──────────┐
│ │ ──────────────────────▶ │ Webhook │ ─────────────────────▶ │ Webshop │
│ API │ │ Endpoint │ │ DB │
└──────────┘ └──────────────┘ └──────────┘
- Boom stuurt een webhook wanneer een product wijzigt
- Je endpoint verifieert de signature en verwerkt de payload
- Je webshop database wordt bijgewerkt
Stap 1: Registreer je webhook
Abonneer je op product events via de API:
Webhook registreren
POST
/v1/webhookscurl https://api.example.nl/v1/webhooks \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"notificationUrl": "https://mijn-webshop.nl/api/webhooks",
"events": [
"product.created",
"product.updated",
"product.deleted"
]
}'
Stap 2: Bouw je webhook endpoint
Express (Node.js)
Een compleet voorbeeld met signature verificatie en database synchronisatie:
import express from 'express'
import crypto from 'crypto'
import db from './db.js'
const app = express()
app.use(express.json())
// Verifieer de webhook signature
function verifySignature(req) {
const signature = req.headers['x-webhook-signature']
const hash = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex')
return hash === signature
}
app.post('/api/webhooks', async (req, res) => {
// 1. Verifieer signature
if (!verifySignature(req)) {
return res.status(401).json({ error: 'Invalid signature' })
}
const { type, payload } = req.body
// 2. Verwerk het event
switch (type) {
case 'product.created':
await db.product.create({
data: {
ean: payload.ean,
name: payload.name,
price: parseFloat(payload.price),
available: payload.status === 'available',
imageUrl: payload.imageUrl,
},
})
break
case 'product.updated':
await db.product.update({
where: { ean: payload.ean },
data: {
name: payload.name,
price: parseFloat(payload.price),
available: payload.status === 'available',
imageUrl: payload.imageUrl,
},
})
break
case 'product.deleted':
await db.product.delete({
where: { ean: payload.ean },
})
break
}
// 3. Bevestig ontvangst
res.sendStatus(200)
})
app.listen(3000)
ASP.NET Minimal API
using System.Security.Cryptography;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
bool VerifySignature(HttpRequest request, string body)
{
var signature = request.Headers["x-webhook-signature"].ToString();
var secret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET");
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var hash = Convert.ToHexString(
hmac.ComputeHash(Encoding.UTF8.GetBytes(body))
).ToLower();
return hash == signature;
}
app.MapPost("/api/webhooks", async (HttpContext context, AppDbContext db) =>
{
var body = await new StreamReader(context.Request.Body).ReadToEndAsync();
if (!VerifySignature(context.Request, body))
return Results.Unauthorized();
var evt = JsonSerializer.Deserialize<WebhookEvent>(body);
switch (evt.Type)
{
case "product.created":
db.Products.Add(new Product {
Ean = evt.Payload.Ean,
Name = evt.Payload.Name,
Price = evt.Payload.Price,
Available = evt.Payload.Status == "available"
});
break;
case "product.updated":
var product = await db.Products.FindAsync(evt.Payload.Ean);
if (product != null) {
product.Name = evt.Payload.Name;
product.Price = evt.Payload.Price;
product.Available = evt.Payload.Status == "available";
}
break;
case "product.deleted":
var toDelete = await db.Products.FindAsync(evt.Payload.Ean);
if (toDelete != null) db.Products.Remove(toDelete);
break;
}
await db.SaveChangesAsync();
return Results.Ok();
});
app.Run();
Stap 3: Test je integratie
Gebruik de API om een product aan te maken of bij te werken en verifieer dat je webhook endpoint de notificatie ontvangt:
Test: product bijwerken
# Update een product — dit triggert een product.updated webhook
curl -X PUT https://api.example.nl/v1/products/9789493113862 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"price": "34.95"}'
Controleer je webhook endpoint logs om te verifiëren dat de product.updated notificatie is ontvangen en verwerkt.
Best practices
- Verifieer altijd de signature — accepteer geen requests zonder geldige
x-webhook-signature - Retourneer snel een 200 — verwerk zware taken asynchroon (queue) om timeouts te voorkomen
- Maak je handler idempotent — dezelfde notificatie kan meerdere keren worden bezorgd
- Log ontvangen events — handig voor debugging en auditing
- Gebruik HTTPS — webhook URLs moeten altijd HTTPS zijn
Volgende stappen
- Registreer webhooks voor meer event types (orders, shipments, invoices)
- Bekijk het PIM-integratie voorbeeld om de andere kant van de koppeling te bouwen
- Lees over security voor meer details over signature verificatie