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

# Leads

Capture enquiries, manage follow-up, associate vehicles, record messages, and send replies through MotorDesk communication channels.

## The Lead Object

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

**Fields (31)**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `id` | integer | - | Lead id. | `4009` |
| `site` | integer | - | Site id, or 0 for none. | `0` |
| `channel` | string | - | Channel the lead came in on (e.g. api, website, email). | `website` |
| `reference` | integer | - | Lead reference number. | `10472` |
| `name` | string | - | The lead's name. | `Jane Doe` |
| `email` | string | - | The lead's email address. | `jane.doe@example.com` |
| `phone` | string | - | The lead's landline number. | `01612345678` |
| `mobile` | string | - | The lead's mobile number. | `07700900123` |
| `contact` | integer or null | - | Linked contact id, or null. | `110153` |
| `type` | array of string | - | Lead enquiry type(s), in snake_case (e.g. test_drive, part_exchange). See /reference/lead-types. | `["test_drive"]` |
| `status` | object | - | Primary workflow status. |  |
| `status.id` | integer | - | Status code (0-5). | `0` |
| `status.name` | enum | - | Status name. | `new` |
| `rating` | integer or null | - | AI buying-intent rating: 5 ready to transact, 4 specific vehicle and questions, 3 genuine interest, 2 vague or early, 1 not a buyer. Null when not rated. Never a spam score (see status junk). | `4` |
| `summary` | string or null | - | AI summary of where the conversation stands, at most 12 words, or null. | `Wants Saturday test drive of the Golf, asked for finance figures.` |
| `created` | integer | - | Unix timestamp the lead was created. | `1781303332` |
| `updated` | integer | - | Unix timestamp the lead was last updated. | `1781309000` |
| `session` | string | - | Visitor session reference (full view only). |  |
| `avatar` | string | - | Avatar reference (full view only). |  |
| `assign` | array of integer | - | Staff user ids the lead is assigned to (full view only). |  |
| `tag` | array of object | - | Applied lead tags ({ name, checked, colour, type }), full view only. Same shape as GET /leads/{id}/tags applied. |  |
| `stat` | boolean | - | Statistics flag: whether the lead counts toward reporting/KPIs (full view only). |  |
| `reopen` | string (date) or null | - | Date a closed lead will auto-reopen, or null (full view only). |  |
| `data` | object | - | Lead detail (source, message, subject, url, vehicle, appointment, junk) (full view only). |  |
| `ai` | object or null | - | The AI's latest read of the conversation, or null when it has not run (full view only). |  |
| `ai.intent` | string or null | - | Main aim, as one of the ids used by type (e.g. test_drive, finance, part_exchange, email for a general enquiry), or other. | `test_drive` |
| `ai.rating_reason` | string or null | - | Why the rating was given. |  |
| `ai.next_action` | string or null | - | Suggested next step for the dealer. |  |
| `ai.junk` | boolean | - | Whether the AI considered the latest message junk. Only high-confidence junk on an unanswered lead moves it to status junk. |  |
| `ai.junk_confidence` | enum or null | - |  |  |
| `ai.processed` | integer or null | - | Unix timestamp the AI last processed the lead. |  |

**Example object**

```json
{
    "id": 4009,
    "site": 0,
    "channel": "website",
    "reference": 10472,
    "name": "Jane Doe",
    "email": "jane.doe@example.com",
    "phone": "01612345678",
    "mobile": "07700900123",
    "contact": 110153,
    "type": [
        "test_drive"
    ],
    "status": {
        "id": 0,
        "name": "new"
    },
    "rating": 4,
    "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
    "created": 1781303332,
    "updated": 1781309000,
    "session": "",
    "avatar": "",
    "assign": [
        0
    ],
    "tag": [
        {
            "name": "",
            "checked": false,
            "colour": "",
            "type": "default"
        }
    ],
    "stat": false,
    "reopen": "2026-01-01",
    "data": {},
    "ai": {
        "intent": "test_drive",
        "rating_reason": "",
        "next_action": "",
        "junk": false,
        "junk_confidence": "high",
        "processed": 0
    }
}
```

## Endpoints

### GET List Leads

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

List leads with pagination and optional filters (status, channel, site, customer, created/updated range).

**Parameters (18)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `page` | query | integer | - | Page number, starting at 1 (offset pagination). |  |
| `per_page` | query | integer | - | Results per page (maximum 500). |  |
| `view` | query | enum | - | Response detail: "simple" for a compact object or "full" for the complete object. |  |
| `site` | query | integer | - | Filter by site id. |  |
| `status` | query | string | - | Filter by status, as the code or the name the lead reads back: 0 new, 1 new_message, 2 read, 3 replied, 4 closed, 5 junk. | `replied` |
| `channel` | query | string | - | Filter by channel. |  |
| `reference` | query | integer | - | Filter by reference. |  |
| `name` | query | string | - | Filter by name. |  |
| `email` | query | string | - | Filter by email. Supports wildcards (%) with the search:wildcard scope. |  |
| `phone` | query | string | - | Filter by phone. |  |
| `mobile` | query | string | - | Filter by mobile. |  |
| `contact` | query | integer | - | Filter by contact id. |  |
| `vehicle` | query | integer | - | Filter to leads associated with this vehicle id. |  |
| `rating_min` | query | integer | - | Only leads the AI rated at or above this buying intent (1-5). Unrated leads are excluded. | `4` |
| `created` | query | string | - | Unix timestamp exact match, or a two-element array [from, to] for a range. An empty bound is open-ended. |  |
| `updated` | query | string | - | Unix timestamp exact match, or a two-element array [from, to] for a range. An empty bound is open-ended. |  |
| `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 | Paginated leads |

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": 4009,
            "site": 0,
            "channel": "website",
            "reference": 10472,
            "name": "Jane Doe",
            "email": "jane.doe@example.com",
            "phone": "01612345678",
            "mobile": "07700900123",
            "contact": 110153,
            "type": [
                "test_drive"
            ],
            "status": {
                "id": 0,
                "name": "new"
            },
            "rating": 4,
            "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
            "created": 1781303332,
            "updated": 1781309000,
            "session": "",
            "avatar": "",
            "assign": [
                0
            ],
            "tag": [
                {
                    "name": "",
                    "checked": false,
                    "colour": "",
                    "type": "default"
                }
            ],
            "stat": false,
            "reopen": "2026-01-01",
            "data": {},
            "ai": {
                "intent": "test_drive",
                "rating_reason": "",
                "next_action": "",
                "junk": false,
                "junk_confidence": "high",
                "processed": 0
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 0,
            "per_page": 0,
            "total": 0,
            "total_pages": 0,
            "next_cursor": ""
        }
    }
}
```

### POST Create Lead

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

Create a lead.

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `site` | integer | - | Site id from /reference/sites; 0 for no site. | `0` |
| `channel` | string | - | Lead channel, e.g. api, website, email, sms. Defaults to api. | `api` |
| `channel_id` | string | - | External reference for the channel (e.g. a messaging thread id). |  |
| `name` | string | - | The lead's name. | `Jane Smith` |
| `email` | string | - | The lead's email address. | `jane.smith@example.com` |
| `phone` | string | - | Landline number in international format. | `441612345678` |
| `mobile` | string | - | Mobile number in international format. | `447700900123` |
| `contact` | integer | - | Existing contact id to link this lead to. | `77684` |
| `type` | string | - | Lead enquiry type(s) in snake_case (e.g. test_drive, part_exchange). See /reference/lead-types. Defaults to email (general enquiry). | `test_drive` |
| `data` | object | - | Free-form detail object stored against the lead. | `{}` |
| `status` | integer | - | Primary status code: 0 new, 1 new_message, 2 read, 3 replied, 4 closed, 5 junk. Prefer the named status field on /leads/{id}/status to change state after creation. | `0` |
| `tag` | array of string | - | Lead tags. Each item is a tag name string or { name, checked }; names must exist in the lead taxonomy (see GET /leads/{id}/tags or /reference/tags?resource=lead). Replaces the full set. | `[]` |
| `notify` | boolean | - | Whether to fire new-lead notifications on create. Defaults to true. | `true` |
| `vehicle` | integer | - | Create only: stock vehicle id the enquiry is about; the vehicle is associated with the new lead exactly as POST /leads/{id}/vehicles would. On an existing lead use that endpoint instead. Use this or vehicle_tag. | `85481` |
| `vehicle_tag` | string | - | Create only: vehicle tag the enquiry is about, as an alternative to vehicle. | `HbSDTp97` |

```json
{
    "site": 0,
    "channel": "api",
    "channel_id": "",
    "name": "Jane Smith",
    "email": "jane.smith@example.com",
    "phone": "441612345678",
    "mobile": "447700900123",
    "contact": 77684,
    "type": "test_drive",
    "data": {},
    "status": 0,
    "tag": [],
    "notify": true,
    "vehicle": 85481,
    "vehicle_tag": "HbSDTp97"
}
```

**Responses**

| Status | Description |
| --- | --- |
| `201` Created | Lead created |

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": 4009,
        "site": 0,
        "channel": "website",
        "reference": 10472,
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "phone": "01612345678",
        "mobile": "07700900123",
        "contact": 110153,
        "type": [
            "test_drive"
        ],
        "status": {
            "id": 0,
            "name": "new"
        },
        "rating": 4,
        "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
        "created": 1781303332,
        "updated": 1781309000,
        "session": "",
        "avatar": "",
        "assign": [
            0
        ],
        "tag": [
            {
                "name": "",
                "checked": false,
                "colour": "",
                "type": "default"
            }
        ],
        "stat": false,
        "reopen": "2026-01-01",
        "data": {},
        "ai": {
            "intent": "test_drive",
            "rating_reason": "",
            "next_action": "",
            "junk": false,
            "junk_confidence": "high",
            "processed": 0
        }
    }
}
```

### GET Get Lead

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

Retrieve a single lead 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 | Lead |

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": 4009,
        "site": 0,
        "channel": "website",
        "reference": 10472,
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "phone": "01612345678",
        "mobile": "07700900123",
        "contact": 110153,
        "type": [
            "test_drive"
        ],
        "status": {
            "id": 0,
            "name": "new"
        },
        "rating": 4,
        "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
        "created": 1781303332,
        "updated": 1781309000,
        "session": "",
        "avatar": "",
        "assign": [
            0
        ],
        "tag": [
            {
                "name": "",
                "checked": false,
                "colour": "",
                "type": "default"
            }
        ],
        "stat": false,
        "reopen": "2026-01-01",
        "data": {},
        "ai": {
            "intent": "test_drive",
            "rating_reason": "",
            "next_action": "",
            "junk": false,
            "junk_confidence": "high",
            "processed": 0
        }
    }
}
```

### PATCH Update Lead

`PATCH /2.0/leads/{id}` · scope `leads:write`

Update a lead. Only the supplied fields are changed.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `site` | integer | - | Site id from /reference/sites; 0 for no site. | `0` |
| `channel` | string | - | Lead channel, e.g. api, website, email, sms. Defaults to api. | `api` |
| `channel_id` | string | - | External reference for the channel (e.g. a messaging thread id). |  |
| `name` | string | - | The lead's name. | `Jane Smith` |
| `email` | string | - | The lead's email address. | `jane.smith@example.com` |
| `phone` | string | - | Landline number in international format. | `441612345678` |
| `mobile` | string | - | Mobile number in international format. | `447700900123` |
| `contact` | integer | - | Existing contact id to link this lead to. | `77684` |
| `type` | string | - | Lead enquiry type(s) in snake_case (e.g. test_drive, part_exchange). See /reference/lead-types. Defaults to email (general enquiry). | `test_drive` |
| `data` | object | - | Free-form detail object stored against the lead. | `{}` |
| `status` | integer | - | Primary status code: 0 new, 1 new_message, 2 read, 3 replied, 4 closed, 5 junk. Prefer the named status field on /leads/{id}/status to change state after creation. | `0` |
| `tag` | array of string | - | Lead tags. Each item is a tag name string or { name, checked }; names must exist in the lead taxonomy (see GET /leads/{id}/tags or /reference/tags?resource=lead). Replaces the full set. | `[]` |
| `notify` | boolean | - | Whether to fire new-lead notifications on create. Defaults to true. | `true` |
| `vehicle` | integer | - | Create only: stock vehicle id the enquiry is about; the vehicle is associated with the new lead exactly as POST /leads/{id}/vehicles would. On an existing lead use that endpoint instead. Use this or vehicle_tag. | `85481` |
| `vehicle_tag` | string | - | Create only: vehicle tag the enquiry is about, as an alternative to vehicle. | `HbSDTp97` |

```json
{
    "site": 0,
    "channel": "api",
    "channel_id": "",
    "name": "Jane Smith",
    "email": "jane.smith@example.com",
    "phone": "441612345678",
    "mobile": "447700900123",
    "contact": 77684,
    "type": "test_drive",
    "data": {},
    "status": 0,
    "tag": [],
    "notify": true,
    "vehicle": 85481,
    "vehicle_tag": "HbSDTp97"
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead updated |

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": 4009,
        "site": 0,
        "channel": "website",
        "reference": 10472,
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "phone": "01612345678",
        "mobile": "07700900123",
        "contact": 110153,
        "type": [
            "test_drive"
        ],
        "status": {
            "id": 0,
            "name": "new"
        },
        "rating": 4,
        "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
        "created": 1781303332,
        "updated": 1781309000,
        "session": "",
        "avatar": "",
        "assign": [
            0
        ],
        "tag": [
            {
                "name": "",
                "checked": false,
                "colour": "",
                "type": "default"
            }
        ],
        "stat": false,
        "reopen": "2026-01-01",
        "data": {},
        "ai": {
            "intent": "test_drive",
            "rating_reason": "",
            "next_action": "",
            "junk": false,
            "junk_confidence": "high",
            "processed": 0
        }
    }
}
```

### DELETE Delete Lead

`DELETE /2.0/leads/{id}` · scope `leads:delete`

Delete a lead.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead deleted |

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,
        "deleted": false
    }
}
```

### Status

### PATCH Update Lead Status

`PATCH /2.0/leads/{id}/status` · scope `leads:write`

Set lead state. status sets the primary workflow state (new, new_message, read, replied, closed, junk); junk and closed/reopen are conveniences over it; stat toggles the separate statistics flag. status cannot be combined with closed or junk.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `status` | enum | - | Set the primary workflow status directly. new=unactioned lead, new_message=unread inbound message, read=acknowledged, replied=staff has replied, closed, junk. Overrides any current status (including junk). | `read` |
| `junk` | boolean | - | true marks the lead as junk (status junk); false clears junk and resets to new. | `false` |
| `closed` | boolean | - | true closes the lead (status closed); false reopens it (status new_message). | `true` |
| `reopen` | string (date) or null | - | Optional date (YYYY-MM-DD) to automatically reopen a closed lead; null clears it. Only meaningful with closed=true. | `2026-09-01` |
| `stat` | boolean | - | The statistics flag (separate from status): whether this lead counts toward reporting/KPIs. | `true` |

```json
{
    "status": "read",
    "junk": false,
    "closed": true,
    "reopen": "2026-09-01",
    "stat": true
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead status updated |

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": 4009,
        "site": 0,
        "channel": "website",
        "reference": 10472,
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "phone": "01612345678",
        "mobile": "07700900123",
        "contact": 110153,
        "type": [
            "test_drive"
        ],
        "status": {
            "id": 0,
            "name": "new"
        },
        "rating": 4,
        "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
        "created": 1781303332,
        "updated": 1781309000,
        "session": "",
        "avatar": "",
        "assign": [
            0
        ],
        "tag": [
            {
                "name": "",
                "checked": false,
                "colour": "",
                "type": "default"
            }
        ],
        "stat": false,
        "reopen": "2026-01-01",
        "data": {},
        "ai": {
            "intent": "test_drive",
            "rating_reason": "",
            "next_action": "",
            "junk": false,
            "junk_confidence": "high",
            "processed": 0
        }
    }
}
```

### Assign

### PATCH Assign Lead to Staff

`PATCH /2.0/leads/{id}/assign` · scope `leads:write`

Set the staff users a lead is assigned to. The supplied set replaces the current assignment; an empty array clears it.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `assign` | array of integer | Yes | Staff user ids to assign the lead to. An empty array clears the assignment. See /reference/staff-users. | `[12,34]` |

```json
{
    "assign": [
        12,
        34
    ]
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Assign Lead to Staff |

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": 4009,
        "site": 0,
        "channel": "website",
        "reference": 10472,
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "phone": "01612345678",
        "mobile": "07700900123",
        "contact": 110153,
        "type": [
            "test_drive"
        ],
        "status": {
            "id": 0,
            "name": "new"
        },
        "rating": 4,
        "summary": "Wants Saturday test drive of the Golf, asked for finance figures.",
        "created": 1781303332,
        "updated": 1781309000,
        "session": "",
        "avatar": "",
        "assign": [
            0
        ],
        "tag": [
            {
                "name": "",
                "checked": false,
                "colour": "",
                "type": "default"
            }
        ],
        "stat": false,
        "reopen": "2026-01-01",
        "data": {},
        "ai": {
            "intent": "test_drive",
            "rating_reason": "",
            "next_action": "",
            "junk": false,
            "junk_confidence": "high",
            "processed": 0
        }
    }
}
```

### Acknowledge

### POST Acknowledge Open Leads

`POST /2.0/leads/acknowledge` · scope `leads:write`

Mark every new or unread lead (status new or new_message) as read in one call.

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Acknowledge Open Leads |

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

```json
{
    "success": true,
    "data": {
        "acknowledged": false
    }
}
```

### Tags

### GET List Lead Tags

`GET /2.0/leads/{id}/tags` · scope `leads:read`

List the tags applied to a lead, plus the available lead tag taxonomy.

**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 | List Lead Tags |

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

```json
{
    "success": true,
    "data": {
        "applied": [
            {
                "name": "Hot lead",
                "checked": false,
                "colour": "success",
                "type": "default"
            }
        ],
        "available": [
            {
                "name": "",
                "colour": "",
                "type": "default",
                "defaulted": false
            }
        ]
    }
}
```

### PUT Set Lead Tags

`PUT /2.0/leads/{id}/tags` · scope `leads:write`

Replace the tags applied to a lead. Each tag name must be available in the lead tag taxonomy. The same tag items can also be set inline via the lead create/update `tag` field.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `tags` | array of string | Yes | The full set of tags to apply. Each item is a tag name string, or an object { name, checked }. | `[{"name":"MOT","checked":true},{"name":"Valet","checked":false}]` |

```json
{
    "tags": [
        {
            "name": "MOT",
            "checked": true
        },
        {
            "name": "Valet",
            "checked": false
        }
    ]
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Set Lead Tags |

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

```json
{
    "success": true,
    "data": {
        "applied": [
            {
                "name": "Hot lead",
                "checked": false,
                "colour": "success",
                "type": "default"
            }
        ],
        "available": [
            {
                "name": "",
                "colour": "",
                "type": "default",
                "defaulted": false
            }
        ]
    }
}
```

### Vehicles

### GET List Lead Vehicles

`GET /2.0/leads/{id}/vehicles` · scope `lead-vehicles:read`

List vehicles associated with a lead.

**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 | Lead vehicle associations |

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": 5521,
            "lead": 4009,
            "appointment": 0,
            "vehicle": 85481
        }
    ]
}
```

### POST Associate Vehicle or Appointment with Lead

`POST /2.0/leads/{id}/vehicles` · scope `lead-vehicles:write`

Associate a vehicle and/or an appointment with a lead. Provide vehicle (a stock id) or vehicle_tag to link a vehicle, appointment to link an appointment, or both. At least one is required; vehicle takes precedence over vehicle_tag.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `vehicle` | integer | - | Stock vehicle id to associate. Use this or vehicle_tag. | `85481` |
| `vehicle_tag` | string | - | Alphanumeric vehicle tag to associate, as an alternative to vehicle. | `HbSDTp97` |
| `appointment` | integer | - | Appointment id to link to the lead. May be supplied on its own (no vehicle) to associate just an appointment. | `747` |

```json
{
    "vehicle": 85481,
    "vehicle_tag": "HbSDTp97",
    "appointment": 747
}
```

**Responses**

| Status | Description |
| --- | --- |
| `201` Created | Lead vehicle association created |

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": 5521,
        "lead": 4009,
        "appointment": 0,
        "vehicle": 85481
    }
}
```

### DELETE Remove Lead Vehicle

`DELETE /2.0/leads/{id}/vehicles/{vehicle_id}` · scope `lead-vehicles:delete`

Remove a vehicle association from a lead.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `vehicle_id` | path | string | Yes | Resource identifier in the path. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead vehicle association deleted |

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,
        "deleted": false
    }
}
```

### Messages

### GET List Lead Messages

`GET /2.0/leads/{id}/messages` · scope `lead-messages:read`

List the messages recorded against a lead.

**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 | Lead messages |

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": 88213,
            "lead": 4009,
            "sender": "0",
            "message": {
                "m": "Is this still available?"
            },
            "created": 1781303332,
            "delivered": 1781303340,
            "viewed": 0
        }
    ]
}
```

### POST Add Lead Message

`POST /2.0/leads/{id}/messages` · scope `lead-messages:write`

Add a message to a lead. By default a staff-sent message (sender = a user id) is dispatched to the lead through the reply pipeline (status becomes replied) and a customer message (sender 0) is recorded inbound (status becomes new_message). Set send=false to record without dispatching. When send is true a channel is required.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `message` | string | Yes | The message body. A plain string is the common case; an object may carry structured fields (m, subject, html, text). | `Thanks for your enquiry. The vehicle is still available. When would suit you for a viewing?` |
| `sender` | integer | Yes | Who sent the message: 0 = the customer/lead (inbound), or a staff user id (outbound reply). See /reference/staff-users. | `0` |
| `send` | boolean | - | Whether to dispatch the message to the lead through the reply pipeline (email/SMS/messaging). Defaults to true for staff senders and false for customer messages. Requires a staff sender and a channel. | `true` |
| `channel` | enum | - | Delivery channel, required when send is true. | `email` |
| `notify` | boolean | - | For recorded (send=false) messages: whether to update lead status and fire live notifications. Defaults to true. | `true` |
| `preview` | boolean | - | When send is true, return a rendered preview without dispatching or recording. | `false` |
| `replies` | boolean | - | When sending by email, include the prior message thread. Defaults to true. | `true` |
| `plain_text` | boolean | - | When sending by email, send plain text instead of the HTML template. | `false` |
| `media` | object | - | Optional media attachment for messaging channels. |  |
| `media.file` | string | - | Base64 media data (optionally a data: URL). Alternative to url. |  |
| `media.type` | enum | - | i=image, vi=video. |  |
| `media.url` | string | - | Publicly reachable https URL of the media. |  |
| `media.mime` | string | - | MIME type matching the media type, e.g. image/jpeg or video/mp4. |  |

```json
{
    "message": "Thanks for your enquiry. The vehicle is still available. When would suit you for a viewing?",
    "sender": 0,
    "send": true,
    "channel": "email",
    "notify": true,
    "preview": false,
    "replies": true,
    "plain_text": false,
    "media": {
        "file": "",
        "type": "i",
        "url": "",
        "mime": ""
    }
}
```

**Responses**

| Status | Description |
| --- | --- |
| `201` Created | Lead message created |

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": 88213,
        "lead": 4009,
        "sender": "0",
        "message": {
            "m": "Is this still available?"
        },
        "created": 1781303332,
        "delivered": 1781303340,
        "viewed": 0
    }
}
```

### GET Get Lead Message

`GET /2.0/leads/{id}/messages/{message_id}` · scope `lead-messages:read`

Retrieve a single lead message by id.

**Parameters (3)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `message_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 | Lead message |

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": 88213,
        "lead": 4009,
        "sender": "0",
        "message": {
            "m": "Is this still available?"
        },
        "created": 1781303332,
        "delivered": 1781303340,
        "viewed": 0
    }
}
```

### PATCH Update Lead Message

`PATCH /2.0/leads/{id}/messages/{message_id}` · scope `lead-messages:write`

Update a recorded lead message.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `message_id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `message` | string | Yes | The message body. A plain string is the common case; an object may carry structured fields (m, subject, html, text). | `Thanks for your enquiry. The vehicle is still available. When would suit you for a viewing?` |
| `sender` | integer | Yes | Who sent the message: 0 = the customer/lead (inbound), or a staff user id (outbound reply). See /reference/staff-users. | `0` |
| `send` | boolean | - | Whether to dispatch the message to the lead through the reply pipeline (email/SMS/messaging). Defaults to true for staff senders and false for customer messages. Requires a staff sender and a channel. | `true` |
| `channel` | enum | - | Delivery channel, required when send is true. | `email` |
| `notify` | boolean | - | For recorded (send=false) messages: whether to update lead status and fire live notifications. Defaults to true. | `true` |
| `preview` | boolean | - | When send is true, return a rendered preview without dispatching or recording. | `false` |
| `replies` | boolean | - | When sending by email, include the prior message thread. Defaults to true. | `true` |
| `plain_text` | boolean | - | When sending by email, send plain text instead of the HTML template. | `false` |
| `media` | object | - | Optional media attachment for messaging channels. |  |
| `media.file` | string | - | Base64 media data (optionally a data: URL). Alternative to url. |  |
| `media.type` | enum | - | i=image, vi=video. |  |
| `media.url` | string | - | Publicly reachable https URL of the media. |  |
| `media.mime` | string | - | MIME type matching the media type, e.g. image/jpeg or video/mp4. |  |

```json
{
    "message": "Thanks for your enquiry. The vehicle is still available. When would suit you for a viewing?",
    "sender": 0,
    "send": true,
    "channel": "email",
    "notify": true,
    "preview": false,
    "replies": true,
    "plain_text": false,
    "media": {
        "file": "",
        "type": "i",
        "url": "",
        "mime": ""
    }
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead message updated |

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": 88213,
        "lead": 4009,
        "sender": "0",
        "message": {
            "m": "Is this still available?"
        },
        "created": 1781303332,
        "delivered": 1781303340,
        "viewed": 0
    }
}
```

### DELETE Delete Lead Message

`DELETE /2.0/leads/{id}/messages/{message_id}` · scope `lead-messages:delete`

Delete a lead message.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `message_id` | path | string | Yes | Resource identifier in the path. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Lead message deleted |

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,
        "deleted": false
    }
}
```

### Notes

### GET List Lead Notes

`GET /2.0/leads/{id}/notes` · scope `lead-notes:read`

List the internal notes recorded against a lead.

**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 | List Lead Notes |

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": 2,
            "lead": 4009,
            "created": 1781303332,
            "user": 12,
            "note": "Customer prefers a callback after 5pm."
        }
    ]
}
```

### POST Add Lead Note

`POST /2.0/leads/{id}/notes` · scope `lead-notes:write`

Add an internal note to a lead, optionally attributed to a staff user.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `note` | string | Yes | The note text (supports line breaks). | `Customer prefers a callback after 5pm.` |
| `user` | integer | - | Optional staff user id the note is attributed to, from /reference/staff-users. | `1` |

```json
{
    "note": "Customer prefers a callback after 5pm.",
    "user": 1
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Add Lead Note |

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": 2,
        "lead": 4009,
        "created": 1781303332,
        "user": 12,
        "note": "Customer prefers a callback after 5pm."
    }
}
```

### DELETE Delete Lead Note

`DELETE /2.0/leads/{id}/notes/{note_id}` · scope `lead-notes:delete`

Delete a lead note.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `note_id` | path | string | Yes | Resource identifier in the path. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Delete Lead Note |

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,
        "deleted": false
    }
}
```

### Appointments

### GET List Lead Appointments

`GET /2.0/leads/{id}/appointments` · scope `lead-appointments:read`

List appointments associated with a lead.

**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 | List Lead Appointments |

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,
            "lead": 0,
            "contact": 0,
            "type": "appointment",
            "calendar": "",
            "booking": "",
            "date": "2026-01-01",
            "time": "",
            "purpose": "",
            "duration": 0,
            "duration_type": "m",
            "note": "",
            "user": [
                0
            ],
            "vehicle": 0,
            "persist": false,
            "done": false,
            "created": 0
        }
    ]
}
```

### POST Create Lead Appointment

`POST /2.0/leads/{id}/appointments` · scope `lead-appointments:write`

Create an appointment for a lead. Provide an optional vehicle (a stock id) or vehicle_tag to also link the appointment to a vehicle of interest, mirroring the lead vehicles endpoint.

**Parameters (1)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |

**Request body**

| Attribute | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `date` | string (date) | Yes | Appointment date (YYYY-MM-DD). | `2026-09-01` |
| `time` | string | Yes | Appointment time (HH:MM, 24-hour). | `14:30` |
| `type` | enum | - | The appointment kind. Defaults to appointment. | `appointment` |
| `purpose` | string | - | Free-text purpose/title for the appointment. | `Test drive` |
| `duration` | integer or null | - | Duration in the unit given by duration_type. | `30` |
| `duration_type` | enum | - | Duration unit: m=minutes, h=hours. | `m` |
| `note` | string | - | Internal note. | `Customer prefers the afternoon.` |
| `user` | array of integer | - | Staff user ids who own the appointment. | `[12]` |
| `calendar` | string | - | Calendar name. See /appointments/calendars. | `Sales` |
| `persist` | boolean | - | Whether the appointment persists across status changes. | `false` |
| `vehicle` | integer | - | Optional stock vehicle id to also link to the lead with this appointment. Use this or vehicle_tag. | `85481` |
| `vehicle_tag` | string | - | Optional alphanumeric vehicle tag, as an alternative to vehicle. | `HbSDTp97` |

```json
{
    "date": "2026-09-01",
    "time": "14:30",
    "type": "appointment",
    "purpose": "Test drive",
    "duration": 30,
    "duration_type": "m",
    "note": "Customer prefers the afternoon.",
    "user": [
        12
    ],
    "calendar": "Sales",
    "persist": false,
    "vehicle": 85481,
    "vehicle_tag": "HbSDTp97"
}
```

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Create Lead Appointment |

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,
        "lead": 0,
        "contact": 0,
        "type": "appointment",
        "calendar": "",
        "booking": "",
        "date": "2026-01-01",
        "time": "",
        "purpose": "",
        "duration": 0,
        "duration_type": "m",
        "note": "",
        "user": [
            0
        ],
        "vehicle": 0,
        "persist": false,
        "done": false,
        "created": 0
    }
}
```

### DELETE Remove Lead Appointment

`DELETE /2.0/leads/{id}/appointments/{appointment_id}` · scope `lead-appointments:delete`

Remove an appointment from a lead.

**Parameters (2)**

| Parameter | In | Type | Required | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Resource identifier in the path. |  |
| `appointment_id` | path | string | Yes | Resource identifier in the path. |  |

**Responses**

| Status | Description |
| --- | --- |
| `200` OK | Remove Lead Appointment |

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,
        "deleted": false
    }
}
```
