> For the complete documentation index, see [llms.txt](https://docs.spara.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.spara.com/developers/spara-api/webhooks.md).

# Webhooks

The Spara platform offers powerful integration capabilities through both outbound webhooks and a [Web API](/developers/spara-api/web-api.md).

Webhooks provide real-time notifications of lead events via `POST` requests to a customer-defined endpoint, enabling automated workflows, external system synchronization, and timely responses to key updates. APIs allow customers to update and enrich lead data, manage user information, and influence the behavior of our AI engine - supporting deep, flexible integrations. All API interactions must be conducted over `HTTPS` to ensure secure communication.

Both webhooks and API support basic data types via JSON. These types are not explicitly identified in request values.

* `string`, ex. `"John Doe"`
* `integer`, ex. `100`
* `boolean`, i.e. `true` or `false`

Malformed values will be rejected, ex. `John Doe`. Take care to not cast integer or boolean values as strings, ex. `"100"`.

{% hint style="warning" %}
Important: Spara does not recommend using webhooks to update information also being updated by a native integration, as this may result in data conflicts or unexpected behavior.

For example, using information from webhooks to update Salesforce records in conjunction with Spara's native Salesforce integration.
{% endhint %}

### Schema

Spara models leads as a single object with any number of arbitrary fields. For example, if you configure Spara to ask your leads the question "What industry is your company in?" you may decide to name that field `industry`.

The following fields are standard for all leads:

```
# Info about the lead.
email(string)
company_name (string)
first_name (string)
last_name (string)
phone_number (string)
job_title (string)
num_employees (integer)
```

In addition, some leads may have an assigned sales rep in Salesforce:

```
# Info about Salesforce objects connected to the lead. All fields are strings.
sales_rep_name
salesforce_account_id- The unique identifier of the Salesforce account
salesforce_account_name - The name of the Salesforce account which usually represents the company name
salesforce_account_owner_email - The email address of the Salesforce account owner (account's default sales rep)
salesforce_account_owner_id - The unique identifier of the Salesforce account owner
salesforce_account_owner_name - The first & last names of the Salesforce account owner
salesforce_account_website - The website URL associated with the Salesforce account
salesforce_assigned_sales_rep_email - The email address of the lead's assigned sales rep
salesforce_assigned_sales_rep_id - The unique identifier of the lead's assigned sales rep
salesforce_assigned_sales_rep_name
```

### Webhook Registration & Events

Each customer can register one or more webhook endpoints in the Settings > [Webhooks](https://app.spara.co/organization/api-webhooks) page. Use "Add Webhook" to register additional endpoints, and the trash icon to remove one. Each endpoint has its own URL and its own set of subscribed events, so you can route different events to different destinations.

The following information is required to register a webhook:<br>

* **Webhook URL**: A valid `HTTPS` endpoint where webhook payloads will be sent. Test payloads may be triggered by clicking the "Test" button.
* **API Key(s)**: Customers must create at least one API Key to enable outbound webhooks. API Keys are shared across all of an organization's webhook endpoints.
* **Events:** Select which events trigger webhook notifications for that endpoint.
  * See table below for all event types.
  * NB: If multiple events are triggered at the same time, they are grouped into a single webhook call.
  * Each endpoint only receives the events it is subscribed to; an event is delivered to every endpoint subscribed to it.

<table data-full-width="true"><thead><tr><th>Event Name</th><th>When the webhook event is triggered</th><th>Example</th></tr></thead><tbody><tr><td><code>Lead Created</code></td><td>A new lead is created.</td><td></td></tr><tr><td><code>Spara Fact Updated</code></td><td>Spara learns a new fact from conversing with the lead.</td><td>A lead sends the message "My email is joe@test.com."</td></tr><tr><td><code>External Fact Updated</code></td><td>Spara learns of a new fact via query parameters or API.<br><br>NB: Will not trigger when a new lead is created if <code>Lead created</code> is not selected.</td><td></td></tr><tr><td><code>Lead Enrichment Fact Updated</code></td><td>Spara learns of a new fact via lead enrichment.</td><td></td></tr><tr><td><code>Lead Message Sent</code></td><td>The lead sends a message.</td><td></td></tr><tr><td><code>AI Message Sent</code></td><td>Spara Chat AI sends a message.</td><td></td></tr><tr><td><code>Human Message Sent</code></td><td>Human uses "Manual Mode" to send a message to the lead.</td><td></td></tr><tr><td><code>Voice Call Ended</code></td><td>A voice call with the lead ends. The payload includes call timestamps, the Voice agent that handled the call, a short summary, and the transcript.</td><td></td></tr></tbody></table>

<figure><img src="/files/DDU5IfN999gPXmdTzHzH" alt=""><figcaption></figcaption></figure>

### Differentiating voice, chat, and email events

Every webhook payload includes a `source` field describing which channel produced the event. Filter on this field to route events in your handler:

| Source  | Channel            |
| ------- | ------------------ |
| `voice` | Voice call         |
| `chat`  | Chat conversation  |
| `email` | Email conversation |

### Delivery Format

Each webhook is sent as a JSON payload in the body of an HTTP POST request. All known fields about a lead will be returned in each webhook event. The standard format is as follows:

```json
POST /your-endpoint
Content-Type: application/json
X-API-Key: <API Key>

// lead.created
{
  "event": "lead.created",
  "timestamp": "2025-09-18T18:48:08Z",
  "object": "lead",
  "id": "GTvcBRZd",
  "url": "https://app.spara.co/conversations/GTvcBRZd",
  "created_at": "2025-09-18T18:48:08Z",
  "updated_at": "2025-09-18T18:48:08Z",
  "data": {
    "ip_country": "US",
    "ip_region": "New York",
    "ip_city": "New York",
    "current_url": "https://www.my-site.co/chat/jJyVt7TQ5",
    "conversation_url": "https://app.spara.co/conversations/GTvcBRZd"
  },
  "conversation": {
    "created_at": "2025-09-18T18:48:08Z",
    "initial_url": "https://www.my-site.co/chat/jJyVt7TQ5",
    "device": "DESKTOP",  // most recent device used
    "initial_device": "DESKTOP",  // first device used
    "messages": []
  }
}

// lead.updated
{
  "event": "lead.updated",
  "timestamp": "2025-09-18T18:48:38Z",
  "object": "lead",
  "id": "GTvcBRZd",
  "url": "https://app.spara.co/conversations/GTvcBRZd",
  "created_at": "2025-09-18T18:48:08Z",
  "updated_at": "2025-09-18T18:48:38Z",
  "data": {
    "ip_country": "US",
    "ip_region": "New York",
    "ip_city": "New York",
    "current_url": "https://www.my-site.co/chat/jJyVt7TQ5",
    "conversation_url": "https://app.spara.co/conversations/GTvcBRZd",
    "first_name": "Jane"
  },
  "conversation": {
    "created_at": "2025-09-18T18:48:08Z",
    "initial_url": "http://localhost:5001/chat/jJyVt7TQ5",
    "device": "DESKTOP",  // most recent device used
    "initial_device": "DESKTOP",  // first device used
    "messages": [
      {
        "sent_by": "AI",
        "created_at": "2025-09-18T18:48:08Z",
        "text": "Hi, any questions I can help with?",
        "asset": "ACME Overview.mp4"
      },
      {
        "sent_by": "LEAD",
        "created_at": "2025-09-18T18:48:13Z",
        "text": "hi my name is Jane"
      },
      {
        "sent_by": "AI",
        "created_at": "2025-09-18T18:48:16Z",
        "text": "Hello! How can I assist you with Acme-Eng's services today?"
      },
      {
        "sent_by": "MANUAL",
        "created_at": "2025-09-18T18:48:38Z",
        "text": "Hi this is your sales rep. I am taking over the conversation."
      }
    ]
  }
}
```

### Security

To ensure secure transmission, all webhook payloads include the customer's oldest active API Keys in the `X-API-Key` header. Customers should verify the API Key before trusting the contents of the webhook.

Webhook URLs must use `HTTPS`. Plain `HTTP` endpoints will be rejected during registration.

### Retry Policy

If a webhook delivery fails (i.e., a non-2xx HTTP response or a timeout), our system will automatically retry the request using exponential backoff. Up to 2 retries (in addition to the original attempt) will be made. Customers are encouraged to design their endpoints to respond quickly and handle retries idempotently.

### Best Practices

* Validate the API Key of incoming webhook requests before processing.
* Respond to webhooks with a `200 OK` status as quickly as possible.
* Offload heavy processing to background jobs or message queues.
* Log and monitor webhook delivery attempts to aid in troubleshooting.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.spara.com/developers/spara-api/webhooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
