Add contacts to a list
/api/v1/contact-lists/{contactList}/membersAdds 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
| Name | In | Type | Description |
|---|---|---|---|
contactListrequired | path | string | The contact list identifier. |
Request body
contact_idsarray<string>requiredIds of contacts that already exist in your organization.
Request
/api/v1/contact-lists/{contactList}/memberscurl -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"
]
}'const response = await fetch('https://app.mailyte.com/api/v1/contact-lists/01JBT8XQ2M9WYC3K4F6R7S8T9V/members', {
method: 'POST',
headers: {
Authorization: 'Bearer mk_live_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"contact_ids": [
"01m2q1qc6skqy6k2sq88abm4pw",
"01m2r4sx6d2h67srjk6knwjczp"
]
}),
});
const { data } = await response.json();import requests
response = requests.post(
"https://app.mailyte.com/api/v1/contact-lists/01JBT8XQ2M9WYC3K4F6R7S8T9V/members",
headers={"Authorization": "Bearer mk_live_YOUR_API_KEY"},
json={
"contact_ids": [
"01m2q1qc6skqy6k2sq88abm4pw",
"01m2r4sx6d2h67srjk6knwjczp"
]
},
)
data = response.json()["data"]<?php
$response = Http::withToken('mk_live_YOUR_API_KEY')
->post('https://app.mailyte.com/api/v1/contact-lists/01JBT8XQ2M9WYC3K4F6R7S8T9V/members', [
'contact_ids' => [
'01m2q1qc6skqy6k2sq88abm4pw',
'01m2r4sx6d2h67srjk6knwjczp',
],
]);
$data = $response->json('data');require "net/http"
require "json"
uri = URI("https://app.mailyte.com/api/v1/contact-lists/01JBT8XQ2M9WYC3K4F6R7S8T9V/members")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer mk_live_YOUR_API_KEY"
request["Content-Type"] = "application/json"
request.body = {
"contact_ids": [
"01m2q1qc6skqy6k2sq88abm4pw",
"01m2r4sx6d2h67srjk6knwjczp"
]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }Response
Success.
dataobjectONE 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_membershiplist_idstringThe list this happened to, echoed from the path so the response can be logged on its own.
addedintegerNewly 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.
removedintegerDetached. Removing somebody who was not a member is a no-op and counts 0. Zero on an add.
skippedintegerIds 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_countintegerThe 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
| Status | When |
|---|---|
401 | The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist. |
403 | The 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. |
404 | No such resource in this organization. |
422 | The request was understood but the values were not acceptable. |
429 | Too 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.