Help Center
Browse topics

Webhooks and API basics

Send leads into NovaReps with the API, and get call data out of it with webhooks.

Updated Oct 29, 2026 · 11 min read

On this page

Find both under Integrations in the sidebar: API (/dashboard/api-webhooks) and Webhooks (/dashboard/webhook-endpoints). Both need a plan that includes them.

Two directions #

API (into NovaReps) Webhooks (out of NovaReps)
What it does You send us a lead to call We send your system a message when something happens
Who starts it Your system NovaReps
Needs An API key A public HTTPS URL

API: push a lead in #

  1. Open Integrations, then API.
  2. Enter a key name, pick an outbound agent and create the key. You are asked for your password. The key is shown once, so copy it straight away.
  3. Send it as a header on every request: Authorization: Bearer <key>.

Two endpoints push leads in. If your plan includes text conversations there is also a Chat API.

GET /api/v1/me #

Tests that your key works.

POST /api/v1/campaigns/leads #

Adds a lead to the campaign linked to your key, to be called by its outbound agent.

Field Required Notes
phone_number Yes For example +15551234567. Common formats such as (555) 123-4567 are converted for you.
first_name No Up to 100 characters.
last_name No Up to 100 characters.
curl -X POST https://YOUR-DOMAIN/api/v1/campaigns/leads \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+15551234567", "first_name": "Jane", "last_name": "Doe"}'

Replies:

  • 201 with "queued": true: the lead was added.
  • 200 with "duplicate": true: that number is already in the campaign, so it was skipped.
  • 403: the key is not allowed to send leads, or your plan does not include the API.
  • 422: the phone number could not be recognised.

There is no endpoint to list calls or agents. To get call data out, use webhooks.

Chat API: talk to your agent in writing #

Use the Chat API to let your own website, app or backend hold written conversations with any of your inbound agents. It needs a plan that includes text conversations. Each agent reply uses one of your plan's text messages.

  1. Open Integrations, then API, and find the Chat API section.
  2. Choose Create chat API key, enter a name and your password. The key is shown once, so copy it straight away.
  3. Send it on every request as Authorization: Bearer <key>. A chat key can reach every inbound agent on your account. It cannot push leads, and a lead key cannot chat.
Request What it does
POST /api/v1/agents/{agent}/conversations Starts a conversation. Optional body: message, external_user_id, phone, metadata.
POST /api/v1/conversations/{id}/messages Sends a customer message. Body: text (up to 4000 characters), optional idempotency_key.
GET /api/v1/conversations/{id} Returns the status and every message so far.
POST /api/v1/conversations/{id}/end Ends the conversation now.

Conversation IDs look like chat_01J9ZK8W2V6X4Q7T3N5R1B0M9D. An agent or conversation that is not yours returns 404.

Getting the reply #

By default the reply is written in the background. The message request returns 202 with a message_id. Then either read the conversation with GET, or subscribe to the Chat Reply Sent webhook (conversation.message).

To get the reply in the same request, add ?wait=8 (1 to 10 seconds). You get 200 with the reply when it is ready, or 202 with the current status if it is not.

curl -X POST "https://YOUR-DOMAIN/api/v1/agents/12/conversations?wait=8" \
  -H "Authorization: Bearer YOUR_CHAT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "What time do you open?", "external_user_id": "user_8841"}'

Sending the same idempotency_key again returns the same message_id and does not trigger a second reply, so retries are safe.

Handing over to a person #

If the customer asks for a person, the agent hands the conversation over. It stops replying, the conversation status becomes paused with handoff_reason set to human_requested, you get an email, and a Text Conversation Handed Off webhook (conversation.handoff) is sent with the transcript so far. New customer messages are still saved. Open the email link to reply from the conversation page in Call History (the customer sees your reply in the chat or as a text), or reply from your own tools. Replies from your team appear in GET conversation with sender set to team, and also fire conversation.message. The same happens, with reason quota_exhausted, when your plan's text messages run out.

Replies you might get #

  • 403: your plan does not include text conversations, or the key is not a chat key.
  • 404: the agent or conversation is not on your account.
  • 409: the agent is switched off, or the conversation has ended.
  • 422: a field is missing or too long.
  • 429: too many requests, or too many open conversations. Wait a moment and try again.

Webhooks: get data out #

We send a JSON POST to your HTTPS URL when something happens, such as a call ending or an appointment being booked.

NovaReps sends the full call record, including the transcript and summary, with the Transcript Ready event (transcript.ready). Call Completed (call.completed) arrives first with summary set to null.

Every message looks like this:

{
  "id": "evt_...",
  "type": "call.completed",
  "api_version": "2026-04-07",
  "created_at": "2026-01-15T14:05:00+00:00",
  "data": { "object": { } }
}

Headers sent with every request:

  • X-Webhook-Signature: proves the message came from us.
  • X-Webhook-Event: the event type.
  • X-Webhook-ID: the event ID, the same on every retry.
  • User-Agent: AIReceptionist-Webhooks/1.0

To set one up, follow the setup guide.

Events #

Calls #

Event Name in the app When it is sent
call.started Call Started Sent when a call begins (for outbound, when dialling starts). Carries the call ID, direction, channel, numbers and agent.
call.completed Call Completed Sent when a call ends. Carries the full call record. The summary is not written yet at this point, so use Transcript Ready if you need it.
transcript.ready Transcript Ready Sent a few seconds after a call ends, once the summary is written. This is the complete record: caller details, collected data, full transcript and summary.
recording.ready Recording Ready Sent when the call recording is available. Carries the full call record with the recording link (only if "Include recording link" is on).
call.missed Call Missed Sent when an inbound phone call fails, is busy, is not answered or is cancelled before a conversation happens.
call.transferred Call Transferred Sent when the AI hands the caller to a human. Carries the full call record so far and the number it was transferred to.
call.message_taken Message Taken Sent when the AI takes a message for your team. Carries the full call record including the message.
call.callback_requested Callback Requested (Inbound) Sent when a caller asks to be called back. Carries the call details and the requested time.
caller.created New Caller Sent the first time a phone number calls one of your agents. Carries the number, the caller name if known and the agent.

Appointments #

Event Name in the app When it is sent
call.appointment_booked Appointment Booked Sent the moment a booking is confirmed, without waiting for the call to end. Carries the appointment time and the booking details.
appointment.rescheduled Appointment Rescheduled Sent when a caller moves an existing appointment. Carries the call details and the new time.
appointment.cancelled Appointment Cancelled Sent when a caller cancels an appointment. Carries the call details.
appointment.confirmed Appointment Confirmed (Text Reply) Sent when a caller confirms an appointment by replying to a reminder text. Carries the call details and the appointment time.

Outbound campaigns #

Event Name in the app When it is sent
lead.created Lead Created (Inbound API) Sent when a lead arrives through the API and is queued for calling. Carries the contact and campaign.
lead.captured Lead Captured (Website Widget) Sent when a visitor submits the lead form on your website widget, before any call starts. Carries the name, email, phone, page and campaign tags. The details are typed by the visitor and not verified.
lead.qualified Lead Qualified Sent as soon as the AI records answers to your qualifying questions, before the call ends. Carries the contact and the answers.
outbound_contact.completed Outbound Contact Completed Sent when an outbound call to a contact finishes. Carries the outcome, qualifying answers, appointment details and transcript.
outbound_contact.not_reached Outbound Contact Not Reached Sent each time an attempt to reach a contact fails (no answer, failed or skipped). Carries the attempt count and whether another attempt is planned.
voicemail.detected Voicemail Detected (Outbound) Sent when an outbound call reaches voicemail. Carries the call details.
campaign.started Campaign Started Sent when a campaign starts or resumes dialling.
campaign.paused Campaign Paused Sent when a campaign is paused.
campaign.failed Campaign Failed Sent when a campaign stops because of an error.
campaign.completed Campaign Completed Sent when every contact in a campaign has been processed. Carries the totals.

Messages and compliance #

Event Name in the app When it is sent
sms.received Text Message Received Sent when someone replies by text to one of your numbers. Carries both numbers and the message text.
dnc.added Number Added to DNC List Sent when a number is added to your Do Not Call list. Carries the number, the source and the reason.
conversation.message Chat Reply Sent Sent each time the agent replies in a chat or text conversation. Carries the conversation ID and the reply, so an async Chat API client can receive replies without polling.
conversation.handoff Text Conversation Handed Off Sent when a chat or text conversation needs a person: the agent stopped replying (for example the plan's text messages ran out). Carries the conversation record and a reason code.

The recording link is null unless Include recording link is on for the endpoint. The link works without logging in and expires after 24 hours.

AI assistants (MCP): ask Claude or ChatGPT about your calls #

Connect an AI assistant to your account and ask it questions such as "How many calls did we miss this week?" or "Summarise yesterday's leads". It can read your agents, calls and text conversations, call statistics, recent callers and outbound campaigns. It cannot change anything.

  1. In NovaReps, open Integrations, then API, and find the AI assistants (MCP) card.
  2. Choose Copy URL.
  3. In Claude, open Settings, then Connectors, add a custom connector and paste the URL. In ChatGPT, add a custom app or connector and paste the same URL. In Claude Code, run claude mcp add --transport http assistant <the URL>.
  4. Sign in to NovaReps when asked. A page shows what the assistant will be able to read. Choose Allow.
  5. Ask your question in the assistant, for example "How many calls did we miss this week?".

The assistant can look up your agents, your calls and conversations (with summaries), call statistics, recent callers and your outbound campaigns. It sees the same data you see, and no more. A team member only reaches what their role allows. The recording of a call is never shared, and a transcript is only read when you ask about the exact words.

To disconnect an app, choose Revoke next to it in the Connected apps list. It loses access straight away and you can connect it again later. If a team member is suspended or removed, their connected apps stop working at once. This section needs a plan that includes API access, and the assistant must be able to reach your site over the internet.

Why can't my assistant connect? Check that you copied the full URL, that your plan includes API access, and that you are signed in as someone allowed to see the data. If it still fails, contact support.