curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}'
import requests
response = requests.put(
"https://api.tracklysms.com/api/v2/contacts",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json"
},
json={
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
)
print(response.json())
const response = await fetch("https://api.tracklysms.com/api/v2/contacts", {
method: "PUT",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "+14155559876",
list_number: "+18005551234",
custom_fields: {
vip_status: "gold",
last_purchase: "2026-02-10",
},
}),
});
const data = await response.json();
console.log(data);
curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"tier": "premium"
},
"merge_fields": false
}'
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"first_name": "Jane",
"source": "landing_page_v2",
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"tier": "premium"
}
}
{
"code": "missing_custom_fields",
"error": "custom_fields is required"
}
{
"code": "list_contact_not_found",
"error": "Contact is not on this list"
}
Contacts (v2)
Update Contact
Update custom fields for a contact on a specific sending list.
PUT
/
v2
/
contacts
curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}'
import requests
response = requests.put(
"https://api.tracklysms.com/api/v2/contacts",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json"
},
json={
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
)
print(response.json())
const response = await fetch("https://api.tracklysms.com/api/v2/contacts", {
method: "PUT",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "+14155559876",
list_number: "+18005551234",
custom_fields: {
vip_status: "gold",
last_purchase: "2026-02-10",
},
}),
});
const data = await response.json();
console.log(data);
curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"tier": "premium"
},
"merge_fields": false
}'
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"first_name": "Jane",
"source": "landing_page_v2",
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"tier": "premium"
}
}
{
"code": "missing_custom_fields",
"error": "custom_fields is required"
}
{
"code": "list_contact_not_found",
"error": "Contact is not on this list"
}
Update the custom fields attached to a contact on a given sending list. By default, the provided fields are merged into the existing custom fields — existing keys not included in the request are preserved. Set
merge_fields to false to replace the entire custom fields object.
Body Parameters
string
required
Contact phone number in E.164 format (e.g.,
+14155559876).string
required
Sending list phone number in E.164 format (e.g.,
+18005551234). Must be a list owned by your account.object
required
Key-value pairs to set on the contact’s custom fields. Values can be strings, numbers, or booleans.
boolean
default:"true"
When
true (default), the provided keys are merged into the existing custom fields — keys not included in the request are preserved. When false, the existing custom fields are entirely replaced with the provided object.Response Fields
boolean
Whether the operation completed successfully.
string
Unique identifier for the list membership that was updated.
object
The full custom fields object after the update.
Examples
curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}'
import requests
response = requests.put(
"https://api.tracklysms.com/api/v2/contacts",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json"
},
json={
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
)
print(response.json())
const response = await fetch("https://api.tracklysms.com/api/v2/contacts", {
method: "PUT",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "+14155559876",
list_number: "+18005551234",
custom_fields: {
vip_status: "gold",
last_purchase: "2026-02-10",
},
}),
});
const data = await response.json();
console.log(data);
curl -X PUT "https://api.tracklysms.com/api/v2/contacts" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155559876",
"list_number": "+18005551234",
"custom_fields": {
"tier": "premium"
},
"merge_fields": false
}'
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"first_name": "Jane",
"source": "landing_page_v2",
"vip_status": "gold",
"last_purchase": "2026-02-10"
}
}
{
"success": true,
"list_contact_id": "665a1b2c3d4e5f6a7b8c9d0f",
"custom_fields": {
"tier": "premium"
}
}
{
"code": "missing_custom_fields",
"error": "custom_fields is required"
}
{
"code": "list_contact_not_found",
"error": "Contact is not on this list"
}
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | missing_phone_number | The phone_number field was not provided. |
| 400 | missing_list_number | The list_number field was not provided. |
| 400 | missing_custom_fields | The custom_fields field was not provided. |
| 400 | invalid_custom_fields | The custom_fields field must be a JSON object. |
| 400 | invalid_phone | The phone_number is not a valid E.164 phone number. |
| 400 | invalid_list_number | The list_number is not a valid E.164 phone number. |
| 400 | contact_not_found | No contact exists with the given phone number. |
| 400 | list_not_found | No sending list with the given list_number exists for this account. |
| 400 | list_contact_not_found | The contact exists but is not on the specified list. |
| 401 | invalid_credentials | Missing or invalid X-Api-Key header. |
| 403 | account_suspended | Your account is suspended. Resolve outstanding billing or contact support. |
| 500 | internal_error | An unexpected server error occurred. |
Next Steps
Importing Contacts
Bulk update contacts
Create Audience
Segment contacts into audiences