Agent skill
Celitech Webhooks Skill
Receive and verify Celitech webhooks (delivered via Svix). Use when setting up Celitech eSIM webhook handlers, debugging svix-signature verification, or handling events like consumption.threshold.reached, esim.downloaded, esim.installed, esim.enabled, esim.disabled, and esim.deleted.
Install this skill
npx skills add hookdeck/webhook-skills --skill celitech-webhooks
Celitech (B2B eSIM connectivity API) sends webhooks through Svix for data-usage thresholds and eSIM lifecycle changes. Every delivery is an HTTP POST with a JSON body and three signature headers: svix-id, svix-timestamp, and svix-signature. Webhooks are enabled per account by Celitech on request.
When to Use This Skill
- How do I receive Celitech webhooks?
- How do I verify Celitech webhook signatures (
svix-signature)? - How do I handle
consumption.threshold.reachedoresim.installedevents? - Why is my Celitech webhook signature verification failing?
- Why are Hookdeck retries of Celitech webhooks rejected with a timestamp error?
Verification (core)
Signed content is {svix-id}.{svix-timestamp}.{raw body}. Celitech signs it with HMAC-SHA256 using the base64-decoded secret (the part after whsec_), base64-encodes the result, and sends one or more space-delimited v1,<signature> entries. Use the official svix library; it compares every v1 entry in constant time.
import { Webhook } from 'svix'; // svix 2.x is ESM-only
// Prefer svix-*; fall back to webhook-* when svix-id is absent (as Hookdeck does)
const p = req.headers['svix-id'] ? 'svix' : 'webhook';
const headers = {
'svix-id': req.headers[`${p}-id`],
'svix-timestamp': req.headers[`${p}-timestamp`],
'svix-signature': req.headers[`${p}-signature`],
};
// rawBody: the raw Buffer/string (express.raw({ type: '*/*' })), never re-serialized JSON
new Webhook(process.env.CELITECH_WEBHOOK_SECRET).verify(rawBody, headers); // throws on failure
const event = JSON.parse(rawBody.toString('utf8')); // parse only after verify passes
from svix.webhooks import Webhook, WebhookVerificationError
wh = Webhook(os.environ["CELITECH_WEBHOOK_SECRET"])
wh.verify(raw_body, {"svix-id": msg_id, "svix-timestamp": ts, "svix-signature": sig})
Missing headers or a bad signature: return 400. If CELITECH_WEBHOOK_SECRET is unset, fail closed (the examples return 500).
Timestamp window and retries. The
svixlibrary always enforces a fixed 5-minute timestamp window. Hookdeck retries and replays resend the original timestamp, so the library rejects any retry or replay that arrives after 5 minutes. If you receive through Hookdeck, use the manual verifier in references/verification.md, where the window can be dropped or widened.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Common Event Types
The body is flat (no data wrapper): a top-level type plus the event's fields.
| Event | Triggered When | Fields |
|---|---|---|
consumption.threshold.reached | A purchase's data usage hits a notification threshold | purchaseId, dataLimitInGB, dataUsageRemainingInGB, actualPercentage, notificationPercentage |
esim.downloaded | The eSIM profile is downloaded to the device | iccid |
esim.installed | The eSIM profile is installed on the device | iccid |
esim.enabled | The eSIM is enabled on the device | iccid |
esim.disabled | The eSIM is disabled on the device | iccid |
esim.deleted | The eSIM is deleted from the device | iccid |
These six are the documented events; the list may not be exhaustive. See references/overview.md.
Environment Variables
# Developers → Webhooks → your endpoint (Svix secret, whsec_ + base64)
CELITECH_WEBHOOK_SECRET=whsec_xxxxx
The secret page does not show the literal value in Celitech's docs; Svix endpoint secrets are whsec_<base64>, which is unconfirmed for Celitech specifically. Store the full value, including whsec_.
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 celitech --path /webhooks/celitech
Register the tunnel URL under Developers → Webhooks in the Celitech dashboard.
Reference Materials
- references/overview.md - Celitech webhook concepts, events, payloads, retries
- references/setup.md - Register an endpoint and get the signing secret
- references/verification.md - Signature verification, header fallback, manual verifier