> For the complete documentation index, see [llms.txt](https://teamleader-sdk.mcore-services.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://teamleader-sdk.mcore-services.dev/api-reference/crm/contacts.md).

# Contacts

Manage contacts in Teamleader Focus CRM.

```php
Teamleader::contacts()
```

|                          |                                                                       |
| ------------------------ | --------------------------------------------------------------------- |
| Class                    | `McoreServices\TeamleaderSDK\Resources\CRM\Contacts`                  |
| Create / update / delete | ✓ / ✓ / ✓                                                             |
| Pagination               | `page_size` / `page_number`; no totals — a short page is the last one |

## Endpoints

* `contacts.add`
* `contacts.delete`
* `contacts.info`
* `contacts.linkToCompany`
* `contacts.list`
* `contacts.tag`
* `contacts.unlinkFromCompany`
* `contacts.untag`
* `contacts.update`
* `contacts.updateCompanyLink`
* `contacts.uploadAvatar`

## Filters

Passed as the first argument to `list()`. Any other key throws.

| Filter                    | Description                                                         |
| ------------------------- | ------------------------------------------------------------------- |
| `company_id`              | Company UUID, or null for contacts linked to no company             |
| `email`                   | Email address — a string, or \["type" => "primary", "email" => ...] |
| `ids`                     | Array of contact UUIDs (a single UUID string is wrapped)            |
| `marketing_mails_consent` | Marketing mails consent (boolean)                                   |
| `status`                  | active or deactivated                                               |
| `tags`                    | Array of tag names (filters on contacts coupled to all given tags)  |
| `term`                    | Search term (searches first\_name, last\_name, email and telephone) |
| `updated_since`           | ISO 8601 datetime                                                   |

## Sorting

Pass `sort` (and optionally `sort_order`) in the options. Any other field throws.

| Field        | Description                       |
| ------------ | --------------------------------- |
| `added_at`   | Date the contact was added        |
| `name`       | Contact name                      |
| `updated_at` | Date the contact was last updated |

## Includes

| Endpoint | Includes        |
| -------- | --------------- |
| `list()` | `custom_fields` |
| `info()` | none            |

## Accepted values

Public constants on the class. Body fields and enum values outside these lists throw before the request is sent.

| Constant             | Values                                                                                                                                                                                                                                                      |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADDRESS_TYPES`      | `primary`, `invoicing`, `delivery`, `visiting`                                                                                                                                                                                                              |
| `EMAIL_TYPES`        | `primary`                                                                                                                                                                                                                                                   |
| `FILTER_EMAIL_TYPES` | `primary`                                                                                                                                                                                                                                                   |
| `GENDERS`            | `female`, `male`, `non_binary`, `prefers_not_to_say`, `unknown`                                                                                                                                                                                             |
| `STATUSES`           | `active`, `deactivated`                                                                                                                                                                                                                                     |
| `TELEPHONE_TYPES`    | `phone`, `mobile`, `fax`                                                                                                                                                                                                                                    |
| `WRITE_FIELDS`       | `first_name`, `last_name`, `salutation`, `emails`, `telephones`, `website`, `addresses`, `gender`, `birthdate`, `iban`, `bic`, `national_identification_number`, `language`, `price_list_id`, `remarks`, `tags`, `custom_fields`, `marketing_mails_consent` |

## Methods

### `info()`

```php
info($id, $includes = null): array
```

Get contact information

`contacts.info` accepts no includes parameter — the spec declares none. Custom fields and the price list are returned automatically; `price_list` is present whenever the account has access to price lists, and null when no price list is set on the contact.

* `$id` — Contact UUID
* `$includes` — Not supported by this endpoint

**Throws** `InvalidArgumentException` When includes are requested

### `create()`

```php
create(array $data): array
```

Create a new contact

### `update()`

```php
update($id, array $data): array
```

Update a contact

### `delete()`

```php
delete($id, ...$additionalParams): array
```

Delete a contact

### `uploadAvatar()`

```php
uploadAvatar(string $id, ?string $image): array
```

Upload or remove a contact avatar. Pass a base64 data URI string to set the avatar, or null to remove it.

* `$id` — Contact UUID
* `$image` — Base64 data URI (e.g. data:image/png;base64,...) or null to remove

### `search()`

```php
search(string $term, array $options = []): array
```

Search contacts by term (searches first\_name, last\_name, email and telephone)

### `list()`

```php
list(array $filters = [], array $options = []): array
```

List contacts

* `$filters` — See $commonFilters; unknown keys throw
* `$options` — page\_size, page\_number, sort, sort\_order, include

**Throws** `InvalidArgumentException` On an unknown filter, sort field or include

### `byEmail()`

```php
byEmail(string $email, array $options = []): array
```

Find contacts by email

### `forCompany()`

```php
forCompany(string $companyId, array $options = []): array
```

Get contacts for a specific company

### `withoutCompany()`

```php
withoutCompany(array $options = []): array
```

Get contacts linked to no company at all

Sends `filter.company_id: null`, which the API has accepted since specification 1.221.0. A contact whose only linked company has been deleted is part of this set.

### `withTags()`

```php
withTags($tags, array $options = []): array
```

Get contacts with specific tags

### `updatedSince()`

```php
updatedSince(string $date, array $options = []): array
```

Get contacts updated since a specific date

### `active()`

```php
active(array $options = []): array
```

Get active contacts only

### `deactivated()`

```php
deactivated(array $options = []): array
```

Get deactivated contacts only

### `manageTags()`

```php
manageTags(string $id, array $tagsToAdd = [], array $tagsToRemove = []): array
```

Manage tags (add/remove)

### `tag()`

```php
tag(string $id, $tags): array
```

Tag a contact

### `untag()`

```php
untag(string $id, $tags): array
```

Untag a contact

### `linkToCompany()`

```php
linkToCompany(string $id, string $companyId, array $data = []): array
```

Link a contact to a company

### `unlinkFromCompany()`

```php
unlinkFromCompany(string $id, string $companyId): array
```

Unlink a contact from a company

### `updateCompanyLink()`

```php
updateCompanyLink(string $id, string $companyId, array $data = []): array
```

Update contact to company link

### `withCustomFields()`

```php
withCustomFields(): self
```

Include custom fields in the next list() request

The only include contacts.list accepts. Note that contacts.info takes no includes at all, so this must not be chained into info().

## Examples

Get all contacts:

```php
$contacts = Teamleader::contacts()->list();
```

Search contacts by term:

```php
$contacts = Teamleader::contacts()->search("John");
```

Get contacts for specific company:

```php
$contacts = Teamleader::contacts()->forCompany("company-uuid");
```

Get contacts linked to no company:

```php
$contacts = Teamleader::contacts()->withoutCompany();
```

Find contact by email:

```php
$contacts = Teamleader::contacts()->byEmail("john@example.com");
```

Get contacts with custom fields:

```php
$contacts = Teamleader::contacts()->withCustomFields()->list();
```

Create a new contact:

```php
$contact = Teamleader::contacts()->create(["first_name" => "John", "last_name" => "Doe"]);
```

Link a contact to a price list:

```php
Teamleader::contacts()->update("contact-uuid", ["price_list_id" => "price-list-uuid"]);
```

Remove the price list from a contact:

```php
Teamleader::contacts()->update("contact-uuid", ["price_list_id" => null]);
```
