API reference
Functions.
A function is an HTTP endpoint of yours that the agent can call in the middle of a conversation — a calendar lookup, an order status, a payment step. You describe it with a JSON Schema, the platform hands that description to the model as a tool, and when the model decides to use it the platform calls your URL and speaks the result.
Register a function
POST /v1/functions requires the functions:write scope and four fields: name, description, parameters and webhook_url.
curl -X POST https://api.rexa.ai/v1/functions \
-H "Authorization: Bearer vk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "check_availability",
"description": "Look up open appointment slots for a given date and service type.",
"parameters": {
"type": "object",
"properties": {
"date": { "type": "string", "format": "date" },
"service_type": { "type": "string", "enum": ["haircut", "colour"] }
},
"required": ["date"]
},
"webhook_url": "https://example.com/rexa/functions/check-availability",
"timeout_ms": 5000,
"category": "lookup",
"waiting_message": "One moment while I check the calendar..."
}'A successful create returns 201 Created:
HTTP/1.1 201 Created
{
"id": "fn_01HQTZ4P9N2K8YV5XW3R7MJBC0",
"name": "check_availability",
"description": "Look up open appointment slots for a given date and service type.",
"parameters": { "type": "object", "properties": { "...": {} } },
"webhook_url": "https://example.com/rexa/functions/check-availability",
"webhook_secret": "<43-char base64url secret, shown once>",
"webhook_secret_prefix": "b7Kq2x…",
"timeout_ms": 5000,
"category": "lookup",
"waiting_message": "One moment while I check the calendar...",
"timeout_message": null,
"enabled": true,
"created_at": "2026-08-08T14:31:02.881Z",
"updated_at": "2026-08-08T14:31:02.881Z"
}webhook_secret appears in this response and in the response to a rotate — nowhere else. Store it now; subsequent reads return only webhook_secret_prefix, the first six characters.
Fields
| Field | Type | Notes |
|---|---|---|
| name | string, required | Matches [a-z0-9_], 1–64 characters. Unique within your tenant, and immutable after create — register a new function instead of renaming. |
| description | string, required | 1–1024 characters. The model reads this to decide when to call the function, so be specific about inputs and outputs. |
| parameters | object, required | A JSON Schema (draft-07) for the arguments. Compiled at write time — an invalid schema is rejected with 400 rather than failing mid-call. |
| webhook_url | string, required | The URL the platform calls when the agent invokes the function. Must parse as a URL and use http or https. |
| timeout_ms | integer, default 10000 | Integer between 1000 and 30000. Past this, the invocation is a timeout and the agent speaks timeout_message. |
| category | enum, default "other" | One of lookup, payment, search, action, other. Selects the default waiting message. |
| waiting_message | string, max 200, nullable | Spoken while the call to your endpoint is in flight. Null falls back to the category default. |
| timeout_message | string, max 200, nullable | Spoken when the call exceeds timeout_ms. Null falls back to the platform default. |
| enabled | boolean | PATCH-only. A disabled function is not resolved at dispatch and cannot be invoked. |
Categories and spoken defaults
A network round-trip is a long silence on a phone call, so the agent says something while it waits. GET /v1/functions/categories returns this table plus the platform-wide default timeout message.
| Category | Default waiting message |
|---|---|
| lookup | Let me look that up for you. |
| payment | Processing your payment, one moment. |
| search | Searching now, just a moment. |
| action | On it, give me a second. |
| other | One moment please. |
The default timeout message is "Sorry, I'm having trouble accessing that right now."
Attach functions to a call
A dispatch can reference stored functions by id, define one-shot functions inline, or both. Inline definitions take the same fields as stored ones and carry their own webhook_secret; they are not persisted.
{
"function_ids": ["fn_01HQTZ4P9N2K8YV5XW3R7MJBC0"],
"function_inline": [
{
"name": "log_outcome",
"description": "Record the outcome the caller agreed to.",
"parameters": { "type": "object", "properties": {} },
"webhook_url": "https://example.com/rexa/functions/log-outcome",
"webhook_secret": "<your own secret>"
}
]
}Three rules are enforced at resolution time. The combined total of function_ids and function_inline is capped at 20 per call, and exceeding it returns 400. A name that appears in both the stored and inline sets returns 400 naming the collision. An id that does not belong to your tenant returns 404 with the unresolved ids in details.missing — cross-tenant ids are never distinguishable from ids that do not exist.
The secret
Each function gets its own HMAC secret, generated by the platform and stored encrypted. Use it to verify the signature on invocation requests arriving at your endpoint, so a third party who learns your URL cannot drive your function. POST /v1/functions/:id/rotate_secret issues a new one and returns the plaintext once; the previous secret stops verifying immediately, so deploy the new value before you rotate, not after.
Endpoints
| Endpoint | Scope | Notes |
|---|---|---|
| POST /v1/functions | functions:write | 201. Returns the secret once. |
| GET /v1/functions | functions:read | Cursor-paginated, newest first. limit defaults to 50 and is clamped to 100. |
| GET /v1/functions/categories | functions:read | Category list with default waiting messages. |
| GET /v1/functions/:id | functions:read | Secret is redacted to its prefix. |
| PATCH /v1/functions/:id | functions:write | Any subset of fields except name. |
| DELETE /v1/functions/:id | functions:write | 204. The function stops resolving at dispatch; the record is retained so historic invocations still resolve. |
| POST /v1/functions/:id/rotate_secret | functions:write | 200 with a new secret. |
| GET /v1/sessions/:id/function_invocations | functions:read | Up to 200 most-recent invocations for one session, newest first. |
| GET /v1/functions/:id/invocations | functions:read | Cursor-paginated across sessions. status, cursor and limit (1–200, default 50). |
Inspect what the agent actually did
Every invocation is recorded with its arguments, your response and how long you took. This is the first place to look when an agent "didn't do" something — usually it called your endpoint and got an answer it could not use.
curl "https://api.rexa.ai/v1/functions/fn_01HQTZ4P9N2K8YV5XW3R7MJBC0/invocations?status=timeout&limit=50" \
-H "Authorization: Bearer vk_live_..."{
"id": "fninv_01HQTZ4P9N2K8YV5XW3R7MJBC0",
"session_id": "sess_01HQTZ4P9N2K8YV5XW3R7MJBC0",
"function_id": "fn_01HQTZ4P9N2K8YV5XW3R7MJBC0",
"function_name": "check_availability",
"arguments": { "date": "2026-05-15", "service_type": "haircut" },
"response": { "slots": ["10:00", "14:00"] },
"duration_ms": 482,
"status": "succeeded",
"error": null,
"invoked_at": "2026-05-10T18:42:01.000Z"
}status records the outcome — for example succeeded, failed or timeout — and error carries the detail when it is not a success. function_id is null when the function was removed after the call.
Errors
| Status | Meaning |
|---|---|
| 400 | Validation error — bad name, a parameters value that is not a valid JSON Schema, a malformed URL, a timeout outside 1000–30000, or more than 20 functions on one call. |
| 401 | Missing or invalid API key. |
| 404 | The function does not exist, or belongs to another tenant. |
| 409 | A function with this name already exists for this tenant. |
Next
- Outbound calls — dispatch a call that uses these functions.
- Webhooks — lifecycle events, including function timeouts.
- Authentication — API keys and scopes.