Platform
Webhooks
Register HTTP endpoints to receive real-time events from InferexAI — low balance alerts, top-ups, rate limit hits, and more. All payloads are signed with HMAC-SHA256 so you can verify they came from InferexAI.
Available events
| Event | Fired when |
|---|
low_balance | Your wallet drops below the alert threshold you set in Dashboard → Settings. |
topup | A manual top-up payment is confirmed and credits are added to your wallet. |
rate_limit_exceeded | A request is rejected because an API key hit its RPM or TPD limit. |
key_expired | A request is rejected because the API key has passed its expires_at date. |
usage_spike | Token consumption in a short window exceeds a multiple of your normal baseline. |
Registering a webhook
Register via Dashboard → Webhooks or the portal API. You can subscribe to one or more events per endpoint.
curl https://api.inferexai.in/portal/webhooks \
-X POST \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/inferex-events",
"events": ["low_balance", "topup"]
}'
{
"id": 7,
"secret": "whsec_a1b2c3d4e5f6..."
}
Save the secret immediately — it is only returned at creation time and cannot be retrieved again. Store it in your secrets manager and use it to verify signatures.
Payload format
All events share a common envelope: event (name) and ts (Unix timestamp). Additional fields are event-specific.
{
"event": "low_balance",
"ts": 1748140800,
"user_id": 42,
"balance_cents": 5000,
"threshold_cents": 10000
}
{
"event": "topup",
"ts": 1748140800,
"user_id": 42,
"amount_cents": 100000,
"new_balance_cents": 350000
}
Request headers
Content-Typeapplication/json
X-Inferex-Eventlow_balance (the event name)
X-Inferex-Signaturesha256=<HMAC-SHA256 hex digest of the raw body>
Verifying signatures
Always verify the X-Inferex-Signature header before processing an event. Use the raw request body (before JSON parsing) and HMAC-SHA256 with the secret you received at registration.
import hashlib
import hmac
def verify_inferex_signature(body: bytes, header: str, secret: str) -> bool:
# header format: "sha256=<hexdigest>"
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)
# In your Flask / FastAPI handler:
# body = await request.body()
# sig = request.headers.get("X-Inferex-Signature")
# if not verify_inferex_signature(body, sig, WEBHOOK_SECRET):
# return 400
import { createHmac, timingSafeEqual } from "crypto";
function verifyInferexSignature(
body: string | Buffer,
header: string,
secret: string,
): boolean {
const expected = "sha256=" + createHmac("sha256", secret)
.update(body)
.digest("hex");
// timingSafeEqual requires same-length buffers
const a = Buffer.from(expected);
const b = Buffer.from(header);
return a.length === b.length && timingSafeEqual(a, b);
}
// In your Express handler:
// const sig = req.headers["x-inferex-signature"];
// if (!verifyInferexSignature(req.rawBody, sig, WEBHOOK_SECRET)) {
// return res.sendStatus(400);
// }
Delivery and reliability
Best-effort delivery
Each event is delivered once. There is no automatic retry on failure. Build your handler to be idempotent (check the ts field) in case events arrive out of order.
Timeout
Your endpoint must respond within 5 seconds. If it does not, the delivery is counted as failed.
Auto-disable
After 10 consecutive failures, the webhook is automatically disabled. Re-enable it from Dashboard → Webhooks once you fix the endpoint.
Always return 2xx
Return any 2xx status to acknowledge the event. Non-2xx responses increment the failure counter even if you processed the payload.
Managing webhooks
List your registered webhooks:
curl https://api.inferexai.in/portal/webhooks \
-H "Authorization: Bearer <session-token>"
Send a test ping to verify your endpoint is reachable:
curl https://api.inferexai.in/portal/webhooks/7/test \
-X POST \
-H "Authorization: Bearer <session-token>"