curl -X POST https://api.tracklysms.com/api/v2/send-raw \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": true,
"skip_rate_limit": true
}'
import requests
response = requests.post(
"https://api.tracklysms.com/api/v2/send-raw",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": True,
"skip_rate_limit": True,
},
)
data = response.json()
print(data["message_id"])
const response = await fetch("https://api.tracklysms.com/api/v2/send-raw", {
method: "POST",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+14155551234",
list_number: "+18005551000",
body: "URGENT: Your verification code is 482901. Ref: {{messageId}}",
skip_duplicate_check: true,
skip_rate_limit: true,
}),
});
const data = await response.json();
console.log(data.message_id);
{
"success": true,
"message_id": "x7y8z9w0",
"status": "queued"
}
{
"error": "Invalid recipient phone number format",
"code": "invalid_phone"
}
Messages (v2)
Send Raw Single Message
Send a single raw SMS message with optional skip flags for advanced control.
POST
/
v2
/
send-raw
curl -X POST https://api.tracklysms.com/api/v2/send-raw \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": true,
"skip_rate_limit": true
}'
import requests
response = requests.post(
"https://api.tracklysms.com/api/v2/send-raw",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": True,
"skip_rate_limit": True,
},
)
data = response.json()
print(data["message_id"])
const response = await fetch("https://api.tracklysms.com/api/v2/send-raw", {
method: "POST",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+14155551234",
list_number: "+18005551000",
body: "URGENT: Your verification code is 482901. Ref: {{messageId}}",
skip_duplicate_check: true,
skip_rate_limit: true,
}),
});
const data = await response.json();
console.log(data.message_id);
{
"success": true,
"message_id": "x7y8z9w0",
"status": "queued"
}
{
"error": "Invalid recipient phone number format",
"code": "invalid_phone"
}
Keys requiring send approval receive
Authenticated requests can also fail with
403 confirmation_required for direct sends. Use pending sends for approved single or bulk SMS; raw sends have no approval workflow.
Send a single SMS message. This endpoint accepts a set of skip_* flags intended for granular control over validation and rate-limiting behavior.
The
skip_* flags are currently accepted but have no effect. The endpoint does not read them, so every check it performs runs regardless of what you pass. This endpoint skips the recipient consent checks that POST /v2/send runs before queuing: a recipient who has opted out of the list or is blocked on it is accepted here with 201 instead of 400 contact_suppressed. That message is still dropped before delivery with status contact_blocked, so a 201 is not proof of delivery — read the message status. Every other consent decision is yours: use this endpoint only for recipients whose consent you manage yourself. It differs from POST /v2/send in more than link wrapping and contact-data macro substitution.The following checks are always enforced:
- Your account must own the sending list
- Phone numbers must be in E.164 format
- Your account must be in active status
Body Parameters
string
required
Recipient phone number in E.164 format (e.g.
+14155551234).string
required
Sending list phone number in E.164 format. Must belong to your account.
string
required
Message body text. Use the
{{messageId}} placeholder to insert the unique message ID into the body at send time.boolean
default:"false"
Intended to skip the duplicate message check. Currently accepted but ignored — this flag has no effect.
boolean
default:"false"
Intended to skip per-list rate limiting. Currently accepted but ignored — this flag has no effect.
boolean
default:"false"
Intended to skip contact validation such as opt-out and block list checks. Currently accepted but ignored — this flag has no effect, and this endpoint does not run those opt-out or block-list checks in the first place.
boolean
default:"false"
Intended to skip the journey enrollment check. Currently accepted but ignored — this flag has no effect.
object
Optional key-value metadata dictionary. Currently accepted but not stored or returned — the endpoint discards this field, so it cannot yet be used to correlate messages with your own systems.
Response Fields
boolean
Whether the message was successfully queued.
string
An opaque, variable-length message identifier for tracking delivery and clicks.
string
Current message status. Will be
"queued" on successful submission.Examples
curl -X POST https://api.tracklysms.com/api/v2/send-raw \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": true,
"skip_rate_limit": true
}'
import requests
response = requests.post(
"https://api.tracklysms.com/api/v2/send-raw",
headers={
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"to": "+14155551234",
"list_number": "+18005551000",
"body": "URGENT: Your verification code is 482901. Ref: {{messageId}}",
"skip_duplicate_check": True,
"skip_rate_limit": True,
},
)
data = response.json()
print(data["message_id"])
const response = await fetch("https://api.tracklysms.com/api/v2/send-raw", {
method: "POST",
headers: {
"X-Api-Key": "trk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+14155551234",
list_number: "+18005551000",
body: "URGENT: Your verification code is 482901. Ref: {{messageId}}",
skip_duplicate_check: true,
skip_rate_limit: true,
}),
});
const data = await response.json();
console.log(data.message_id);
{
"success": true,
"message_id": "x7y8z9w0",
"status": "queued"
}
{
"error": "Invalid recipient phone number format",
"code": "invalid_phone"
}
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | missing_to | The to field is required but was not provided. |
| 400 | missing_list_number | The list_number field is required but was not provided. |
| 400 | missing_body | The body field is required but was not provided. |
| 400 | invalid_phone | The to field is not a valid E.164 phone number. |
| 400 | invalid_list_number | The list_number field is not a valid E.164 phone number. |
| 400 | list_not_found | The sending list was not found or does not belong to your account. |
| 400 | webhook_not_configured | Webhook verification required before sending (BYOC lists). |
| 400 | pending_confirmation | The recipient has not confirmed their double opt-in yet, so they cannot be messaged. |
| 400 | doi_expired | The recipient never confirmed their double opt-in and the confirmation window has expired. |
| 400 | warmup_limit | The recipient is not yet eligible to be messaged under the list’s warm-up schedule. |
| 403 | list_not_allowed_for_key | The API key’s send_policy.list_numbers does not include this list_number. Applies to sandbox keys too. |
| 429 | daily_cap_exceeded | The API key’s daily_send_cap is reached for today (UTC). Sandbox sends do not count. |
| 503 | send_cap_unavailable | The daily quota check or reservation could not be confirmed; the send was refused. An uncertain reservation may still count toward today’s cap. Retry with backoff. |
| 502 | kafka_producer_failure | Publication was not confirmed; delivery may still occur and daily quota remains charged. The body includes errorCode: "KAFKA_PRODUCER_FAILURE". Reconcile the message ID when available before considering another send. |
401 invalid_credentials, 403 account_suspended, or 429 rate_limited — see Error Codes.
Next Steps
Campaign Execution
How messages flow from queue to delivery
Create Contact
Add contacts before sending