> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.laposta.org/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.laposta.org/_mcp/server.

# What are common mistakes with the API?

> Pitfalls when integrating with the Laposta API, including the error message you get and the solution.

## An unknown ID does not return a 404

If you check whether a list or subscriber exists by testing for a `404`, you will miss any unknown ID. In that case, the API returns a `400`:

```json
{ "error": { "type": "invalid_input", "message": "Unknown list", "code": 203, "parameter": "list_id" } }
```

You only receive a `404` for a path that does not exist, such as a typo in the URL. You should therefore check for `code` `203` instead of the status code.

Note the difference between two codes here: an ID or email address that does not exist in the list returns `203`, whereas `202` ("Invalid member_id") means the syntax of the parameter is incorrect.

## An empty multiple-choice field is not cleared

If you send an empty list for a `select_multiple` field, the choices will not disappear. The existing values remain in place, and you simply receive a `200` back without an error message.

**`curl`**

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

**`PHP`**

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

If you want to be sure a selection is empty, check the response and report it via [helpdesk@laposta.nl](mailto:helpdesk@laposta.nl) if it still contains values.

## Sending labels without square brackets does not work

A subscriber can have multiple [labels](/labels), so the field expects an array. If you send a single value without brackets, you will receive a `200` back containing the subscriber without an error message, and nothing will have changed.

**`curl`**

```bash title="curl"
-d "custom_fields[labels]=Customer"      # succeeds, but does nothing
-d "custom_fields[labels][]=Customer"    # this is the right way
```

**`PHP`**

```php title="PHP"
'custom_fields' => ['labels' => 'Customer']      // succeeds, but does nothing
'custom_fields' => ['labels' => ['Customer']]    // this is the right way
```

The `labels` field only exists once the list has at least one label. Before that, it will not appear in the fields or with the subscriber. You cannot use it to create a label either: a name that the list does not recognise returns a `400`.

```json
{ "error": { "type": "invalid_input", "message": "Field labels: unknown option", "code": 203, "parameter": "labels" } }
```

Always send the name and not the ID from `options_full`. An ID returns the same message.

For bulk requests, you send JSON, which means using an array rather than brackets. If you send a plain string there, the API counts the subscriber as modified without an error message, but that subscriber's labels will then be empty.

```json
"custom_fields": { "labels": "Customer" }     // 200, edited_count 1, labels empty afterwards
"custom_fields": { "labels": ["Customer"] }   // this is the right way
```

If you send an unknown label in a bulk request, that subscriber will be placed in `errors` with the same code `203`, and will not be added.

## Bulk is disabled by default

The endpoint for bulk synchronisation exists in every account, but returns a `401` without permission:

```json
{ "error": { "type": "invalid_request", "message": "Not permitted to issue bulk requests (1)" } }
```

This is not an error in your code. You can read who can use bulk and how to have it enabled under [Synchronising subscribers through the API](/relaties-synchroniseren-via-de-api).

## A campaign is sent twice if called a second time

If you call [Send campaign](/campagnes/campagne-verzenden) twice, you will receive a `200` both times and the delivery will be triggered again. You can find out how to prevent this in your own code under [Sending a campaign through the API](/campagne-versturen-via-de-api).

Editing a campaign that has already been sent is not blocked either.

## Retrieving campaign content does not work for every campaign

If you request the content of a campaign created in the drag & drop editor, you will receive:

```json
{ "error": { "type": "invalid_input", "message": "Wrong campaign type", "code": 203, "parameter": "campaign_id" } }
```

This is not a fault. You can see which campaigns support this under [Sending a campaign through the API](/campagne-versturen-via-de-api).

## The \_iso field may be missing

When a date field is empty, the `_iso` variant is sometimes completely absent from the response instead of being `null`. Always check whether this field is present in the response before reading it, otherwise your code will fail on a missing key. See: [Date and time fields in the API](/api-datum-en-tijdvelden).

## You can quickly reach the request limit

On a free account, you can make 30 requests per minute, and 120 on a paid account. A synchronisation that makes a call per subscriber will quickly use this up if you have a few hundred subscribers.

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
```

Wait for the number of seconds specified in the `Retry-After` header instead of trying again at once, and use [bulk synchronisation](/lijsten/lijst-synchroniseren-bulk) for large numbers. You can read more about this under [API limits and error messages](/api-limieten-en-foutmeldingen).

## An unknown field name in a segment does not return an error message

You create a segment using a definition in JSON. The API checks the format and the comparisons, but not whether the field you are selecting on actually exists. A typo in a field name will therefore simply return a `201`, resulting in a segment that selects nobody.

You should therefore check the field names in your definition against the fields you have retrieved using [Retrieve all fields](/velden/alle-velden-opvragen).

## Related articles

#### [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…

#### [Synchronising subscribers through the API](/relaties-synchroniseren-via-de-api)

Keep your list in sync with your webshop or CRM: adding, updating, unsubscribing and…

#### [Trying out the API with Try it](/api-uitproberen)

Send a real call to the Laposta API from your browser, without installing anything.