> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.vapi.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server.

# Structured outputs

> Extract structured, schema-defined data from voice calls using AI-powered analysis. Covers field types, extraction timing, limitations, and HIPAA storage behavior.

## Overview

Structured outputs enable automatic extraction of specific information from voice conversations in a structured format. Define your data requirements using JSON Schema, and we will identify and extract that information from your calls.

**Key benefits:**

* Extract customer information, appointments, and orders automatically
* Validate data with JSON Schema constraints
* Use any AI model for extraction (OpenAI, Anthropic, Google, Azure)
* Reuse extraction definitions across multiple assistants

## How it works

#### Define your schema

Create a JSON Schema that describes the data you want to extract

#### Create structured output

Use the API to create a reusable structured output definition

#### Link to assistants

Connect the structured output to one or more assistants

#### Extract from calls

Data is automatically extracted after each call and stored in call artifacts

## Quick start

### Create a structured output

**`TypeScript (Server SDK)`**

```typescript title="TypeScript (Server SDK)"
import { VapiClient } from '@vapi-ai/server-sdk';

const vapi = new VapiClient({ token: process.env.VAPI_API_KEY });

const structuredOutput = await vapi.structuredOutputs.create({
  name: "Customer Info",
  type: "ai",
  description: "Extract customer contact information",
  schema: {
    type: "object",
    properties: {
      firstName: {
        type: "string",
        description: "Customer's first name"
      },
      lastName: {
        type: "string",
        description: "Customer's last name"
      },
      email: {
        type: "string",
        format: "email",
        description: "Customer's email address"
      },
      phone: {
        type: "string",
        pattern: "^\\+?[1-9]\\d{1,14}$",
        description: "Phone number in E.164 format"
      }
    },
    required: ["firstName", "lastName"]
  }
});

console.log('Created structured output:', structuredOutput.id);
```

**`Python (Server SDK)`**

```python title="Python (Server SDK)"
import os
from vapi import Vapi

vapi = Vapi(token=os.environ['VAPI_API_KEY'])

structured_output = vapi.structured_outputs.create(
    name="Customer Info",
    type="ai",
    description="Extract customer contact information",
    schema={
        "type": "object",
        "properties": {
            "firstName": {
                "type": "string",
                "description": "Customer's first name"
            },
            "lastName": {
                "type": "string",
                "description": "Customer's last name"
            },
            "email": {
                "type": "string",
                "format": "email",
                "description": "Customer's email address"
            },
            "phone": {
                "type": "string",
                "pattern": "^\\+?[1-9]\\d{1,14}$",
                "description": "Phone number in E.164 format"
            }
        },
        "required": ["firstName", "lastName"]
    }
)

print(f"Created structured output: {structured_output.id}")
```

**`cURL`**

```bash title="cURL"
curl -X POST https://api.vapi.ai/structured-output \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Info",
    "type": "ai",
    "description": "Extract customer contact information",
    "schema": {
      "type": "object",
      "properties": {
        "firstName": {
          "type": "string",
          "description": "Customer'\''s first name"
        },
        "lastName": {
          "type": "string",
          "description": "Customer'\''s last name"
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "Customer'\''s email address"
        },
        "phone": {
          "type": "string",
          "pattern": "^\\+?[1-9]\\d{1,14}$",
          "description": "Phone number in E.164 format"
        }
      },
      "required": ["firstName", "lastName"]
    }
  }'
```

### Link to an assistant

Add the structured output ID to your assistant's configuration:

**`TypeScript (Server SDK)`**

```typescript title="TypeScript (Server SDK)"
const assistant = await vapi.assistants.create({
  name: "Customer Support Agent",
  // ... other assistant configuration
  artifactPlan: {
    structuredOutputIds: [structuredOutput.id]
  }
});
```

**`Python (Server SDK)`**

```python title="Python (Server SDK)"
assistant = vapi.assistants.create(
    name="Customer Support Agent",
    # ... other assistant configuration
    artifact_plan={
        "structuredOutputIds": [structured_output.id]
    }
)
```

**`cURL`**

```bash title="cURL"
curl -X POST https://api.vapi.ai/assistant \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Support Agent",
    "artifactPlan": {
      "structuredOutputIds": ["output-id-here"]
    }
  }'
```

### Access extracted data

After a call completes, retrieve the extracted data:

**`TypeScript (Server SDK)`**

```typescript title="TypeScript (Server SDK)"
const call = await vapi.calls.get(callId);

// Access structured outputs from call artifacts
const outputs = call.artifact?.structuredOutputs;

if (outputs) {
  for (const [outputId, data] of Object.entries(outputs)) {
    console.log(`Output: ${data.name}`);
    console.log(`Result:`, data.result);
    
    // Handle the extracted data
    if (data.result) {
      // Process successful extraction
      const { firstName, lastName, email, phone } = data.result;
      // ... save to database, send notifications, etc.
    }
  }
}
```

**`Python (Server SDK)`**

```python title="Python (Server SDK)"
call = vapi.calls.get(call_id)

# Access structured outputs from call artifacts
outputs = call.artifact.get('structuredOutputs', {})

for output_id, data in outputs.items():
    print(f"Output: {data['name']}")
    print(f"Result: {data['result']}")
    
    # Handle the extracted data
    if data['result']:
        # Process successful extraction
        result = data['result']
        first_name = result.get('firstName')
        last_name = result.get('lastName')
        email = result.get('email')
        phone = result.get('phone')
        # ... save to database, send notifications, etc.
```

**`Webhook Response`**

```javascript title="Webhook Response"
// In your webhook handler
app.post('/vapi/webhook', (req, res) => {
  const { message } = req.body;
  
  if (message.type === 'end-of-call-report') {
    const outputs = message.artifact?.structuredOutputs;
    
    if (outputs) {
      Object.entries(outputs).forEach(([outputId, data]) => {
        console.log(`Extracted ${data.name}:`, data.result);
        // Process the extracted data
      });
    }
  }
  
  res.status(200).send('OK');
});
```

## Schema types

### Primitive types

Extract simple values directly:

**`String`**

```json title="String"
{
  "type": "string",
  "minLength": 1,
  "maxLength": 100,
  "pattern": "^[A-Z][a-z]+$"
}
```

**`Number`**

```json title="Number"
{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "multipleOf": 0.5
}
```

**`Boolean`**

```json title="Boolean"
{
  "type": "boolean",
  "description": "Whether customer agreed to terms"
}
```

**`Enum`**

```json title="Enum"
{
  "type": "string",
  "enum": ["small", "medium", "large", "extra-large"]
}
```

### Object types

Extract structured data with multiple fields:

```json
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Full name"
    },
    "age": {
      "type": "integer",
      "minimum": 0,
      "maximum": 120
    },
    "email": {
      "type": "string",
      "format": "email"
    }
  },
  "required": ["name", "email"]
}
```

### Array types

Extract lists of items:

```json
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "product": {
        "type": "string"
      },
      "quantity": {
        "type": "integer",
        "minimum": 1
      }
    }
  },
  "minItems": 1,
  "maxItems": 10
}
```

### Nested structures

Extract complex hierarchical data:

```json
{
  "type": "object",
  "properties": {
    "customer": {
      "type": "object",
      "properties": {
        "name": {"type": "string"},
        "contact": {
          "type": "object",
          "properties": {
            "email": {"type": "string", "format": "email"},
            "phone": {"type": "string"}
          }
        }
      }
    },
    "order": {
      "type": "object",
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "sku": {"type": "string"},
              "quantity": {"type": "integer"}
            }
          }
        }
      }
    }
  }
}
```

## Validation features

### String formats

Vapi supports standard JSON Schema formats for validation:

| Format      | Description        | Example                                     |
| ----------- | ------------------ | ------------------------------------------- |
| `email`     | Email addresses    | [john@example.com](mailto:john@example.com) |
| `date`      | Date in YYYY-MM-DD | 2024-01-15                                  |
| `time`      | Time in HH:MM:SS   | 14:30:00                                    |
| `date-time` | ISO 8601 datetime  | 2024-01-15T14:30:00Z                        |
| `uri`       | Valid URI          | [https://example.com](https://example.com)  |
| `uuid`      | UUID format        | 123e4567-e89b-12d3-a456-426614174000        |

### Pattern matching

Use regular expressions for custom validation:

```json
{
  "type": "string",
  "pattern": "^[A-Z]{2}-\\d{6}$",
  "description": "Order ID like US-123456"
}
```

### Conditional logic

Use `if/then/else` for conditional requirements:

```json
{
  "type": "object",
  "properties": {
    "serviceType": {
      "type": "string",
      "enum": ["emergency", "scheduled"]
    },
    "appointmentTime": {
      "type": "string",
      "format": "date-time"
    }
  },
  "if": {
    "properties": {
      "serviceType": {"const": "scheduled"}
    }
  },
  "then": {
    "required": ["appointmentTime"]
  }
}
```

## Conditional generation

By default, every linked structured output runs after each call. Attach **conditions** to a structured output so it only generates when the call meets your criteria — for example, skip extraction on calls that barely started, or only run an output when the call ended a certain way.

> **Note**
>
> Conditions gate **whether the output runs at all**. This is different from the [`if/then/else` schema logic](#conditional-logic) above, which shapes the data *within* a single extraction.

### How conditions work

* Add a `conditions` array to a structured output.
* **Every condition must pass** for the output to run (AND semantics).
* When `conditions` is omitted or empty, no user-defined conditions gate the output (runtime defaults still apply).
* On update (`PATCH`), send `conditions: null` to clear a previously saved gate.

When a condition isn't met, the output is **skipped** rather than failed. Skipped outputs are surfaced in the **assistant preview**, **call logs**, and **sessions**, so you can see which outputs ran and which were gated out.

### Condition types

| Type              | Fields                                                          | Output runs when                                                                                                                                                                                                                  |
| ----------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `minMessages`     | `count` (integer ≥ 0)                                           | The conversation has at least `count` messages. `count: 0` removes the runtime default minimum.                                                                                                                                   |
| `minCallDuration` | `seconds` (integer ≥ 0)                                         | The call lasted at least `seconds` seconds.                                                                                                                                                                                       |
| `endedReason`     | `operator` (`oneOf` or `notOneOf`), `values` (array of strings) | The call's [ended reason](/calls/call-ended-reason) passes the membership test against `values`. `oneOf` runs the output only if the ended reason is in `values`; `notOneOf` runs it only if the ended reason is not in `values`. |

### Example

Only extract a call summary when the call had a real conversation (at least 4 messages and 10 seconds) and the customer ended it:

**`TypeScript (Server SDK)`**

```typescript title="TypeScript (Server SDK)"
const structuredOutput = await vapi.structuredOutputs.create({
  name: "Call Summary",
  type: "ai",
  description: "Summarize the conversation",
  schema: {
    type: "object",
    properties: {
      summary: { type: "string" }
    }
  },
  conditions: [
    { type: "minMessages", count: 4 },
    { type: "minCallDuration", seconds: 10 },
    { type: "endedReason", operator: "oneOf", values: ["customer-ended-call"] }
  ]
});
```

**`Python (Server SDK)`**

```python title="Python (Server SDK)"
structured_output = vapi.structured_outputs.create(
    name="Call Summary",
    type="ai",
    description="Summarize the conversation",
    schema={
        "type": "object",
        "properties": {
            "summary": {"type": "string"}
        }
    },
    conditions=[
        {"type": "minMessages", "count": 4},
        {"type": "minCallDuration", "seconds": 10},
        {"type": "endedReason", "operator": "oneOf", "values": ["customer-ended-call"]}
    ]
)
```

**`cURL`**

```bash title="cURL"
curl -X POST https://api.vapi.ai/structured-output \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Call Summary",
    "type": "ai",
    "description": "Summarize the conversation",
    "schema": {
      "type": "object",
      "properties": {
        "summary": { "type": "string" }
      }
    },
    "conditions": [
      { "type": "minMessages", "count": 4 },
      { "type": "minCallDuration", "seconds": 10 },
      { "type": "endedReason", "operator": "oneOf", "values": ["customer-ended-call"] }
    ]
  }'
```

## Custom models

By default, structured outputs are extracted with GPT-4.1. Configure the `model` to use a different provider or model, or to supply your own extraction prompts:

**`TypeScript`**

```typescript title="TypeScript"
const structuredOutput = await vapi.structuredOutputs.create({
  name: "Sentiment Analysis",
  type: "ai",
  schema: {
    type: "object",
    properties: {
      sentiment: {
        type: "string",
        enum: ["positive", "negative", "neutral"]
      },
      confidence: {
        type: "number",
        minimum: 0,
        maximum: 1
      }
    }
  },
  model: {
    provider: "openai",
    model: "gpt-4.1",
    temperature: 0.1,
    messages: [
      {
        role: "system",
        content: "You are an expert at analyzing customer sentiment. Be precise and consistent."
      },
      {
        role: "user",
        content: "Extract {{structuredOutput.name}} using this schema:\n{{structuredOutput.schema}}\n\nAnalyze the sentiment of this conversation:\n{{transcript}}"
      }
    ]
  }
});
```

**`Python`**

```python title="Python"
structured_output = vapi.structured_outputs.create(
    name="Sentiment Analysis",
    type="ai",
    schema={
        "type": "object",
        "properties": {
            "sentiment": {
                "type": "string",
                "enum": ["positive", "negative", "neutral"]
            },
            "confidence": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
            }
        }
    },
    model={
        "provider": "openai",
        "model": "gpt-4.1",
        "temperature": 0.1,
        "messages": [
            {
                "role": "system",
                "content": "You are an expert at analyzing customer sentiment. Be precise and consistent."
            },
            {
                "role": "user",
                "content": "Extract {{structuredOutput.name}} using this schema:\n{{structuredOutput.schema}}\n\nAnalyze the sentiment of this conversation:\n{{transcript}}"
            }
        ]
    }
)
```

### Available variables

Use these variables in custom prompts:

* `{{transcript}}` - Full conversation transcript
* `{{messages}}` - Conversation messages array (JSON)
* `{{endedReason}}` - How the call ended
* `{{duration}}` - Call duration in seconds
* `{{startedAt}}` - Call start time (ISO 8601)
* `{{endedAt}}` - Call end time (ISO 8601)
* `{{systemPrompt}}` - The assistant's system prompt
* `{{structuredOutput}}` - The full structured output definition
* `{{structuredOutput.name}}` - Output name
* `{{structuredOutput.description}}` - Output description
* `{{structuredOutput.schema}}` - Schema definition

> **Note**
>
> When you supply custom `messages`, reference either `{{transcript}}` or `{{messages}}` for the conversation, and a variation of `{{structuredOutput}}` so the model has the schema definition.

## API reference

The full set of request fields, response types, and query parameters lives in the API reference. Refer there for all possible values rather than duplicating them here.

### Create structured output

### Request

POST [https://api.vapi.ai/structured-output](https://api.vapi.ai/structured-output)

```curl
curl -X POST https://api.vapi.ai/structured-output \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "name": "string",
  "schema": {
    "type": "string"
  }
}'
```

```python
from vapi import Vapi, JsonSchema

client = Vapi(
    token="YOUR_TOKEN_HERE",
)

client.structured_outputs.structured_output_controller_create(
    name="string",
    schema=JsonSchema(
        type="string",
    ),
)

```

```go
package example

import (
    context "context"

    serversdkgo "github.com/VapiAI/server-sdk-go"
    client "github.com/VapiAI/server-sdk-go/client"
    option "github.com/VapiAI/server-sdk-go/option"
)

func do() {
    client := client.NewClient(
        option.WithToken(
            "YOUR_TOKEN_HERE",
        ),
    )
    request := &serversdkgo.CreateStructuredOutputDto{
        Name: "string",
        Schema: &serversdkgo.JsonSchema{
            Type: serversdkgo.JsonSchemaTypeString,
        },
    }
    client.StructuredOutputs.StructuredOutputControllerCreate(
        context.TODO(),
        request,
    )
}

```

See [Create structured output](/api-reference/structured-outputs/structured-output-controller-create) for every request field, including `type`, `conditions`, `model`, and `assistantIds`.

### Update structured output

### Request

PATCH [https://api.vapi.ai/structured-output/\{id}](https://api.vapi.ai/structured-output/\{id})

```curl
curl -X PATCH "https://api.vapi.ai/structured-output/id?schemaOverride=schemaOverride" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{}'
```

```python
from vapi import Vapi

client = Vapi(
    token="YOUR_TOKEN_HERE",
)

client.structured_outputs.structured_output_controller_update(
    id="id",
    schema_override="schemaOverride",
)

```

```go
package example

import (
    context "context"

    serversdkgo "github.com/VapiAI/server-sdk-go"
    client "github.com/VapiAI/server-sdk-go/client"
    option "github.com/VapiAI/server-sdk-go/option"
)

func do() {
    client := client.NewClient(
        option.WithToken(
            "YOUR_TOKEN_HERE",
        ),
    )
    request := &serversdkgo.UpdateStructuredOutputDto{
        Id: "id",
        SchemaOverride: "schemaOverride",
    }
    client.StructuredOutputs.StructuredOutputControllerUpdate(
        context.TODO(),
        request,
    )
}

```

> **Note**
>
> Updating the top-level schema type after creation requires the `?schemaOverride=true` query parameter. See [Update structured output](/api-reference/structured-outputs/structured-output-controller-update).

### List structured outputs

### Request

GET [https://api.vapi.ai/structured-output](https://api.vapi.ai/structured-output)

```curl
curl https://api.vapi.ai/structured-output \
     -H "Authorization: Bearer <token>"
```

```python
from vapi import Vapi

client = Vapi(
    token="YOUR_TOKEN_HERE",
)

client.structured_outputs.structured_output_controller_find_all()

```

```go
package example

import (
    context "context"

    serversdkgo "github.com/VapiAI/server-sdk-go"
    client "github.com/VapiAI/server-sdk-go/client"
    option "github.com/VapiAI/server-sdk-go/option"
)

func do() {
    client := client.NewClient(
        option.WithToken(
            "YOUR_TOKEN_HERE",
        ),
    )
    request := &serversdkgo.StructuredOutputControllerFindAllRequest{}
    client.StructuredOutputs.StructuredOutputControllerFindAll(
        context.TODO(),
        request,
    )
}

```

See [List structured outputs](/api-reference/structured-outputs/structured-output-controller-find-all) for all query parameters, including filtering, sorting, and pagination.

### Delete structured output

### Request

DELETE [https://api.vapi.ai/structured-output/\{id}](https://api.vapi.ai/structured-output/\{id})

```curl
curl -X DELETE https://api.vapi.ai/structured-output/id \
     -H "Authorization: Bearer <token>"
```

```python
from vapi import Vapi

client = Vapi(
    token="YOUR_TOKEN_HERE",
)

client.structured_outputs.structured_output_controller_remove(
    id="id",
)

```

```go
package example

import (
    context "context"

    serversdkgo "github.com/VapiAI/server-sdk-go"
    client "github.com/VapiAI/server-sdk-go/client"
    option "github.com/VapiAI/server-sdk-go/option"
)

func do() {
    client := client.NewClient(
        option.WithToken(
            "YOUR_TOKEN_HERE",
        ),
    )
    request := &serversdkgo.StructuredOutputControllerRemoveRequest{
        Id: "id",
    }
    client.StructuredOutputs.StructuredOutputControllerRemove(
        context.TODO(),
        request,
    )
}

```

## Common use cases

### Customer information collection

```json
{
  "name": "Customer Profile",
  "type": "ai",
  "schema": {
    "type": "object",
    "properties": {
      "name": {"type": "string"},
      "email": {"type": "string", "format": "email"},
      "phone": {"type": "string"},
      "accountNumber": {"type": "string"},
      "preferredContactMethod": {
        "type": "string",
        "enum": ["email", "phone", "sms"]
      }
    }
  }
}
```

### Appointment scheduling

```json
{
  "name": "Appointment Request",
  "type": "ai",
  "schema": {
    "type": "object",
    "properties": {
      "preferredDate": {"type": "string", "format": "date"},
      "preferredTime": {"type": "string", "format": "time"},
      "duration": {"type": "integer", "enum": [15, 30, 45, 60]},
      "serviceType": {
        "type": "string",
        "enum": ["consultation", "follow-up", "procedure"]
      },
      "notes": {"type": "string"}
    },
    "required": ["preferredDate", "preferredTime", "serviceType"]
  }
}
```

### Order processing

```json
{
  "name": "Order Details",
  "type": "ai",
  "schema": {
    "type": "object",
    "properties": {
      "items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "product": {"type": "string"},
            "quantity": {"type": "integer", "minimum": 1},
            "specialInstructions": {"type": "string"}
          },
          "required": ["product", "quantity"]
        }
      },
      "deliveryAddress": {
        "type": "object",
        "properties": {
          "street": {"type": "string"},
          "city": {"type": "string"},
          "zipCode": {"type": "string", "pattern": "^\\d{5}$"}
        }
      },
      "deliveryInstructions": {"type": "string"}
    }
  }
}
```

### Lead qualification

```json
{
  "name": "Lead Information",
  "type": "ai",
  "schema": {
    "type": "object",
    "properties": {
      "company": {"type": "string"},
      "role": {"type": "string"},
      "budget": {
        "type": "string",
        "enum": ["< $10k", "$10k-50k", "$50k-100k", "> $100k"]
      },
      "timeline": {
        "type": "string",
        "enum": ["immediate", "1-3 months", "3-6 months", "6+ months"]
      },
      "painPoints": {
        "type": "array",
        "items": {"type": "string"}
      },
      "nextSteps": {"type": "string"}
    }
  }
}
```

## Best practices

#### Start simple

Begin with basic schemas and add complexity as needed. Test with real conversations before adding advanced features.

#### Use descriptive names

Help the AI understand what to extract by using clear field names and descriptions in your schema.

#### Set appropriate constraints

Balance flexibility with validation. Too strict and extraction may fail; too loose and data quality suffers.

#### Handle optional fields

Only mark fields as required if they're truly essential. Use optional fields for information that might not be mentioned.

### Performance tips

* **Keep schemas focused**: Extract only what you need to minimize processing time
* **Use appropriate models**: use a capable model (for example, GPT-4.1) for complex schemas; lighter models can handle simpler ones
* **Set low temperature**: Use 0.1 or lower for consistent extraction
* **Monitor success rates**: Track extraction failures and adjust schemas accordingly

### Error handling

Always check for null results which indicate extraction failure:

```typescript
if (data.result === null) {
  console.log(`Extraction failed for ${data.name}`);
  // Implement fallback logic
}
```

## Troubleshooting

### No data extracted

#### Verify schema validity

Ensure your JSON Schema is valid and properly formatted

#### Check conversation content

Confirm the required information was actually mentioned

#### Review assistant configuration

Verify the structured output ID is linked to your assistant

#### Test with simpler schema

Try a basic schema to isolate the issue

### Incorrect extraction

* Add more descriptive field descriptions
* Provide examples in custom prompts
* Use stricter validation patterns
* Lower the model temperature

### Partial extraction

* Make fields optional if they might not be mentioned
* Verify data types match expected values

## Limitations

> **Warning**
>
> * Schema updates require `?schemaOverride=true` parameter
> * Extraction occurs after call completion (not real-time)
> * Name field limited to 40 characters

## Related

* [create-structured-output skill](/agent-skills#create-structured-output) - Use an AI coding assistant to define, attach, and verify reusable post-call extraction.
* [Call analysis](/assistants/call-analysis) - Summarize and evaluate calls
* [Function tools](/tools/custom-tools) - Trigger actions during calls
* [Webhooks](/server-url) - Receive extracted data via webhooks
* [Variables](/assistants/dynamic-variables) - Use dynamic data in conversations