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

# Agent webhook

> Get every call result sent to your server, set per agent.

Each agent can send its call results to your own URL. Set a different URL per agent, and every finished call from that agent is sent there once, as a `POST` with a JSON body.

## Set it up

<Steps>
  <Step title="Open your agent">
    In the dashboard sidebar, open **Voice Agents** and click the agent you want results from.
  </Step>

  <Step title="Go to Post-call rules">
    Open **Settings & post-call**, then **Post-call rules**. Or go straight to `app.scalysis.com/call-agent/AGENT_ID?tab=call-config`.
  </Step>

  <Step title="Add your URL">
    In the **Webhook** card, paste your `https://` URL and click **Save**. The switch turns on.
  </Step>

  <Step title="Send a test">
    Click **Send test**. Your URL receives the sample payload below.
  </Step>
</Steps>

<Note>
  Each agent has its own webhook. Turn the switch off to stop sending without losing the URL.
</Note>

## When it is sent

After every finished call from that agent: campaign calls, API calls, inbound calls and test calls. Chat tests are never sent.

## Sample payload

```json call.completed theme={null}
{
  "event": "call.completed",
  "version": 1,
  "id": "run_1001",
  "occurred_at": "2026-08-18T16:01:28.000Z",
  "agent_id": 2041,
  "agent_name": "Order confirmation",
  "customer_name": "Priya Sharma",
  "customer_phone": "+919149874123",
  "started_at": "2026-08-18T16:00:00.000Z",
  "duration_sec": 88,
  "call_status": "completed",
  "call_outcome": "Order confirmed",
  "summary": "Customer confirmed the order and asked to keep the same address.",
  "transcript": "Agent: Hi Priya, this is a quick call about your order.\nCustomer: Yes, please confirm it.",
  "transcript_turns": [
    {
      "speaker": "agent",
      "text": "Hi Priya, this is a quick call about your order.",
      "timestamp": "2026-08-18T16:00:02.000Z"
    },
    {
      "speaker": "customer",
      "text": "Yes, please confirm it.",
      "timestamp": "2026-08-18T16:00:08.000Z"
    }
  ],
  "order_number": "1042",
  "answered": true,
  "direction": "outbound",
  "source": "campaign",
  "new_address": null,
  "address_change_requested": false
}
```

## Fields

<ResponseField name="event" type="string">
  Always `call.completed`.
</ResponseField>

<ResponseField name="id" type="string">
  Unique ID of this call. Use it to ignore duplicates.
</ResponseField>

<ResponseField name="occurred_at" type="string">
  When the call ended (ISO 8601, UTC).
</ResponseField>

<ResponseField name="agent_id" type="number">
  The agent that made or took the call.
</ResponseField>

<ResponseField name="agent_name" type="string">
  The agent's name.
</ResponseField>

<ResponseField name="customer_name" type="string | null">
  Customer name, if known.
</ResponseField>

<ResponseField name="customer_phone" type="string | null">
  Customer phone number.
</ResponseField>

<ResponseField name="started_at" type="string | null">
  When the call started (ISO 8601, UTC).
</ResponseField>

<ResponseField name="duration_sec" type="number">
  Talk time in seconds. `0` if not answered.
</ResponseField>

<ResponseField name="answered" type="boolean">
  `true` if the customer picked up.
</ResponseField>

<ResponseField name="call_status" type="string">
  Final call status, for example `completed`.
</ResponseField>

<ResponseField name="call_outcome" type="string | null">
  The result label from your agent's analysis, for example `Order confirmed`.
</ResponseField>

<ResponseField name="summary" type="string | null">
  Short summary of the call.
</ResponseField>

<ResponseField name="transcript" type="string">
  Full transcript as plain text, one line per turn.
</ResponseField>

<ResponseField name="transcript_turns" type="array">
  The same transcript as a list of `{ speaker, text, timestamp }`. `speaker` is `agent` or `customer`.
</ResponseField>

<ResponseField name="direction" type="string">
  `outbound` or `inbound`.
</ResponseField>

<ResponseField name="source" type="string">
  What started the call: `campaign`, `api`, `inbound`, `test` or `other`.
</ResponseField>

<ResponseField name="order_number" type="string | null">
  Order number, when the call was about an order.
</ResponseField>

<ResponseField name="new_address" type="string | null">
  New address the customer gave, if any.
</ResponseField>

<ResponseField name="address_change_requested" type="boolean">
  `true` if the customer asked to change the address.
</ResponseField>

## Receive it

Reply with any `2xx` status within 25 seconds.

<CodeGroup>
  ```js Node.js (Express) theme={null}
  app.post("/scalysis-webhook", express.json(), (req, res) => {
    const call = req.body;
    if (call.event === "call.completed") {
      console.log(call.agent_id, call.call_outcome, call.summary);
    }
    res.sendStatus(200);
  });
  ```

  ```python Python (Flask) theme={null}
  @app.post("/scalysis-webhook")
  def scalysis_webhook():
      call = request.get_json()
      if call["event"] == "call.completed":
          print(call["agent_id"], call["call_outcome"], call["summary"])
      return "", 200
  ```
</CodeGroup>

<Tip>
  Recordings are not included in the payload. Fetch them with [Fetch Call Recording](/fetch-call-recording).
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.