The inbound endpoint
Every app exposes one normalized inbound endpoint. Any channel worker or webhook bridge (Telegram bots, SMS gateways, your own chat widget) POSTs a message envelope and gets back the app character's reply — grounded in the app's knowledge baseand that end user's memory, metered from the app wallet.
POST
/api/apps/{app_id}/channels/inboundEnvelope format
| Name | Type | Description |
|---|---|---|
channelRequired | string | Channel identifier, e.g. telegram or web. |
end_user_refRequired | string | Stable reference for the end user on that channel — keys their per-user memory. |
messageRequired | string | The inbound message text. |
mediaOptional | array | Optional media attachments on channels that support them. |
curl -X POST https://router.intelli-verse-x.ai/api/apps/APP_ID/channels/inbound \
-H "Authorization: Bearer $INTELLIVERSE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "telegram",
"end_user_ref": "tg:123456789",
"message": "What are your opening hours?"
}'Webhook signatures
Bridges that shouldn't hold an API key authenticate with a signed webhook instead. Configure a webhook secret on the channel, then sign each request:
X-IV-Timestamp— the request timestamp.X-IV-Signature— hexHMAC-SHA256(webhook_secret, "<timestamp>.<raw body>").
import { createHmac } from "node:crypto";
const timestamp = Date.now().toString();
const body = JSON.stringify(envelope);
const signature = createHmac("sha256", process.env.CHANNEL_WEBHOOK_SECRET)
.update(`${timestamp}.${body}`)
.digest("hex");
await fetch("https://router.intelli-verse-x.ai/api/apps/APP_ID/channels/inbound", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-IV-Timestamp": timestamp,
"X-IV-Signature": signature,
},
body,
});Note
When the signature header is present it wins over Bearer auth — the signature already proves channel ownership. Signature verification is timing-safe and the channel must be
active. Channel setup lives under Dashboard → Apps → Channels; the product tour is on /channels.