Actions
Let the agent look up and update data in your system, securely and with user confirmation.
Actions are endpoints in your system that the agent can call during a conversation. With them, the agent goes from answering only what is in the knowledge to getting things done: "what are my upcoming appointments?", "move it to Friday", "did my payment go through?".
Customer → Nevox agent → (needs data) → POST to your URL → your response → Agent repliesNevox never gets access to your database: it only calls the URLs you register, and the agent only sees what those URLs return.
Register an action
POST /v1/agents/{agent_id}/actions · scope actions:write
curl https://api.nevox.ai/v1/agents/agt_8f2k1x/actions \
-H "Authorization: Bearer $NEVOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "upcoming_appointments",
"description": "Fetches the patient'\''s upcoming scheduled appointments. Use it when they ask about booked appointments, times or the appointment link.",
"url": "https://api.yourcompany.com/nevox/upcoming-appointments",
"mode": "read",
"parameters": {
"type": "object",
"properties": {
"limit": { "type": "integer", "description": "How many appointments to return", "default": 3 }
}
}
}'{
"id": "act_51nb",
"name": "upcoming_appointments",
"mode": "read",
"requires_confirmation": false,
"status": "active",
"signing_secret": "whsec_act_...",
"created_at": "2026-11-03T17:00:00Z"
}The signing_secret is shown only once. Use it to verify that the call came from Nevox.
| Field | Description |
|---|---|
name | Lowercase letters, numbers and _ only. Unique per agent. |
description | The most important field. This is how the agent decides when to use the action. Write it the way you would explain it to a new support rep. |
url | HTTPS required. Internal or private addresses are rejected. |
mode | read (lookup only) or write (changes something in your system) |
requires_confirmation | Always true for write. The agent confirms with the user before calling. |
parameters | JSON Schema for the arguments the agent must fill in |
requires_contact | Default true: the action only runs when the contact is identified (conversation opened through the API with contact, or widget with a session token). Without a contact, the agent says it can't look that up there. |
timeout_ms | Default 8,000, maximum 15,000 |
Other endpoints: GET /v1/agents/{agent_id}/actions, PATCH .../actions/{id}, DELETE .../actions/{id}, POST .../actions/{id}/rotate-secret.
What Nevox sends you
POST /nevox/upcoming-appointments HTTP/1.1
Host: api.yourcompany.com
Content-Type: application/json
Nevox-Signature: t=1762182000,v1=5f2b0c...
Nevox-Environment: live
Nevox-Request-Id: req_8q1m
{
"action": "upcoming_appointments",
"invocation_id": "inv_3k2l",
"agent_id": "agt_8f2k1x",
"conversation_id": "conv_7mk2p9",
"contact": {
"id": "ctc_4hq81",
"external_id": "patient_1042",
"name": "Mary Smith",
"language": "en-US"
},
"arguments": { "limit": 3 },
"confirmed": false
}What you respond
Respond 200 with JSON within 8 seconds:
{
"result": {
"appointments": [
{ "date": "2026-11-06T13:00:00Z", "doctor": "Dr. Lima", "type": "Follow-up" }
]
},
"message_for_agent": "Remind the patient to join 5 minutes early."
}| Field | Description |
|---|---|
result | Any JSON. The agent uses it to build the reply. Up to 20 KB. |
message_for_agent | Optional. An extra instruction for this reply. |
error | If something went wrong on your side: { "code": "not_found", "message": "Patient has no appointments" }. The agent explains it to the user without exposing technical details. |
If your URL doesn't respond in time or returns a 5xx error, the agent says it couldn't look it up right now and offers to hand off to a human. read actions get 1 retry; write actions are never retried automatically.
Verify the signature
Every call carries the Nevox-Signature header. Reject calls without a valid signature or older than 5 minutes.
import crypto from "node:crypto";
export function isValidSignature(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${t}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Always verify against the raw body of the request, before parsing it as JSON.
Write actions
For mode: "write", the agent always confirms first. The confirmation is checked by Nevox, not just by the AI: the call with "confirmed": true only happens if the user replied after the agent asked, and with exactly the same arguments.
"confirmed": true)Best practices:
- Use
invocation_idas the idempotency key on your side. - Check in your system whether the contact is allowed to do that. The agent should never be the only safeguard.
- For payments, discounts and account changes, prefer handing off to a human.
Test
POST /v1/agents/{agent_id}/actions/{id}/test calls your URL with sample arguments and returns what Nevox received, the response time and whether the signature was accepted.
Actions can also be registered, tested, enabled and disabled in Dashboard → Developers → Actions, which shows the latest calls (success, error and time). The history is kept for 30 days. What your system returns is not stored: only the size, the status and the time.