> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.laposta.org/llms.txt.

# Synchronising subscribers through the API

> Keep your list in sync with your webshop or CRM: adding, updating, unsubscribing and handling errors.

With an API connection, sign-ups from your webshop, CRM or website automatically end up in the right list.

## Retrieving and storing fields

You pass custom fields under `custom_fields`, using the field's `custom_name` as the key. This name sometimes differs from what you might expect: the field called ‘First name’ in the application is usually called `voornaam` in the API. Therefore, retrieve these names once and store them in your own code.

**`curl`**

```bash title="curl"
curl "https://api.laposta.nl/v2/field?list_id=BaImMu3JZA" \
  -u YOUR_API_KEY:
```

**`PHP`**

```php title="PHP"
$laposta = new Laposta('YOUR_API_KEY');
$fields = $laposta->fieldApi()->all('BaImMu3JZA');
```

> **Tip**
>
> Do not retrieve the field names with every sign-up, but store them in your own system and refresh them, for example, once a day. Fields rarely change, and every call counts towards your limit of 30 requests per minute (120 on a paid account). With a busy webshop, you would otherwise quickly use up your limit requesting data you already had.

## Adding and updating a subscriber

#### Include the email address, the IP-address and your custom fields

The IP-address is required: it records where the sign-up came from. You need this to prove that someone signed up themselves.

**`curl`**

```bash title="curl"
curl https://api.laposta.nl/v2/member \
  -u YOUR_API_KEY: \
  -d list_id=BaImMu3JZA \
  -d ip=198.51.100.10 \
  -d email=new.subscriber@example.net \
  -d source_url=https://example.net/subscribe \
  -d custom_fields[voornaam]=Sanne
```

**`PHP`**

```php title="PHP"
$laposta = new Laposta('YOUR_API_KEY');
$subscriber = $laposta->memberApi()->create('BaImMu3JZA', [
    'ip' => '198.51.100.10',
    'email' => 'new.subscriber@example.net',
    'source_url' => 'https://example.net/subscribe',
    'custom_fields' => ['voornaam' => 'Sanne'],
]);
```

#### Handle the message if the address already exists

If the address is already in the list, you will receive a `400` with error code `204`. If you want to update the existing data instead of receiving an error in that case, set `options[upsert]` to `true`.

#### Update data later

Make a POST request to the subscriber itself to update data. You only need to include what changes. The other fields remain unchanged. You can use the `member_id` for this, or simply the email address.

**`curl`**

```bash title="curl"
curl https://api.laposta.nl/v2/member/new.subscriber@example.net \
  -u YOUR_API_KEY: \
  -d list_id=BaImMu3JZA \
  -d custom_fields[woonplaats]=Utrecht
```

**`PHP`**

```php title="PHP"
$laposta->memberApi()->update('BaImMu3JZA', 'new.subscriber@example.net', [
    'custom_fields' => ['woonplaats' => 'Utrecht'],
]);
```

## Unsubscribing or deleting a subscriber

If someone unsubscribes via your own site, it is best to set the subscriber to unsubscribed. Only use delete if someone asks to have their data completely erased.

| What you do | How                                                | What happens                                                                                                                             |
| ----------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Unsubscribe | update with `state` set to `unsubscribed`          | The subscriber remains in the system and no longer receives anything. If someone signs up again later, you will see this in the history. |
| Delete      | [Delete subscriber](/relaties/relatie-verwijderen) | The subscriber is permanently removed, including the history.                                                                            |

## Synchronising an entire list at once

If you synchronise per subscriber, it will take a long time when you have thousands of subscribers and you will hit the rate limit. Instead, use [Synchronise list (bulk)](/lijsten/lijst-synchroniseren-bulk): this allows you to send up to 500,000 subscribers as JSON in a single call.

**`JSON`**

```json title="JSON"
{
  "actions": ["add", "update"],
  "members": [
    { "email": "first@example.net", "custom_fields": { "voornaam": "Sanne" } },
    { "email": "second@example.net" }
  ]
}
```

With the PHP library, you send the same content as an array:

**`PHP`**

```php title="PHP"
$laposta->listApi()->syncMembers('BaImMu3JZA', [
    'actions' => ['add', 'update'],
    'members' => [
        ['email' => 'first@example.net', 'custom_fields' => ['voornaam' => 'Sanne']],
        ['email' => 'second@example.net'],
    ],
]);
```

With the `unsubscribe_excluded` action, you unsubscribe everyone who is not included in your submission. Only use this if your system is the source of truth, and not if you are only submitting a part of your file.

> **Warning**
>
> Bulk is not enabled by default. It is only available for paid accounts, and Laposta has to enable it per account. If you receive a `401` with "Not permitted to issue bulk requests (1)", please contact the helpdesk at [helpdesk@laposta.nl](mailto:helpdesk@laposta.nl) and state your account number.

## What should you watch out for?

* You cannot empty a multiple-choice field by sending an empty list. If you send an empty list for a `select_multiple` field, the existing choices are not cleared. See: [Common mistakes](/veelgemaakte-fouten-met-de-api).
* If you send a label as plain text, all existing labels are cleared. Send `"labels": ["Customer"]` and not `"labels": "Customer"`. If you do it wrong, you will simply receive a `200` with `edited_count` without an error message, but all labels will be empty. See: [Common mistakes](/veelgemaakte-fouten-met-de-api).
* An unknown ID does not return a `404`, but a `400` with code `203`. Make sure to test for that.
* The limit is tighter than you might think on a free account: 30 requests per minute. Build in a delay based on the `Retry-After` header instead of retrying immediately.

## Related articles

#### [Using webhooks for modifications in a list](/webhooks-gebruiken)

With a webhook, Laposta notifies your system as soon as someone subscribes…

#### [What are common mistakes with the API?](/veelgemaakte-fouten-met-de-api)

Pitfalls when integrating with the Laposta API, including the error message you get and…

#### [What are the limits and error messages of the API?](/api-limieten-en-foutmeldingen)

How many requests per minute the API allows and which status and error codes may be…