> ## Documentation Index
> Fetch the complete documentation index at: https://docs.starleads.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive Conversation Results

> Get your agents' conversation results in real-time via webhooks.

## Introduction

Starleads sends you conversation results **in real-time** via webhooks. Every time one of your AI agents completes a conversation, Starleads sends a `POST` request to a URL of your choice containing the full campaign item data — including the classification tag, the conversation transcript, an AI-generated summary, and any custom metadata you configured.

## How to set up

<Steps>
  <Step title="Log in to Starleads" icon="user">
    Go to [app.starleads.co](https://app.starleads.co) and sign in to your account.
  </Step>

  <Step title="Open your Campaign settings" icon="gear">
    Navigate to the campaign you want to receive webhooks for, and open its **Settings** panel.
  </Step>

  <Step title="Enter your webhook URL" icon="link">
    Paste the public URL of your webhook endpoint (e.g. `https://yourserver.com/webhook`). Your endpoint must accept `POST` requests and return a `200` status code.
  </Step>

  <Step title="Save and test" icon="check">
    Save the configuration. Starleads will send a test payload to your endpoint to verify it responds correctly. Once confirmed, you'll receive all future call results automatically.
  </Step>
</Steps>

## Payload

### Annotated example

The webhook sends a JSON payload representing a processed campaign item. Here's the full structure with annotations:

```jsonc theme={null}
{
  "Id": "66e47083637b020bcd9865a9",             // unique campaign item identifier
  "CampaignId": "66f1b2d0016e6d3e9353ab85",
  "CreatedAt": "2024-09-13T17:04:03.515Z",
  "ProcessedAt": "2024-09-13T17:04:05.795Z",
  "LastCallDate": "2024-09-13T17:04:05.795Z",
  "RunningStatus": "Processed",
  "AttemptCount": 1,
  "PhoneNumber": "+3300000000",
  "NextTryDate": "2024-09-13T17:04:03.515Z",
  "DataBag": {
    "id": "",
    "firstname": "Paul",
    "email": "paul@gmail.com"
  },

  // — call classification result —
  "Result": {

    // tag assigned by your reporting rules
    "Tag": {
      "_id": "Appointment_88B8DB86",
      "Name": "Appointment",
      "Color": "#1ee5a6"
    },

    // full conversation transcript
    "Conversation": {
      "_id": "24ef5fc9-9d20-4dcb-bd8b-f83e4929d36d",
      "Messages": [
        // one message per turn — only 2 shown for brevity
        {
          "Timestamp": "2024-09-13T17:04:17.000Z",
          "Role": "user",
          "Text": "oui bonjour",
          "Intent": ""
        },
        {
          "Timestamp": "2024-09-13T17:04:18.000Z",
          "Role": "assistant",
          "Text": "Oui bonjour Paul ?",
          "Intent": ""
        }
      ]
    },

    // AI-generated call summary
    "Summary": "La discussion s'est conclue par un consentement explicite de l'utilisateur pour prendre rendez-vous avec Anthony.",
    "IsSystem": false,

    // custom metadata extracted per your reporting config
    "Metadata": {
      "Informations": "L'utilisateur a déjà eu un contact avec Anthony sur LinkedIn.",
      "Date rendez-vous": "flexible"
    }
  },

  "IsArchived": false,

  // lifecycle events
  "EventList": [
    { "Type": "LaunchCall", "Date": "2024-09-13T17:04:05.824Z", "Description": "" },
    { "Type": "ProcessingResult", "Date": "2024-09-13T17:06:38.403Z", "Description": "" },
    { "Type": "EndCall", "Date": "2024-09-13T17:06:40.426Z", "Description": "ProcessingResult DONE" }
  ]
}
```

<Note>The **Tag** and **Metadata** fields are configurable in the **Reporting** section of your campaign settings.</Note>

### Complete example

Here is the complete payload for copy-paste integration:

```json theme={null}
{
  "Id": "66e47083637b020bcd9865a9",
  "CampaignId": "66f1b2d0016e6d3e9353ab85",
  "CreatedAt": "2024-09-13T17:04:03.515Z",
  "ProcessedAt": "2024-09-13T17:04:05.795Z",
  "LastCallDate": "2024-09-13T17:04:05.795Z",
  "RunningStatus": "Processed",
  "AttemptCount": 1,
  "PhoneNumber": "+3300000000",
  "NextTryDate": "2024-09-13T17:04:03.515Z",
  "DataBag": {
    "id": "",
    "firstname": "Paul",
    "email": "paul@gmail.com"
  },
  "Result": {
    "Tag": {
      "_id": "Appointment_88B8DB86",
      "Name": "Appointment",
      "Color": "#1ee5a6"
    },
    "Conversation": {
      "_id": "24ef5fc9-9d20-4dcb-bd8b-f83e4929d36d",
      "Messages": [
        {
          "Timestamp": "2024-09-13T17:04:17.000Z",
          "Role": "user",
          "Text": "oui bonjour",
          "Intent": ""
        },
        {
          "Timestamp": "2024-09-13T17:04:18.000Z",
          "Role": "assistant",
          "Text": "Oui bonjour Paul ?",
          "Intent": ""
        },
        {
          "Timestamp": "2024-09-13T17:04:52.000Z",
          "Role": "user",
          "Text": "ouais carrément bonne soirée ça m'intéresse beaucoup",
          "Intent": ""
        },
        {
          "Timestamp": "2024-09-13T17:05:35.000Z",
          "Role": "user",
          "Text": "j'aimerais bien que tu me préqualifies une liste d'appels",
          "Intent": ""
        },
        {
          "Timestamp": "2024-09-13T17:06:21.000Z",
          "Role": "user",
          "Text": "je veux bien prendre un rendez-vous avec Anthony",
          "Intent": ""
        }
      ]
    },
    "Summary": "La discussion s'est conclue par un consentement explicite de l'utilisateur pour prendre rendez-vous avec Anthony.",
    "IsSystem": false,
    "Metadata": {
      "Informations": "L'utilisateur a déjà eu un contact avec Anthony sur LinkedIn et est flexible pour le rendez-vous.",
      "Date rendez-vous": "flexible"
    }
  },
  "IsArchived": false,
  "EventList": [
    {
      "Type": "LaunchCall",
      "Date": "2024-09-13T17:04:05.824Z",
      "Description": ""
    },
    {
      "Type": "ProcessingResult",
      "Date": "2024-09-13T17:06:38.403Z",
      "Description": ""
    },
    {
      "Type": "EndCall",
      "Date": "2024-09-13T17:06:40.426Z",
      "Description": "ProcessingResult DONE"
    }
  ]
}
```

## Receive the webhook

Here's how to receive and parse the webhook payload in your application:

<CodeGroup>
  ```javascript server.js theme={null}
  // npm install express
  const express = require("express");
  const app = express();

  app.use(express.json());

  app.post("/webhook", (req, res) => {
    const item = req.body;

    // Extract key fields
    const phone = item.PhoneNumber;
    const tag = item.Result?.Tag?.Name;
    const summary = item.Result?.Summary;

    console.log(`Call processed for ${phone}`);
    console.log(`Tag: ${tag}`);
    console.log(`Summary: ${summary}`);

    // Access the conversation transcript
    const messages = item.Result?.Conversation?.Messages || [];
    messages.forEach((msg) => {
      console.log(`[${msg.Role}] ${msg.Text}`);
    });

    // Access custom metadata
    const metadata = item.Result?.Metadata || {};
    Object.entries(metadata).forEach(([key, value]) => {
      console.log(`${key}: ${value}`);
    });

    res.sendStatus(200);
  });

  app.listen(3000, () => console.log("Webhook server running on port 3000"));
  ```

  ```python server.py theme={null}
  # pip install flask
  from flask import Flask, request

  app = Flask(__name__)

  @app.route("/webhook", methods=["POST"])
  def webhook():
      item = request.get_json()

      # Extract key fields
      phone = item.get("PhoneNumber")
      tag = item.get("Result", {}).get("Tag", {}).get("Name")
      summary = item.get("Result", {}).get("Summary")

      print(f"Call processed for {phone}")
      print(f"Tag: {tag}")
      print(f"Summary: {summary}")

      # Access the conversation transcript
      messages = item.get("Result", {}).get("Conversation", {}).get("Messages", [])
      for msg in messages:
          print(f"[{msg['Role']}] {msg['Text']}")

      # Access custom metadata
      metadata = item.get("Result", {}).get("Metadata", {})
      for key, value in metadata.items():
          print(f"{key}: {value}")

      return "", 200

  if __name__ == "__main__":
      app.run(port=3000)
  ```
</CodeGroup>

## Properties

<ResponseField name="Id" type="string" required>
  Unique identifier of the campaign item.
</ResponseField>

<ResponseField name="CampaignId" type="string" required>
  Identifier of the campaign this item belongs to.
</ResponseField>

<ResponseField name="CreatedAt" type="DateTime" required>
  Date and time the campaign item was created.
</ResponseField>

<ResponseField name="ProcessedAt" type="DateTime">
  Date and time the item was processed.
</ResponseField>

<ResponseField name="LastCallDate" type="DateTime">
  Date and time of the last call attempt.
</ResponseField>

<ResponseField name="RunningStatus" type="RunningStatus" required>
  Current status of the campaign item. See [RunningStatus](#enum-runningstatus).
</ResponseField>

<ResponseField name="AttemptCount" type="int" required>
  Number of attempts made for this item.
</ResponseField>

<ResponseField name="PhoneNumber" type="string" required>
  Phone number associated with this campaign item.
</ResponseField>

<ResponseField name="NextTryDate" type="DateTime">
  Date and time of the next call or processing attempt.
</ResponseField>

<ResponseField name="DataBag" type="object">
  Dictionary containing additional information specific to this item (e.g. `firstname`, `email`). Keys correspond to the fields configured in your campaign.
</ResponseField>

<ResponseField name="Result" type="Result object">
  Result of the task associated with this item, including the tag, conversation, summary, and metadata. See [Result](#nested-objects).
</ResponseField>

<ResponseField name="IsArchived" type="boolean" required>
  Whether the campaign item has been archived.
</ResponseField>

<ResponseField name="EventList" type="TaskEvent[]">
  List of events recorded during the lifecycle of this item. See [TaskEvent](#nested-objects).
</ResponseField>

## Nested objects

<AccordionGroup>
  <Accordion title="Result" icon="bullseye" defaultOpen>
    Represents the result of a task or call associated with the campaign item.

    | Field          | Type    | Description                                                                      |
    | -------------- | ------- | -------------------------------------------------------------------------------- |
    | `Tag`          | object  | Call classification tag. See **Tag** below.                                      |
    | `Conversation` | object  | Messages exchanged during the call. See **Conversation** below.                  |
    | `Summary`      | string  | AI-generated summary of the call.                                                |
    | `IsSystem`     | boolean | Whether the result was generated by the system (e.g. no answer, invalid number). |
    | `Metadata`     | object  | Key-value pairs of custom metadata extracted from the call.                      |

    <Note>**Tag** and **Metadata** are configurable in the **Reporting** section of your campaign settings.</Note>
  </Accordion>

  <Accordion title="Tag" icon="tag">
    Categorization information assigned to the call based on your reporting rules.

    | Field   | Type   | Description                                       |
    | ------- | ------ | ------------------------------------------------- |
    | `_id`   | string | Unique identifier of the tag.                     |
    | `Name`  | string | Tag name (e.g. `Appointment`, `Not interested`).  |
    | `Color` | string | Tag color in hexadecimal format (e.g. `#1ee5a6`). |
  </Accordion>

  <Accordion title="Conversation & Message" icon="comments">
    The conversation object contains the full transcript of the call.

    **Conversation fields:**

    | Field      | Type       | Description                                         |
    | ---------- | ---------- | --------------------------------------------------- |
    | `_id`      | string     | Unique identifier of the conversation.              |
    | `Messages` | Message\[] | Ordered list of messages exchanged during the call. |

    **Message fields:**

    | Field       | Type     | Description                                                 |
    | ----------- | -------- | ----------------------------------------------------------- |
    | `Timestamp` | DateTime | Date and time of the message.                               |
    | `Role`      | string   | `user` (the prospect) or `assistant` (the Starleads agent). |
    | `Text`      | string   | Text content of the message.                                |
    | `Intent`    | string   | Detected intent of the message (can be empty).              |
  </Accordion>

  <Accordion title="TaskEvent" icon="calendar">
    Events recorded during the lifecycle of the campaign item.

    | Field         | Type     | Description                            |
    | ------------- | -------- | -------------------------------------- |
    | `Type`        | Event    | Event type. See [Event](#enum-event).  |
    | `Date`        | DateTime | Date and time when the event occurred. |
    | `Description` | string   | Optional description of the event.     |
  </Accordion>
</AccordionGroup>

## Enums

### Enum: RunningStatus

Indicates the current status of the campaign item.

| Value              | Description                                      |
| ------------------ | ------------------------------------------------ |
| `Pending`          | Waiting — the task has not started yet.          |
| `Calling`          | The task is in progress (e.g. call in progress). |
| `Processed`        | The task completed successfully.                 |
| `ProcessingResult` | The result is being processed.                   |
| `Error`            | An error occurred during processing.             |

### Enum: Event

Represents the different event types that can occur during the lifecycle of a campaign item.

| Value              | Description                         |
| ------------------ | ----------------------------------- |
| `LaunchCall`       | Call started.                       |
| `ResetCall`        | Call reset.                         |
| `EndCall`          | Call ended.                         |
| `ProcessingResult` | Result processing.                  |
| `Error`            | An error occurred.                  |
| `PickUp`           | The call was picked up by the user. |
