Appearance
Catalog Webhooks
Receive real-time push notifications when your product catalog changes. Instead of polling /v2/catalog, register a webhook endpoint and your backend is notified immediately when products, options, categories, or groups are created, updated, or deleted.
Overview
IIMMPACT ──POST──▶ Your Webhook URL
│
├── Verify X-Webhook-Signature (HMAC-SHA256)
├── Process event (upsert/delete in your DB)
└── Return 200 OK- One event per request — each HTTP POST contains a single event
- Signed with HMAC-SHA256 — verify every request using your webhook secret
- Automatic retries — failed deliveries are retried with exponential backoff
Webhook Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET | /v2/reseller/catalog/webhook | Get current webhook configuration |
POST | /v2/reseller/catalog/webhook | Register webhook URL and generate secret |
PUT | /v2/reseller/catalog/webhook | Enable or disable webhook delivery |
DELETE | /v2/reseller/catalog/webhook | Remove webhook configuration and disable delivery |
POST | /v2/reseller/catalog/webhook/rotate | Rotate webhook secret |
All endpoints require API Key Authentication with HMAC signing.
Registration
Register your HTTPS endpoint to start receiving catalog change notifications:
bash
curl -X POST "https://api.iimmpact.com/v2/reseller/catalog/webhook" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Timestamp: 1704067200" \
-H "X-Nonce: req-1704067200-a1b2c3d4e5f6" \
-H "X-Signature: v1=BASE64_HMAC_SIGNATURE" \
-d '{ "webhook_url": "https://your-api.com/iimmpact/catalog-webhook" }'The response includes your webhook secret. Store it securely — it cannot be retrieved after this initial response. If lost or compromised, use the rotate endpoint to generate a new one.
HTTPS Required
Your webhook URL must use HTTPS. HTTP endpoints are rejected.
Event Types
Your webhook receives all event types automatically. Each HTTP request contains one event.
| Event | Resource | Description |
|---|---|---|
product.created | products | New product added |
product.updated | products | Product details changed |
product.deleted | products | Product deactivated |
option.created | options | New option added |
option.updated | options | Option details changed |
option.deleted | options | Option deactivated |
category.created | categories | New category added |
category.updated | categories | Category details changed |
category.deleted | categories | Category deactivated |
group.created | groups | New group added |
group.updated | groups | Group details changed |
group.deleted | groups | Group deactivated |
Payload Format
Each webhook sends a POST request with this JSON structure:
json
{
"type": "product.updated",
"resource": "products",
"id": "CELCOM10",
"timestamp": "2024-01-15T10:30:00.000Z",
"data": {
"product_code": "CELCOM10",
"product_category_code": "MOBILE_PREPAID",
"name": "Celcom Prepaid",
"display_name": "Celcom Prepaid Reload",
"image_url": "https://dashboard.iimmpact.com/img/CELCOM10.png",
"processing_time": "instant",
"is_active": true
}
}| Field | Type | Description |
|---|---|---|
type | string | Event type (e.g. product.updated, option.created) |
resource | string | Resource kind: products, options, categories, groups |
id | string | Identifier of the affected resource |
timestamp | string | ISO 8601 timestamp of when the change occurred |
data | object|null | Full resource data, or null for delete events |
Delete Events
For *.deleted events, the data field is null. Use the id field to remove the resource from your local store.
Signature Verification
All webhook requests include an X-Webhook-Signature header. Always verify the signature before processing the event to confirm it originated from IIMMPACT and was not tampered with.
The header format is sha256=<hex_digest>, computed as HMAC-SHA256 of the raw request body using your webhook secret.
typescript
import crypto from "crypto";
function verifyWebhookSignature(
rawBody: string,
signature: string | null,
secret: string,
): boolean {
if (!signature) return false;
const providedSig = signature.startsWith("sha256=")
? signature.slice(7)
: signature;
const expectedSig = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
try {
return crypto.timingSafeEqual(
Buffer.from(providedSig, "hex"),
Buffer.from(expectedSig, "hex"),
);
} catch {
return false;
}
}Use Raw Body
Verify the signature against the raw request body bytes, not a parsed-and-re-serialized JSON object. Re-serializing can change key order or whitespace, causing a mismatch.
Handling Webhooks
A complete webhook handler should: verify the signature, process the event, and return 200 OK.
typescript
app.post("/iimmpact/catalog-webhook", async (req, res) => {
// 1. Verify signature
const signature = req.headers["x-webhook-signature"];
if (!verifyWebhookSignature(req.rawBody, signature, WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// 2. Process event
const { type, resource, id, data } = req.body;
switch (type) {
case "product.created":
case "product.updated":
await db.products.upsert({ id, ...data });
break;
case "product.deleted":
await db.products.deactivate(id);
break;
case "option.created":
case "option.updated":
await db.options.upsert({ id, ...data });
break;
case "option.deleted":
await db.options.deactivate(id);
break;
// Handle category.* and group.* similarly
}
// 3. Return 200 to acknowledge receipt
res.status(200).send("OK");
});Respond Quickly
Return 200 OK as fast as possible. If your processing is slow, accept the webhook, queue the work, and process asynchronously. Slow responses may be treated as failures and trigger retries.
Retry Policy
Failed deliveries are retried with exponential backoff. After 5 failed attempts, the event is dropped.
| Attempt | Delay After Failure |
|---|---|
| 1 | Immediate |
| 2 | ~1 minute |
| 3 | ~2 minutes |
| 4 | ~4 minutes |
| 5 | ~8 minutes |
What Triggers Retries
| Response | Retried? | Reason |
|---|---|---|
5xx (server error) | Yes | Transient failure |
408 (request timeout) | Yes | Transient failure |
429 (too many requests) | Yes | Rate limited |
| Connection error / DNS failure | Yes | Network issue |
4xx (except 408, 429) | No | Permanent failure |
Permanent Failures
4xx responses (except 408 and 429) are treated as permanent failures and are not retried. Ensure your endpoint returns 200 on success and only returns 4xx for genuinely invalid requests (e.g. 401 for bad signatures).
Secret Rotation
Your webhook secret is stored securely and cannot be retrieved after initial registration. If compromised or lost, rotate it:
bash
curl -X POST "https://api.iimmpact.com/v2/reseller/catalog/webhook/rotate" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Timestamp: 1704067200" \
-H "X-Nonce: req-1704067200-a1b2c3d4e5f6" \
-H "X-Signature: v1=BASE64_HMAC_SIGNATURE"After rotation, the old secret is immediately invalidated. Update your webhook handler with the new secret before the next delivery.
Enable / Disable
Temporarily pause webhook delivery without removing your configuration:
bash
# Disable
curl -X PUT "https://api.iimmpact.com/v2/reseller/catalog/webhook" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Timestamp: 1704067200" \
-H "X-Nonce: req-1704067200-a1b2c3d4e5f6" \
-H "X-Signature: v1=BASE64_HMAC_SIGNATURE" \
-d '{ "enabled": false }'
# Re-enable
curl -X PUT "https://api.iimmpact.com/v2/reseller/catalog/webhook" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Timestamp: 1704067200" \
-H "X-Nonce: req-1704067200-a1b2c3d4e5f6" \
-H "X-Signature: v1=BASE64_HMAC_SIGNATURE" \
-d '{ "enabled": true }'Events During Downtime
Events that occur while webhooks are disabled are not queued. When re-enabled, fetch /v2/catalog to sync any missed changes.
Remove Webhook
Permanently remove your webhook configuration:
bash
curl -X DELETE "https://api.iimmpact.com/v2/reseller/catalog/webhook" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Timestamp: 1704067200" \
-H "X-Nonce: req-1704067200-a1b2c3d4e5f6" \
-H "X-Signature: v1=BASE64_HMAC_SIGNATURE"This deletes the URL, secret, and stops all deliveries. You can re-register at any time with POST.
