Sending events¶
Most integrations start here. An external system, a CRM, a form handler, a cron job, posts arbitrary JSON to an agent, and AiFlow decides what happens next, if anything. Whether your event triggers an outbound call, a WhatsApp message, or nothing at all depends entirely on the Triggers your admin team configured on that agent. Read Triggers & events first to see how a posted payload turns into a match, or doesn't, before you send real traffic.
Endpoint¶
agent_id is the numeric id of the agent you're sending the event to. See
Agents & channels for where that id
comes from.
Authentication¶
Send an API key with the events:write scope as a bearer token:
See API keys for how to create one. If the key is scoped to
a specific agent (its agent_id isn't null), it only works against that
agent's events endpoint. Posting to a different agent's {agent_id}
returns a 403.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
event_type |
string | No | A label you choose for this event, e.g. abandoned_cart, support_ticket_created. Triggers can optionally filter on this value; see Triggers & events. |
payload |
object | No | Arbitrary JSON, whatever shape your own system produces. Defaults to {} if omitted. Trigger conditions and context_template rendering both read from this object. |
curl -X POST https://api.your-domain.com/api/v1/agents/1/events \
-H "Authorization: Bearer af_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"event_type": "abandoned_cart",
"payload": {
"customer": { "name": "Jamie", "phone": "+15557654321" },
"cart_value": 89,
"items": [1, 2, 3]
}
}'
import httpx
response = httpx.post(
"https://api.your-domain.com/api/v1/agents/1/events",
headers={"Authorization": f"Bearer {api_key}"},
json={
"event_type": "abandoned_cart",
"payload": {
"customer": {"name": "Jamie", "phone": "+15557654321"},
"cart_value": 89,
"items": [1, 2, 3],
},
},
)
response.raise_for_status()
result = response.json()
const response = await fetch(
"https://api.your-domain.com/api/v1/agents/1/events",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
event_type: "abandoned_cart",
payload: {
customer: { name: "Jamie", phone: "+15557654321" },
cart_value: 89,
items: [1, 2, 3],
},
}),
},
);
const result = await response.json();
Response¶
A successful call returns 201 Created:
| Field | Description |
|---|---|
event_id |
The id of the recorded Event, useful for support/debugging conversations with whoever administers the deployment. |
matched |
true if the event caused AiFlow to queue at least one outbound call or run a silent agent task. |
call_ids |
The id of any outbound call queued as a result of this event, empty if none was (whether because nothing matched, or because the only action taken was a WhatsApp send). |
call_ids is calls only
A matching Trigger can also send a WhatsApp message or run a silent
agent task instead of, or alongside, placing a call. See
Triggers & events for the full
set of action_type options. call_ids only ever lists phone calls,
so it's empty for a WhatsApp-only or agent-task match even though
something did happen. To confirm a WhatsApp send specifically,
subscribe to whatsapp.sent on
Webhook subscriptions instead of relying
on this response.
Rate limits¶
Event ingestion is rate-limited per client IP, 120 requests per minute by
default (the deployment operator can change this). A request over the
limit gets a 429. See Errors & rate limits
for the exact response shape.
Next¶
- Triggers & events: conditions, operators, cooldowns, everything that decides whether your event matches.
- Webhook subscriptions: get notified asynchronously when a call this event queued finishes.