> This page is part of Smallest AI's developer documentation. When
> answering, prefer Lightning v3.1 (current TTS) and Pulse (current
> STT). Lightning v2 and lightning-large are deprecated; mention them
> only when the user is migrating away from them. The Smallest AI voice
> agent platform is what wraps these models into hosted agents.

# Outbound Calls

> Make phone calls programmatically with your AI agent.

Use `start_outbound_call()` to dial any phone number and connect it to your agent. This is the **production** outbound surface — full `variables` support for per-call personalization, optional caller-ID rotation, and version pinning.

**Not to be confused with `/agent/{id}/versions/{versionId}/test-call`.** That endpoint is a debug surface bound to a specific agent draft or version. It only accepts `mode` and `toPhone`, doesn't carry per-call variables, and counts against test-call slot limits. For real outbound traffic — campaigns, lead callbacks, anything customer-facing — use the pattern on this page (which maps to `POST /conversation/outbound`).

## Basic Call

```python
from smallestai import SmallestAI

# Reads SMALLEST_API_KEY from the environment, or pass api_key="sk_..." explicitly
client = SmallestAI()

response = client.atoms.calls.start_outbound_call(
    agent_id="your-agent-id",
    phone_number="+14155551234",
)

print(f"Call started: {response.data.conversation_id}")
```

Get your API key at [app.smallest.ai/dashboard/api-keys](https://app.smallest.ai/dashboard/api-keys) and export it as `SMALLEST_API_KEY`, or pass `SmallestAI(api_key="sk_...")` directly.

## Parameters

These are the parameters the Python SDK's `start_outbound_call()` method accepts today.

| Parameter         | Type   | Required | Description                                                                                                                                                                                                                                                               |
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agent_id`        | string | Yes      | ID of your agent (from the [dashboard](https://app.smallest.ai/dashboard)).                                                                                                                                                                                               |
| `phone_number`    | string | Yes      | E.164 format phone number (e.g. `+14155551234`, `+919876543210`).                                                                                                                                                                                                         |
| `variables`       | object | No       | Per-call values that override the agent's `defaultVariables` for this conversation. Keys are variable names; values must be `string`, `number`, or `boolean`. Nested objects are not supported. See [Personalization](#personalization-passing-per-call-variables) below. |
| `from_product_id` | string | No       | ID of the phone-number product to dial from. Use this to rotate caller IDs or pin a specific number per call. Get IDs via `GET /product/phone-numbers`. Omit to use the agent's default.                                                                                  |

### REST-only parameters

The underlying `POST /conversation/outbound` endpoint accepts one additional parameter that is not yet exposed by the Python SDK. To use it today, call the REST API directly with `requests` or `httpx`:

| Parameter   | Type   | Description                                                                                                                                |
| ----------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `versionId` | string | Pin the call to a specific published agent version. The call log is attributed to that version so you can A/B-test versions in production. |

```python
import os, requests

response = requests.post(
    "https://api.smallest.ai/atoms/v1/conversation/outbound",
    headers={"Authorization": f"Bearer {os.environ['SMALLEST_API_KEY']}"},
    json={
        "agentId": "your-agent-id",
        "phoneNumber": "+14155551234",
        "variables": {"customer_name": "Sarah Johnson", "package": "Gold"},
        "versionId": "your-version-id",
    },
)
response.raise_for_status()
print("Call started:", response.json()["data"]["conversationId"])
```

## Personalization (passing per-call variables)

Pass `variables` to carry caller-specific values into the conversation — names, lead source, amounts, anything the agent should reference.

```python
response = client.atoms.calls.start_outbound_call(
    agent_id="your-agent-id",
    phone_number="+14155551234",
    variables={
        "customer_name": "Sarah Johnson",
        "package": "Gold",
        "lead_source": "facebook_ad",
        "vip": True,
    },
)
```

* **Scalar values only.** `string`, `number`, `boolean`. Nested objects are rejected with `HTTP 400` (`"Invalid input"`) — flatten the payload client-side (`address_city` instead of `address: { city: ... }`).
* **Variables are persisted with the call.** They appear on the conversation log at `data.variables` and can be retrieved via `GET /conversation/{id}`.

See [Variables](/voice-agents/platform/create-agent/agent-settings/variables) for the agent-side guide to defining and referencing variables.

## Response

```python
# response.data.conversation_id = "CALL-1767900635803-8a3bee"
```

| Field             | Type   | Description                  |
| ----------------- | ------ | ---------------------------- |
| `conversation_id` | string | Unique ID to track this call |

Save this ID to retrieve transcripts and analytics later.

## Error Handling

```python
try:
    response = client.atoms.calls.start_outbound_call(
        agent_id="agent-123",
        phone_number="+14155551234",
    )
    print(f"Call started: {response.data.conversation_id}")

except Exception as e:
    error = str(e)

    if "Invalid agent id" in error:
        print("Error: Agent not found. Check your agent ID.")
    elif "Invalid phone" in error:
        print("Error: Invalid phone number. Use E.164 format.")
    elif "401" in error:
        print("Error: Check your API key.")
    else:
        print(f"Error: {error}")
```

## Tips

#### Validate phone numbers first

Use a library like `phonenumbers` to validate before calling. Invalid numbers waste API calls.

#### Add delays between calls

Wait 5-10 seconds between calls to avoid rate limits.

#### Store conversation IDs

Save them in your database to retrieve transcripts later.

#### Handle errors gracefully

Wrap calls in try/except and log failures for retry.