# Contacts

The people you email: what a contact holds, how to add many at once, and how to export or erase one.

## What a contact holds

- **email**: the address, stored in lowercase. It never changes; to move someone to a new address, create a new contact.
- **first_name**, **last_name**: used by the `{{ first_name }}` and `{{ last_name }}` merge tags.
- **timezone**: an IANA zone like `Europe/London`. Campaign send windows use it before the campaign’s or project’s zone.
- **tags**: labels like `trial` or `customer`, up to 50 per contact.
- **attributes**: key and value pairs like `plan = pro`, up to 100 per contact. Keys use lowercase letters, digits and underscores.
- **is_unsubscribed**, **is_blocked**: read from the address’s history, see [Unsubscribes and blocks](https://sendocado.com/docs/blocked-list).

## Add contacts from your app

Create one contact when someone signs up. The answer is `409 contact_exists` when the address is already in the project.

```sh Create a contact
curl -X POST "https://sendocado.com/api/v1/projects/$PROJECT_ID/contacts" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "maya@example.com",
  "first_name": "Maya",
  "last_name": "Patel",
  "timezone": "Europe/London",
  "tags": ["trial"],
  "attributes": {
    "plan": "trial",
    "company": "Northwind"
  }
}'
```

To create or update many at once, send up to 1,000 contacts to the batch route. It is all or nothing: one bad contact refuses the whole batch, and the error names its index. For a contact that already exists, a `null` field keeps what is stored, tags are added, and attributes are set.

```sh Create or update contacts
curl -X PUT "https://sendocado.com/api/v1/projects/$PROJECT_ID/contacts/batch" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "contacts": [
    {
      "email": "maya@example.com",
      "first_name": "Maya",
      "last_name": null,
      "timezone": null,
      "tags": ["customer"],
      "attributes": {
        "plan": "pro"
      }
    },
    {
      "email": "leo@example.com",
      "first_name": "Leo",
      "last_name": "Martin",
      "timezone": "Europe/Paris",
      "tags": ["trial"],
      "attributes": {}
    }
  ]
}'
```

A new contact, or one whose tags or attributes change, joins every live campaign whose audience it now matches within seconds.

## Find contacts

List contacts with one of `search` (email and name), `tag` or `email`. To see which tags and attribute keys are in use, for building an audience, list the contact tags and attribute keys.

## History and privacy

- **Activity** lists every email sent to the address and what happened to it.
- **Export** returns everything held about a contact in one JSON document, for a subject-access request.
- **Erasure** deletes the contact and everything sent to the address. The address stays unsubscribed or blocked, without the address itself, so it can never be mailed again by mistake.

Deleting a contact only removes the contact: its unsubscribes and blocks stay.

See the [Contacts reference](https://sendocado.com/docs/api/contacts) for every route.
