Webhooks are the backbone of any real integration. Instead of polling the API every 30 seconds to check if a new order arrived, you register a URL and LetBuyy pushes events to you the moment they happen.
Available Event Types
- order.created, order.updated, order.fulfilled, order.cancelled
- payment.captured, payment.failed, payment.refunded
- product.created, product.updated, product.deleted
- inventory.low_stock, inventory.out_of_stock
- customer.created, customer.updated
- checkout.abandoned, checkout.completed
Registering a Webhook
POST /v1/webhooks
{
"url": "https://yourapp.com/webhooks/letbuyy",
"events": ["order.created", "payment.captured"],
"secret": "your_webhook_secret"
}Signature Verification (Critical)
Every webhook includes a X-LetBuyy-Signature header. Verify it before processing. LetBuyy signs the raw request body with your webhook secret using HMAC-SHA256.
import { createHmac, timingSafeEqual } from "crypto"
function verifyWebhook(body: string, signature: string, secret: string): boolean {
const expected = createHmac("sha256", secret)
.update(body)
.digest("hex")
const signatureBuffer = Buffer.from(signature, "hex")
const expectedBuffer = Buffer.from(expected, "hex")
return signatureBuffer.length === expectedBuffer.length &&
timingSafeEqual(signatureBuffer, expectedBuffer)
}Use timingSafeEqual
Never use string equality (===) to compare HMAC signatures. It's vulnerable to timing attacks. Always use crypto.timingSafeEqual as shown above.
Reliability Patterns
- Respond with HTTP 200 within 5 seconds — do heavy processing async
- LetBuyy retries failed deliveries: 1min, 5min, 30min, 2hr, 24hr
- Implement idempotency using the webhook ID (X-LetBuyy-Webhook-ID header)
- Store raw webhook payload before processing — enables replay on errors
- Expose a /webhooks/health endpoint for monitoring