[← API v2 Overview](https://motordesk.com/api-docs/v2/)

# Calls

Read and record VOIP call logs. Providers and integration bridges can push calls with `POST /calls`; re-posting the same provider and provider_id updates the entry. Calls are linked to contacts and leads by phone number.

## The Call Object

Generated from the OpenAPI schema. Always matches the live API.

**Fields (15)**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `id` | integer | - | Call id. |  |
| `provider` | enum | - | VOIP provider the call came from. |  |
| `direction` | enum | - | Call direction. |  |
| `number` | string | - | External party phone number (digits only). |  |
| `contact` | integer or null | - | Linked contact id, or null if unmatched. |  |
| `lead` | integer or null | - | Linked lead id, or null. |  |
| `result` | enum | - | Normalised call outcome. |  |
| `duration` | integer | - | Call duration in seconds. |  |
| `started` | integer | - | Unix timestamp the call started. |  |
| `line` | string | - | Business line/number that handled the call (full view only). |  |
| `user` | integer or null | - | Staff user who handled the call, or null (full view only). |  |
| `recording_available` | boolean | - | Whether a recording exists for this call. Playback is not exposed via the API (full view only). |  |
| `voicemail` | boolean | - | Whether the call went to voicemail (full view only). |  |
| `ended` | integer | - | Unix timestamp the call ended, or 0 (full view only). |  |
| `created` | integer | - | Unix timestamp the record was created (full view only). |  |

**Example object**

```json
{
    "id": 0,
    "provider": "aircall",
    "direction": "inbound",
    "number": "",
    "contact": 0,
    "lead": 0,
    "result": "completed",
    "duration": 0,
    "started": 0,
    "line": "",
    "user": 0,
    "recording_available": false,
    "voicemail": false,
    "ended": 0,
    "created": 0
}
```

## Endpoints

### GET List Calls

`GET /2.0/calls` · scope `calls:read`

List VOIP call logs with pagination and optional filters: contact, lead, user, provider, direction, result, number, and started/created date ranges.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `cursor` | query | string | - | Keyset pagination cursor from a previous response's meta.pagination.next_cursor. When supplied, page/total are not returned. |  |
| `fields` | query | string | - | Comma-separated dot-paths to return only those fields, e.g. id,data.stock.price_channel. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | List Calls |

Failures use the standard [error responses](https://motordesk.com/api-docs/v2/errors/) (4xx/5xx) with the shared error envelope.

```json
{
    "success": true,
    "data": [
        {
            "id": 0,
            "provider": "aircall",
            "direction": "inbound",
            "number": "",
            "contact": 0,
            "lead": 0,
            "result": "completed",
            "duration": 0,
            "started": 0,
            "line": "",
            "user": 0,
            "recording_available": false,
            "voicemail": false,
            "ended": 0,
            "created": 0
        }
    ],
    "meta": {
        "pagination": {
            "page": 0,
            "per_page": 0,
            "total": 0,
            "total_pages": 0,
            "next_cursor": ""
        }
    }
}
```

### POST Create Call

`POST /2.0/calls` · scope `calls:write`

Record a call log entry. Intended for VOIP providers and integration bridges to push calls into MotorDesk. Re-posting the same provider and provider_id updates the existing entry (so a call can be created on ring and updated on completion). The contact and lead are resolved from the number when not supplied.

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `provider` | string | Yes | Short provider/bridge identifier, e.g. aircall or ringcentral (max 16 chars, alphanumeric). | `aircall` |
| `provider_id` | string | Yes | The provider's own unique id for the call. Used for idempotent upserts. | `call_8f2c1a` |
| `direction` | enum | Yes | Call direction. | `inbound` |
| `number` | string | Yes | The external party phone number (international format preferred). | `447700900123` |
| `line` | string | - | The business line/number or name that handled the call. | `Sales` |
| `contact` | integer or null | - | Contact id to link to. Resolved from the number when omitted. | `25325` |
| `lead` | integer or null | - | Lead id to link to. Resolved from the number when omitted. |  |
| `user` | integer | - | Staff user id who handled the call. See /reference/staff-users. | `12` |
| `result` | string | - | Call outcome. Provider wording is accepted and normalised to one of: completed, missed, voicemail, no_answer, busy, failed, in_progress. | `completed` |
| `duration` | integer | - | Call duration in seconds. | `184` |
| `recording` | string | - | Provider recording id, if a recording exists. | `rec_77a2` |
| `recording_available` | boolean | - | Whether a recording exists. Set automatically when recording is supplied. | `true` |
| `voicemail` | boolean | - | Whether the call went to voicemail. | `false` |
| `started` | integer | - | Unix timestamp the call started. Defaults to now when omitted. | `1788000000` |
| `ended` | integer | - | Unix timestamp the call ended. | `1788000184` |

```json
{
    "provider": "aircall",
    "provider_id": "call_8f2c1a",
    "direction": "inbound",
    "number": "447700900123",
    "line": "Sales",
    "contact": 25325,
    "lead": 0,
    "user": 12,
    "result": "completed",
    "duration": 184,
    "recording": "rec_77a2",
    "recording_available": true,
    "voicemail": false,
    "started": 1788000000,
    "ended": 1788000184
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Create Call |

Failures use the standard [error responses](https://motordesk.com/api-docs/v2/errors/) (4xx/5xx) with the shared error envelope.

```json
{
    "success": true,
    "data": {
        "id": 0,
        "provider": "aircall",
        "direction": "inbound",
        "number": "",
        "contact": 0,
        "lead": 0,
        "result": "completed",
        "duration": 0,
        "started": 0,
        "line": "",
        "user": 0,
        "recording_available": false,
        "voicemail": false,
        "ended": 0,
        "created": 0
    }
}
```

### GET Get Call

`GET /2.0/calls/{id}` · scope `calls:read`

Retrieve a single call log entry by id.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `fields` | query | string | - | Comma-separated dot-paths to return only those fields, e.g. id,data.stock.price_channel. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Get Call |

Failures use the standard [error responses](https://motordesk.com/api-docs/v2/errors/) (4xx/5xx) with the shared error envelope.

```json
{
    "success": true,
    "data": {
        "id": 0,
        "provider": "aircall",
        "direction": "inbound",
        "number": "",
        "contact": 0,
        "lead": 0,
        "result": "completed",
        "duration": 0,
        "started": 0,
        "line": "",
        "user": 0,
        "recording_available": false,
        "voicemail": false,
        "ended": 0,
        "created": 0
    }
}
```
