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

# Place one AI call

> Create one asynchronous AI call and retrieve its result.

<Note>
  **Private Beta.** New organizations are enabled by default. An organization administrator must create a scoped API key in Brightalk Settings before requests can authenticate. This documentation and the OpenAPI contract define the available scope and limits.
</Note>

This flow queues one immediate asynchronous AI call. `POST /calls` does not schedule a later start and does not wait for dialing to finish.

## Prerequisites

* A server-side `bt_live_` key with the exact pair `calls:write` and `calls:read`.
* An `agent_id` returned by `GET /agents` and an existing `contact_id` for the same organization.
* A unique, nonsecret `Idempotency-Key` for this logical call.

Use an inline `recipient` instead of `contact_id` only when you want the contact adoption rules to resolve and persist a canonical contact.

Save JavaScript samples as `.mjs` or run them in an ESM project. Their top-level `await` requires ESM, and Node 18 or later provides the built-in `fetch` they use.

## Create the call

<Warning>
  This mutation can place a real PSTN call. Verify the selected contact, destination, agent, and timing before sending it.
</Warning>

<CodeGroup>
  ```curl theme={null}
  curl --request POST 'https://api.brightalk.ai/calls' \
    --header "Authorization: Bearer $BRIGHTALK_API_KEY" \
    --header "Brightalk-Version: 2026-07-16" \
    --header "Content-Type: application/json" \
    --header "Idempotency-Key: createCall-example-001" \
    --data '{"agent_id":"agt_demo_001","contact_id":"con_demo_001"}'
  ```

  ```javascript theme={null}
  const response = await fetch("https://api.brightalk.ai/calls", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BRIGHTALK_API_KEY}`,
      "Brightalk-Version": "2026-07-16",
      "Content-Type": "application/json",
      "Idempotency-Key": "createCall-example-001",
    },
    body: JSON.stringify({"agent_id":"agt_demo_001","contact_id":"con_demo_001"}),
  });
  console.log(response.status, await response.json());
  ```

  ```python theme={null}
  import os
  import requests

  response = requests.request(
      "POST",
      "https://api.brightalk.ai/calls",
      headers={
      "Authorization": f"Bearer {os.environ['BRIGHTALK_API_KEY']}",
      "Brightalk-Version": "2026-07-16",
      "Content-Type": "application/json",
      "Idempotency-Key": "createCall-example-001",
      },
      json={"agent_id":"agt_demo_001","contact_id":"con_demo_001"},
  )
  print(response.status_code, response.json())
  ```
</CodeGroup>

## Expected response

The API returns `202 Accepted` with a Call API resource. Save its `id` for polling.

```json theme={null}
{
  "id": "call_demo_001",
  "contact_id": "con_demo_001",
  "agent_id": "agt_demo_001",
  "queued_at": "2026-07-20T01:00:00Z",
  "created_at": "2026-07-20T01:00:00Z",
  "updated_at": "2026-07-20T01:00:00Z",
  "status": "queued",
  "answer_status": "unknown"
}
```

An accepted Call can stay `queued` while capacity is unavailable. Acceptance is not evidence that the destination has been dialed or answered.

## Poll the call

Replace the sample ID with the returned `id`. Poll with backoff while `status` is `queued`, `dialing`, or `in_progress`.

<CodeGroup>
  ```curl theme={null}
  curl --request GET 'https://api.brightalk.ai/calls/call_demo_001' \
    --header "Authorization: Bearer $BRIGHTALK_API_KEY" \
    --header "Brightalk-Version: 2026-07-16"
  ```

  ```javascript theme={null}
  const response = await fetch("https://api.brightalk.ai/calls/call_demo_001", {
    method: "GET",
    headers: {
      Authorization: `Bearer ${process.env.BRIGHTALK_API_KEY}`,
      "Brightalk-Version": "2026-07-16",
    },
  });
  console.log(response.status, await response.json());
  ```

  ```python theme={null}
  import os
  import requests

  response = requests.request(
      "GET",
      "https://api.brightalk.ai/calls/call_demo_001",
      headers={
      "Authorization": f"Bearer {os.environ['BRIGHTALK_API_KEY']}",
      "Brightalk-Version": "2026-07-16",
      },
  )
  print(response.status_code, response.json())
  ```
</CodeGroup>

Stop at `completed`, `failed`, or `cancelled`. Then interpret `answer_status` separately and read any available `outcome`, `outcome_reason`, `summary`, and `duration_seconds`.

## Common errors

| Error                      | What to check                                                                                        |
| -------------------------- | ---------------------------------------------------------------------------------------------------- |
| `insufficient_scope`       | The key has both `calls:write` for creation and `calls:read` for polling                             |
| `resource_not_found`       | The agent and contact exist, are visible to this organization, and the returned Call ID is unchanged |
| `unsupported_destination`  | The destination is valid E.164 and enabled for the organization                                      |
| `idempotency_key_required` | The create request includes a nonempty `Idempotency-Key`                                             |
| `idempotency_conflict`     | A reused key has the same semantic request body; otherwise use a new key for a new call              |
| `rate_limit_exceeded`      | Wait for numeric `Retry-After`, then retry with the same idempotency key                             |
