{
"success_count": 2,
"error_count": 0,
"duplicates_skipped": 0,
"invalid_phones": 0,
"errors": []
}
{
"success_count": 1,
"error_count": 0,
"duplicates_skipped": 1,
"invalid_phones": 0,
"errors": []
}
{
"error": "records array is required",
"code": "missing_records"
}
{
"error": "Maximum 1000 records per request",
"code": "too_many_records"
}
Data Import (v2)
Import Send History
Import historical send records into your account.
POST
/
v2
/
history
/
sends
{
"success_count": 2,
"error_count": 0,
"duplicates_skipped": 0,
"invalid_phones": 0,
"errors": []
}
{
"success_count": 1,
"error_count": 0,
"duplicates_skipped": 1,
"invalid_phones": 0,
"errors": []
}
{
"error": "records array is required",
"code": "missing_records"
}
{
"error": "Maximum 1000 records per request",
"code": "too_many_records"
}
Bulk import up to 1,000 historical send records per request. Use this endpoint to migrate data from another platform into Trackly SMS. Duplicate message IDs are automatically skipped, and invalid phone numbers are flagged in the response.
Authenticated requests can also fail with Per-record errors (
Authentication
string
required
Your Trackly SMS API key. Format:
trk_[32-char-alphanumeric].Body Parameters
array
required
An array of send records to import. Maximum of 1,000 records per request. Each record accepts the following fields:
Show Record fields
Show Record fields
string
required
A unique message ID. Duplicate IDs are skipped.
integer
The sending list ID. Either
list_id or list_number is required.string
The sending list phone number in E.164 format (e.g.,
+14155551234). Either list_id or list_number is required.string
required
The recipient phone number in E.164 format.
string
The message text that was sent. Accepted for compatibility but not currently stored — the imported record does not persist message text.
integer
Reference to a creative ID in Trackly SMS. Accepted for compatibility but not currently stored on the imported record.
string
Reference to a schedule ID in Trackly SMS. Accepted for compatibility but not currently stored on the imported record.
string
default:"campaign"
Type of send. One of:
campaign, transactional, or test.boolean
Whether the message was successfully delivered.
integer
Length of the message in characters.
datetime
required
The original send timestamp in ISO 8601 format.
All records imported via this endpoint are automatically marked as
imported=true. This flag is set by the server and cannot be overridden. Imported records can be selectively cleared later via the Clear History endpoint.Response Fields
integer
Number of send records successfully imported.
integer
Number of records that failed validation or processing.
integer
Number of records skipped because their ID already exists.
integer
Number of records skipped due to invalid phone numbers.
array
Array of error objects (maximum 100 returned). Each object contains:
index(integer) — Position of the failed record in the input array.id(string) — The message ID of the failed record.code(string) — Machine-readable error code.error(string) — Human-readable error description.
cURL
curl -X POST https://api.tracklysms.com/api/v2/history/sends \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"id": "hist_0001",
"list_number": "+14155551234",
"to_number": "+12025559876",
"message": "Check out this deal!",
"send_type": "campaign",
"delivered": true,
"length": 21,
"timestamp": "2025-11-15T14:30:00Z"
},
{
"id": "hist_0002",
"list_id": 42,
"to_number": "+13105558888",
"message": "Limited time offer",
"creative_id": 101,
"send_type": "campaign",
"delivered": true,
"timestamp": "2025-11-15T14:31:00Z"
}
]
}'
Python
import requests
response = requests.post(
"https://api.tracklysms.com/api/v2/history/sends",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"records": [
{
"id": "hist_0001",
"list_number": "+14155551234",
"to_number": "+12025559876",
"message": "Check out this deal!",
"send_type": "campaign",
"delivered": True,
"length": 21,
"timestamp": "2025-11-15T14:30:00Z",
},
{
"id": "hist_0002",
"list_id": 42,
"to_number": "+13105558888",
"message": "Limited time offer",
"creative_id": 101,
"send_type": "campaign",
"delivered": True,
"timestamp": "2025-11-15T14:31:00Z",
},
],
},
)
print(response.json())
Node.js
const response = await fetch("https://api.tracklysms.com/api/v2/history/sends", {
method: "POST",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
records: [
{
id: "hist_0001",
list_number: "+14155551234",
to_number: "+12025559876",
message: "Check out this deal!",
send_type: "campaign",
delivered: true,
length: 21,
timestamp: "2025-11-15T14:30:00Z",
},
{
id: "hist_0002",
list_id: 42,
to_number: "+13105558888",
message: "Limited time offer",
creative_id: 101,
send_type: "campaign",
delivered: true,
timestamp: "2025-11-15T14:31:00Z",
},
],
}),
});
const data = await response.json();
console.log(data);
{
"success_count": 2,
"error_count": 0,
"duplicates_skipped": 0,
"invalid_phones": 0,
"errors": []
}
{
"success_count": 1,
"error_count": 0,
"duplicates_skipped": 1,
"invalid_phones": 0,
"errors": []
}
{
"error": "records array is required",
"code": "missing_records"
}
{
"error": "Maximum 1000 records per request",
"code": "too_many_records"
}
Error Codes
Only two conditions reject the whole request. Every other error is reported per record: the request still returns201, and each failed record appears in the response’s errors[] array with a code (see the Partial Success example above).
Request errors (HTTP status)
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | missing_records | The records field is required and must be a non-empty array. |
| 413 | too_many_records | Exceeded the maximum of 1,000 records per request. |
401 invalid_credentials or 403 account_suspended — see Error Codes.
Per-record errors (errors[].code, returned with HTTP 201)
| Error Code | Description |
|---|---|
missing_id | A record is missing the id field. |
missing_to_number | A record is missing the to_number field. |
missing_timestamp | A record is missing the timestamp field. |
invalid_phone | The phone number is not a valid E.164 format. |
list_not_found | No sending list found matching the given list_id or list_number. |
invalid_timestamp | The timestamp is not a valid ISO 8601 datetime. |
save_error | An unexpected error occurred while saving the record. |
Next Steps
Reporting Overview
Analyze your imported data
Bulk Create Contacts
Import contacts alongside history