Documentation Index Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
Use this file to discover all available pages before exploring further.
Bulk import up to 1,000 historical click records per request. Each click is associated with an existing message and offer. Only one click per message_id is stored (MessageClick uses message_id as its primary key), so duplicate entries are automatically skipped.
Importing clicks also updates the associated ListContact’s denormalized stats: click_count and last_clicked_at.
Authentication
Your Trackly SMS API key. Format: trk_[32-char-hex].
Body Parameters
An array of click records to import. Maximum of 1,000 records per request. Each record accepts the following fields: The message ID this click is associated with. The message must already exist in the system.
The offer ID that was clicked. The offer must already exist in the system.
The contact’s phone number in E.164 format.
The original send timestamp of the associated message in ISO 8601 format.
The click timestamp in ISO 8601 format.
Response Fields
Number of click records successfully imported.
Number of records that failed validation or processing.
Number of records skipped because a click already exists for that message_id.
Array of error objects (maximum 100 returned). Each object contains:
index (integer) — Position of the failed record in the input array.
code (string) — Machine-readable error code.
error (string) — Human-readable error description.
curl -X POST https://api.tracklysms.com/api/v2/history/clicks \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"message_id": "a1b2c3d4",
"offer_id": "offer_123",
"phone_number": "+12025559876",
"send_timestamp": "2025-11-15T14:30:00Z",
"timestamp": "2025-11-15T14:35:22Z"
},
{
"message_id": "e5f6g7h8",
"offer_id": "offer_456",
"phone_number": "+13105558888",
"timestamp": "2025-11-15T15:10:45Z"
}
]
}'
import requests
response = requests.post(
"https://api.tracklysms.com/api/v2/history/clicks" ,
headers = {
"X-Api-Key" : "trk_your_api_key_here" ,
"Content-Type" : "application/json" ,
},
json = {
"records" : [
{
"message_id" : "a1b2c3d4" ,
"offer_id" : "offer_123" ,
"phone_number" : "+12025559876" ,
"send_timestamp" : "2025-11-15T14:30:00Z" ,
"timestamp" : "2025-11-15T14:35:22Z" ,
},
{
"message_id" : "e5f6g7h8" ,
"offer_id" : "offer_456" ,
"phone_number" : "+13105558888" ,
"timestamp" : "2025-11-15T15:10:45Z" ,
},
],
},
)
print (response.json())
const response = await fetch ( "https://api.tracklysms.com/api/v2/history/clicks" , {
method: "POST" ,
headers: {
"X-Api-Key" : "trk_your_api_key_here" ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({
records: [
{
message_id: "a1b2c3d4" ,
offer_id: "offer_123" ,
phone_number: "+12025559876" ,
send_timestamp: "2025-11-15T14:30:00Z" ,
timestamp: "2025-11-15T14:35:22Z" ,
},
{
message_id: "e5f6g7h8" ,
offer_id: "offer_456" ,
phone_number: "+13105558888" ,
timestamp: "2025-11-15T15:10:45Z" ,
},
],
}),
});
const data = await response . json ();
console . log ( data );
201 - Success
201 - Partial Success
400 - Validation Error
413 - Payload Too Large
{
"success_count" : 2 ,
"error_count" : 0 ,
"duplicates_skipped" : 0 ,
"errors" : []
}
Error Codes
HTTP Status Error Code Description 400 missing_recordsThe records field is required and must be a non-empty array. 413 too_many_recordsExceeded the maximum of 1,000 records per request. 400 missing_message_idA record is missing the message_id field. 400 missing_offer_idA record is missing the offer_id field. 400 missing_phone_numberA record is missing the phone_number field. 400 missing_timestampA record is missing the timestamp field. 404 message_not_foundNo message exists with the given message_id. 404 offer_not_foundNo offer exists with the given offer_id. 400 invalid_timestampThe timestamp is not a valid ISO 8601 datetime. 500 save_errorAn unexpected error occurred while saving the record.
Next Steps
Reporting Overview Analyze click data
Bulk Create Contacts Import contacts alongside history