Add contacts to a list

POST/api/v1/contact-lists/{contactList}/members
Requires anorganization API keywith the scopecontacts:write

Adds existing contacts to a list. This does not create contacts — create them first with POST /api/v1/contacts, then add them here by id.

Adding somebody who is already on the list is a no-op rather than an error or a duplicate, so this is safe to call repeatedly with the same payload.

Ids that do not belong to your organization are ignored rather than rejected, and counted in skipped. They are not named: saying which ids were unknown would confirm which ids exist in somebody else's account. If skipped comes back non-zero, check the ids you sent.

Parameters

NameInTypeDescription
contactListrequiredpathstringThe contact list identifier.

Request body

  • contact_idsarray<string>required

    Ids of contacts that already exist in your organization.

Request

POST/api/v1/contact-lists/{contactList}/members
curl -X POST 'https://app.mailyte.com/api/v1/contact-lists/01JBT8XQ2M9WYC3K4F6R7S8T9V/members' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "contact_ids": [
      "01m2q1qc6skqy6k2sq88abm4pw",
      "01m2r4sx6d2h67srjk6knwjczp"
    ]
  }'
The key names its own organization, so no X-Organization-ID header is needed.

Response

Success.

  • dataobject

    ONE shape for both directions — adding members and removing one answer the same five counters, with the irrelevant ones at zero — so a caller writing a "sync my list" routine never has to branch on which call it just made.

    • objectstringcontact_list_membership
    • list_idstring

      The list this happened to, echoed from the path so the response can be logged on its own.

    • addedinteger

      Newly attached. Re-adding an existing member is a no-op that still counts as added — the request "this contact is on this list" was satisfied either way. Zero on a removal.

    • removedinteger

      Detached. Removing somebody who was not a member is a no-op and counts 0. Zero on an add.

    • skippedinteger

      Ids that resolved to nothing in this organization. Both endpoints quietly ignore ids they cannot see — answering "no such contact" would confirm which ids exist in someone else's account — so without this counter a caller submitting 500 ids and having 40 ignored would have no way to know. It does not name them, for the same reason.

    • contact_countinteger

      The size of the list AFTER the change, so you never have to follow up with a GET. Counts every member whatever their state, exactly as `contact_list.contact_count` does.

Returned inside the standard envelope.

Errors

StatusWhen
401The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist.
403The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys.
404No such resource in this organization.
422The request was understood but the values were not acceptable.
429Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait.

Every status, with what causes it and what to do, is on the error reference.