Webhooks
Webhooks allow your application to receive real-time HTTP POST notifications about events happening on the Elixpo Accounts platform (e.g. user signup, oauth app deletion).
Supported Events
You can configure webhook subscriptions in the Developer Portal for any of the following event types:
| Event Code | Description |
|---|---|
user.created | Triggered when a new user registers on the platform. |
user.updated | Triggered when user profile data or username is updated. |
user.deleted | Triggered when a user deletes their account. Register a webhook_url and subscribe to this to purge the user's data and stop any billing — e.g. Elixpo Pay cancels their subscriptions and revokes entitlements on this event. |
auth.login_success | Triggered on a successful user login. |
auth.login_failed | Triggered on a failed login attempt (suspicious activity tracker). |
oauth.app_created | Triggered when a new developer registers an OAuth application. |
Payload Format
All webhook deliveries send a JSON POST request containing standard fields:
{
"id": "evt_7f1c1a2b3c4d",
"event": "user.created",
"createdAt": "2026-06-07T18:48:21.000Z",
"data": {
"id": "u_9b7bf7c2-866e-ee9d-3e48-ee9d3e488297",
"email": "newuser@example.com",
"displayName": "swift-falcon",
"createdAt": "2026-06-07T18:48:20.000Z"
}
}Signature Verification
Every webhook request includes an X-Webhook-Signature header. This is a hex-encoded HMAC SHA256 signature calculated from the raw string payload body and your webhook signing secret.
Always verify this signature using a constant-time comparison helper (like Node's crypto.timingSafeEqual) before processing.
const crypto = require("crypto");
app.post("/webhook-endpoint", (req, res) => {
const signature = req.headers["x-webhook-signature"];
const rawBody = JSON.stringify(req.body); // Ensure you have access to the raw payload string
const webhookSecret = process.env.WEBHOOK_SECRET;
if (!signature) {
return res.status(401).send("Missing signature");
}
// Generate expected signature
const expectedSignature = crypto
.createHmac("sha256", webhookSecret)
.update(rawBody)
.digest("hex");
// Constant-time comparison to prevent timing attacks
const isValid = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
if (!isValid) {
return res.status(403).send("Invalid signature");
}
// Handle the verified webhook event...
console.log("Verified event:", req.body.event);
res.status(200).send("OK");
});Delivery & Retry Policy
Your server must respond with a status code in the 2xx range within 5 seconds to mark a delivery as successful. If the delivery fails (e.g. timeout or non-2xx status), the webhook system will retry up to 5 times with an exponential backoff spacing.
