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

# Calls

> Start an outbound voice call with a PAM-managed or custom agent.

Use `POST /v1/calls` to start a single outbound voice call. PAM accepts the request and places the call asynchronously.

## Create a Call

```bash theme={null}
curl https://api.pamhq.com/v1/calls \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: call_01HV7K4ZD3Q9X8P1M8Y2K9A0BC" \
  -d '{
    "agentSlug": "voice-recall",
    "toNumber": "+15555550199",
    "fromNumber": "+15555550123",
    "welcomeMessage": "Hi Ada, this is PAM Motors following up on your service recall.",
    "dynamicVariables": {
      "contact_first_name": "Ada",
      "contact_last_name": "Lovelace",
      "dealership_name": "PAM Motors",
      "recall_id": "24V-123",
      "service_ids": "RECALL_SERVICE",
      "vin": "1HGBH41JXMN109186",
      "vehicle_year": "2021",
      "vehicle_make": "Honda",
      "vehicle_model": "Accord"
    },
    "metadata": {
      "externalContactId": "contact_123"
    },
    "externalReferenceId": "touchpoint_123",
    "webhookUrl": "https://partner.example.com/pam/webhooks"
  }'
```

Successful requests return `202 Accepted`:

```json theme={null}
{
  "data": {
    "conversationId": null,
    "status": "queued"
  },
  "meta": {
    "requestId": "req_abc123"
  }
}
```

`queued` means PAM accepted the request and will place the call asynchronously.

PAM creates a `conversationId` after the call is placed. Subsequent call lifecycle webhooks such as `call.started`, `call.ended`, and `call.analyzed` include `conversationId`.

If PAM cannot place the call, PAM sends a `call.failed` webhook. Use `data.dispatchRequestId`, top-level `externalReferenceId`, the original `Idempotency-Key`, or your request metadata to reconcile the failed call attempt.

If `webhookUrl` is provided, PAM uses it for `call.failed` even when no `conversationId` was created yet.

## Request Fields

| Field                 | Required                                         | Description                                                                                                                                                                                                                       |
| --------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agentSlug`           | one of `agentSlug` or `agentId`                  | Stable slug for a PAM-managed voice agent, such as `voice-recall` or `voice-retention`.                                                                                                                                           |
| `agentId`             | one of `agentSlug` or `agentId`                  | UUID of a specific agent.                                                                                                                                                                                                         |
| `toNumber`            | yes                                              | Customer phone number in E.164 format.                                                                                                                                                                                            |
| `fromNumber`          | PAM-managed agents only                          | Sender phone number in E.164 format. For custom agents with a configured number, PAM uses the agent's number.                                                                                                                     |
| `welcomeMessage`      | PAM-managed voice agents only                    | Opening text used as the Retell begin message.                                                                                                                                                                                    |
| `dynamicVariables`    | PAM-managed recall and retention agents only     | Public string variables used to build the voice agent context and tools. See [PAM Agents](/guides/agents) for the required variables for each managed agent.                                                                      |
| `metadata`            | no                                               | Opaque reconciliation data stored with the conversation.                                                                                                                                                                          |
| `externalReferenceId` | no                                               | Opaque caller-owned reference echoed as top-level `externalReferenceId` on webhook events for this call. PAM does not interpret this value. It does not need to be globally unique and is not a replacement for `idempotencyKey`. |
| `idempotencyKey`      | required if `Idempotency-Key` header is not sent | Stable key for safely retrying this create request. Prefer the `Idempotency-Key` header for new integrations.                                                                                                                     |
| `webhookUrl`          | no                                               | HTTPS URL that receives webhook events for this call instead of the default webhook registration URL. Event subscriptions, custom headers, and signing secret still come from your matching webhook registration.                 |

Your API key determines the client organization for attribution and billing. Do not send `clientOrgId` in the request body.

Use `externalReferenceId` when your system needs to map webhooks back to one of your own objects, such as a touchpoint, campaign, or workflow run. PAM stores the value and echoes it on webhooks when provided.

For PAM-managed agents, PAM generates internal prompt context blocks from the submitted `dynamicVariables` plus server-owned client configuration. Those generated context blocks are not returned by call GET or list responses.

## Idempotency

An idempotency key is required. Send it in the `Idempotency-Key` header or as `idempotencyKey` in the JSON body. Use the same key when retrying a request after a network error or timeout.

If PAM has already accepted a call request for the same key and client organization, the retry returns the current `status`. If the call has already been placed, the response may also include the resulting `conversationId`.

## List Calls

Use `GET /v1/calls` to list voice call conversations for your organization.

```bash theme={null}
curl "https://api.pamhq.com/v1/calls?limit=20" \
  -H "Authorization: Bearer $PAM_API_KEY"
```

You can filter by `status`, `agentId`, `toNumber`, `fromNumber`, `createdAfter`, and `createdBefore`.

Results are cursor-paginated:

```json theme={null}
{
  "data": [
    {
      "id": "b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2",
      "conversationId": "b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2",
      "status": "in_progress",
      "agentId": "2c4a1e72-7a5d-4b6e-9c2a-01a78b7b3f3f",
      "agentVersionId": "7a9c7b3e-8d0f-4c40-a156-dcc78c89b127",
      "fromNumber": "+15555550123",
      "toNumber": "+15555550199",
      "dynamicVariables": {
        "contact_first_name": "Ada",
        "contact_last_name": "Lovelace",
        "dealership_name": "PAM Motors",
        "recall_id": "24V-123"
      },
      "metadata": {
        "externalContactId": "contact_123"
      },
      "startedAt": "2026-04-10T14:00:02.010Z",
      "endedAt": null,
      "endReason": null,
      "createdAt": "2026-04-10T13:59:58.000Z",
      "updatedAt": "2026-04-10T14:00:02.010Z",
      "provider": "retell",
      "providerCallId": "call_abc123",
      "recordingUrl": null,
      "transcriptUrl": null,
      "durationMs": null,
      "costCents": null,
      "analysis": null
    }
  ],
  "meta": {
    "requestId": "req_abc123",
    "pagination": {
      "cursor": null,
      "hasMore": false
    }
  }
}
```

If `hasMore` is `true`, pass the returned `cursor` in the next request.

## Get Call Status

Use `GET /v1/calls/{id}` to get the current status for one voice call conversation.

```bash theme={null}
curl https://api.pamhq.com/v1/calls/b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2 \
  -H "Authorization: Bearer $PAM_API_KEY"
```

```json theme={null}
{
  "data": {
    "id": "b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2",
    "conversationId": "b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2",
    "status": "completed",
    "agentId": "2c4a1e72-7a5d-4b6e-9c2a-01a78b7b3f3f",
    "agentVersionId": "7a9c7b3e-8d0f-4c40-a156-dcc78c89b127",
    "fromNumber": "+15555550123",
    "toNumber": "+15555550199",
    "dynamicVariables": {
      "contact_first_name": "Ada",
      "contact_last_name": "Lovelace",
      "dealership_name": "PAM Motors",
      "recall_id": "24V-123"
    },
    "metadata": {
      "externalContactId": "contact_123"
    },
    "startedAt": "2026-04-10T14:00:02.010Z",
    "endedAt": "2026-04-10T14:03:41.000Z",
    "endReason": "user_hangup",
    "createdAt": "2026-04-10T13:59:58.000Z",
    "updatedAt": "2026-04-10T14:03:41.000Z",
    "provider": "retell",
    "providerCallId": "call_abc123",
    "recordingUrl": "https://recordings.example/abc.mp3",
    "transcriptUrl": null,
    "durationMs": 219000,
    "costCents": 42,
    "analysis": {
      "status": "completed",
      "result": {
        "call_successful": true
      },
      "durationMs": 1200
    }
  },
  "meta": {
    "requestId": "req_abc123"
  }
}
```

These read endpoints are useful when a webhook is delayed, retried, or missed by your system.

## Status Meanings

| Status        | Meaning                                                              |
| ------------- | -------------------------------------------------------------------- |
| `queued`      | PAM accepted the request, but the call has not started yet.          |
| `in_progress` | The call has started and is still open.                              |
| `completed`   | The call ended normally. Check `endReason` for why it ended.         |
| `failed`      | PAM could not place the call or the call hit an unrecoverable error. |
| `cancelled`   | The call was cancelled before normal completion.                     |

## Lifecycle Webhooks

Subscribe to these events to follow the call:

| Event           | When it fires                                             |
| --------------- | --------------------------------------------------------- |
| `call.started`  | The call started.                                         |
| `call.ended`    | The call has ended and the transcript has been persisted. |
| `call.analyzed` | Post-call analysis is available.                          |
| `call.failed`   | PAM could not place the call.                             |

Webhook payloads are canonical PAM payloads. Provider-specific Retell identifiers and raw provider payloads are not part of the external contract.

Voice lifecycle webhook data includes `dispatchRequestId` and `idempotencyKey` when PAM can associate the event with the original create-call request. If you provided `externalReferenceId`, PAM includes it as a top-level field on every lifecycle webhook for the call, including pre-conversation `call.failed` events.

## Close a Call

Use `POST /v1/calls/{id}/close` to close an open voice conversation.

The `{id}` is the `conversationId` from call lifecycle webhooks or from an idempotent create-call retry after PAM has created the conversation. A pre-placement `call.failed` event may not have a `conversationId`; use `dispatchRequestId`, top-level `externalReferenceId`, the original `Idempotency-Key`, or your request metadata to reconcile that case.

```bash theme={null}
curl https://api.pamhq.com/v1/calls/b7ee8d1b-5e3e-4a1a-8f0a-9e2a4f8f1aa2/close \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "admin_closed"
  }'
```

If `reason` is omitted, PAM uses `admin_closed`.

## Common Errors

* `400 validation_error` — missing idempotency key, invalid phone format, invalid or non-HTTPS `webhookUrl`, both `agentId` and `agentSlug` were provided, or neither was provided.
* `400 validation_error` — `fromNumber` is missing for a PAM-managed agent.
* `400 validation_error` — a managed agent request is missing required `dynamicVariables`.
* `401 unauthorized` — missing, expired, revoked, or invalid API key.
* `404 not_found` — the agent could not be resolved or the conversation does not belong to the authenticated client.
