Webhooks
Webhooks let you receive real-time HTTP notifications when events occur in your store. Use them to sync with external systems, send custom notifications, or trigger automation workflows.
Setting up webhooks
- 1Go to Settings → Webhooks in your dashboard.
- 2Click Add Endpoint and enter your HTTPS URL.
- 3Select the events you want to subscribe to, or choose All Events.
- 4Copy your Signing Secret — you will need it to verify payloads.
Payload format
Every webhook delivery is a POST request with a JSON body. Your endpoint must return a 2xx status code within 30 seconds to confirm receipt.
{
"id": "evt_abc123",
"type": "order.completed",
"created_at": "2025-01-15T10:30:00Z",
"data": {
"id": "ord_abc123",
"email": "customer@example.com",
"product_id": "prod_abc123",
"product_title": "Premium WordPress Theme",
"amount": 29.99,
"currency": "USD",
"payment_method": "stripe",
"status": "completed"
}
}Request headers
| Header | Description |
|---|---|
| X-Sellvy-Signature | HMAC-SHA256 signature for payload verification |
| X-Sellvy-Event | The event type (e.g., order.completed) |
| X-Sellvy-Delivery | Unique delivery ID for deduplication |
Signature verification
Always verify the X-Sellvy-Signature header to ensure the webhook was sent by Sellvy and has not been tampered with. The signature is a HMAC-SHA256 hash of the raw request body using your signing secret.
import crypto from "crypto";
function verifyWebhook(req, signingSecret) {
const signature = req.headers["x-sellvy-signature"];
const body = req.rawBody; // raw request body as string
const expected = crypto
.createHmac("sha256", signingSecret)
.update(body)
.digest("hex");
if (signature !== expected) {
throw new Error("Invalid webhook signature");
}
return JSON.parse(body);
}
// Express.js example
app.post("/webhooks/sellvy", (req, res) => {
try {
const event = verifyWebhook(req, process.env.SELLVY_WEBHOOK_SECRET);
switch (event.type) {
case "order.completed":
console.log("New order:", event.data.id);
// Handle order...
break;
case "order.refunded":
console.log("Refund:", event.data.id);
break;
}
res.status(200).json({ received: true });
} catch (err) {
res.status(400).json({ error: err.message });
}
});Event types
| Event | Description |
|---|---|
| order.created | A new order has been placed (payment pending) |
| order.completed | Payment confirmed and product delivered |
| order.refunded | An order has been refunded |
| order.disputed | A payment dispute/chargeback has been filed |
| product.created | A new product was created |
| product.updated | A product was modified |
| product.deleted | A product was deleted |
| customer.created | A new customer record was created |
| customer.blacklisted | A customer was blacklisted |
| subscription.created | A new subscription started |
| subscription.renewed | A subscription was renewed |
| subscription.cancelled | A subscription was cancelled |
Retry policy
If your endpoint does not return a 2xx status code within 30 seconds, Sellvy retries the delivery with exponential backoff:
| Attempt | Delay after failure |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
| 6th retry (final) | 24 hours |
After 6 failed attempts, the webhook is marked as failed. You can manually retry from the dashboard.