# Simulate an inbound call

`POST https://api.morevoice.ai/v1/test_helpers/inbound_calls`

Test mode only. A simulated caller dials one of your sandbox numbers: the call is routed like a real one (the number's assistant, flow or inbound route), runs on the virtual carrier with simulated speech and AI, and sends every call event to your test-mode webhook endpoints. Returns the call (status `ringing`); it is answered within a second.

Authenticate with a secret API key: `Authorization: Bearer $MOREVOICE_API_KEY`.

Operation ID: `test_helpers_inbound_calls_create`.

## Parameters

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `MoreVoice-Version` | `string` | no | The API version to use for this request. Defaults to the version the API key is pinned to. |
| `Idempotency-Key` | `string` | no | A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice. |

## Request body

Required, `application/json`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `to` | `string` | yes | A sandbox number of yours (POST /v1/phone_numbers with a test key). |
| `from` | `string` | no | The simulated caller's number (default +972521234567). |
| `script` | `string` | no | What the simulated caller does: `answer` (default) talks for a few turns and hangs up; `silent` says nothing (and hangs up after 30 s); `dtmf:123` presses the keys after the greeting, then talks. |

Example:

```json
{
  "from": "+972521234567",
  "script": "dtmf:1",
  "to": "+972509991234"
}
```

## Responses

### 201 Created

Created Returns `Call`.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | A call ID (prefix `call_`). |
| `object` | `"call"` | — |
| `type` | `CallType` | Who handles the call: an AI assistant, a human agent, an IVR flow, a conference room, or a voicemail box. One of `"ai"`, `"human"`, `"ivr"`, `"conference"`, `"voicemail"`. |
| `direction` | `CallDirection \| null` | One of `"inbound"`, `"outbound"`, `"browser"`. |
| `transport` | `"sip" \| "webrtc"` | `sip` for phone calls, `webrtc` for browser calls and conference rooms. |
| `status` | `CallStatus` | `queued` (placed, not ringing yet), `ringing`, `in_progress` (answered, or an inbound call being handled) or `ended`. One of `"queued"`, `"ringing"`, `"in_progress"`, `"ended"`. |
| `from` | `string \| null` | The calling number (E.164 when it is a phone number) or name. |
| `to` | `string \| null` | The called number (E.164 when it is a phone number) or destination. |
| `assistant_id` | `string \| null` | `asst_…` ID. |
| `flow_id` | `string \| null` | `flow_…` ID. |
| `flow_version` | `integer \| null` | The flow version that ran (0: an unpublished draft). |
| `queue_id` | `string \| null` | `q_…` ID. |
| `agent_id` | `string \| null` | The human agent who handled the call (`usr_…`). |
| `campaign_id` | `string \| null` | `cmp_…` ID. |
| `contact_id` | `string \| null` | `ctc_…` ID. |
| `connection_id` | `string \| null` | `conn_…` ID. |
| `api_key_id` | `string \| null` | The API key that created the call (`key_…`). |
| `purpose` | `CallPurpose \| null` | One of `"service"`, `"marketing"`, `"survey"`. |
| `started_at` | `string` | When the call started: dialled out, or rang in. |
| `answered_at` | `string \| null` | — |
| `ended_at` | `string \| null` | — |
| `duration_ms` | `integer \| null` | — |
| `end_reason` | `string \| null` | Why the call ended, e.g. `customer-ended-call`, `assistant-ended-call`, `customer-busy`, `customer-did-not-answer`. |
| `answered_by` | `CallAnsweredBy \| null` | One of `"human"`, `"machine"`, `"unknown"`. |
| `disposition` | `string \| null` | The business outcome recorded on the call (set_outcome tool, or the summary). |
| `has_recording` | `boolean` | — |
| `ai_generated` | `boolean` | Machine-readable marking (EU AI Act Art. 50(2)): true when the call contains speech generated by AI — an AI voice agent, or synthetic-voice IVR prompts. Recordings of such calls carry the same tag in their file metadata. |
| `ai_segments` | `CallAiSegment[]` | When AI-generated speech was played, in ms from the start of the call (empty when `ai_generated` is false). |
| `summary` | `CallSummary \| null` | — |
| `summary.object` | `"call_summary"` | — |
| `summary.call_id` | `string` | A call ID (prefix `call_`). |
| `summary.text` | `string` | A two-to-four sentence summary, in the language of the call. |
| `summary.intent` | `string` | What the caller wanted. |
| `summary.outcome` | `string` | How the call ended, or what was agreed. |
| `summary.sentiment` | `"positive" \| "neutral" \| "negative" \| "mixed"` | — |
| `summary.key_points` | `string[]` | — |
| `summary.action_items` | `string[]` | Follow-ups for your business; empty when there are none. |
| `summary.generated_at` | `string \| null` | — |
| `cost` | `CallCost \| null` | Set once the call has ended (never null then); null while it is in progress. |
| `cost.amount` | `integer` | The amount in the currency's minor unit (cents, agorot), rounded. |
| `cost.amount_decimal` | `string` | The exact amount in minor units, as a decimal string (sub-cent precision). |
| `cost.currency` | `string` | ISO 4217 currency code. |
| `cost.estimate` | `boolean` | true: an estimate from provider usage, not a billed amount. |
| `variables` | `Record<string, string>` | The variables the call was created with. |
| `metadata` | `Metadata` | Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `assistant` | `CallAssistant` | The assistant of the call (expand[]=assistant). |
| `assistant.id` | `string` | A assistant ID (prefix `asst_`). |
| `assistant.object` | `"assistant"` | — |
| `assistant.name` | `string` | — |

Example:

```json
{
  "agent_id": null,
  "ai_generated": true,
  "ai_segments": [
    {
      "end_ms": 99710,
      "source": "assistant",
      "start_ms": 0
    }
  ],
  "answered_at": "2026-11-03T09:14:29.410Z",
  "answered_by": "human",
  "api_key_id": "key_9i2E2pKO6g3z4nXl57Qb4g",
  "assistant_id": "asst_4Gk2LmN9pQ4rS6tV8wX0yZ",
  "campaign_id": null,
  "connection_id": "conn_2bF8kQ1nR7sT3vW5xY9zA0",
  "contact_id": null,
  "cost": {
    "amount": 4,
    "amount_decimal": "4.2310",
    "currency": "USD",
    "estimate": true
  },
  "direction": "outbound",
  "disposition": null,
  "duration_ms": 99710,
  "end_reason": "customer-ended-call",
  "ended_at": "2026-11-03T09:16:02.120Z",
  "flow_id": null,
  "flow_version": null,
  "from": "+97237654321",
  "has_recording": true,
  "id": "call_8tRPaZp5hLMbrGqdJ9AmNa",
  "livemode": true,
  "metadata": {
    "crm_contact_id": "0031x00000AbCdE"
  },
  "object": "call",
  "purpose": "service",
  "queue_id": null,
  "started_at": "2026-11-03T09:14:22.000Z",
  "status": "ended",
  "summary": null,
  "to": "+972501234567",
  "transport": "sip",
  "type": "ai",
  "variables": {
    "customer_name": "Dana"
  }
}
```

### 400 Bad Request

The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown. Returns `ErrorEnvelope`.

### 401 Unauthorized

No valid API key was sent. Returns `ErrorEnvelope`.

### 403 Forbidden

The key may not do this (a missing scope, a plan limit, or a compliance block). Returns `ErrorEnvelope`.

### 409 Conflict

The request conflicts with the object's state, or the Idempotency-Key was reused with other parameters. Returns `ErrorEnvelope`.

### 429 Too Many Requests

Too many requests, or no call capacity right now. Retry after the Retry-After delay. Returns `ErrorEnvelope`.

### 500 Internal Server Error

Something went wrong on MoreVoice's side. Retry with the same Idempotency-Key. Returns `ErrorEnvelope`.

## Code samples

**TypeScript**

```ts
import MoreVoice from "@morevoice/sdk";

const mv = new MoreVoice(); // MOREVOICE_API_KEY from the environment

const call = await mv.testHelpersInboundCalls.create({
	from: "+972521234567",
	script: "dtmf:1",
	to: "+972509991234",
});
console.log(call);
```

**Python**

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

call = client.test_helpers_inbound_calls.create({
    "from": "+972521234567",
    "script": "dtmf:1",
    "to": "+972509991234",
})
print(call)
```

**cURL**

```sh
curl -X POST https://api.morevoice.ai/v1/test_helpers/inbound_calls \
  -H "Authorization: Bearer $MOREVOICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "from": "+972521234567",
  "script": "dtmf:1",
  "to": "+972509991234"
}'
```
