Send SMS to Contact Group
Send an SMS to all contacts in a saved contact group
Endpoint
POST /api/sms/messages/contactsRequest body
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Non-empty message content. Longer messages are billed as multiple SMS parts |
sender | string | Yes | Sender ID (max 11 alphanumeric chars) |
payment_type | string | Yes | wallet or subscription |
contact_group_id | string (UUID) | Yes | ID of a contact group linked to this project |
Unlike the other send endpoints, this one does not accept expires_after. Group sends always use the 24-hour default, and the field is ignored if you pass it. See Message validity.
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer YOUR_API_TOKEN |
Content-Type | Yes | application/json |
Accept | Yes | application/json |
Idempotency-Key | No | Replaying the same key with the same body returns the original result instead of sending again |
Example
curl -X POST https://sms.lamah.com/api/sms/messages/contacts \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"message": "Your monthly statement is ready.",
"sender": "MyBank",
"payment_type": "wallet",
"contact_group_id": "0198faa2-8ddd-72c7-afce-32d980bd60fe"
}'Response
{
"message_id": "b9e8a1f2-4c60-4b0b-9f51-0c4f2f6c9e7a",
"cost": 27,
"details": {
"sent": 27,
"total": 30,
"skipped_unavailable": 0
}
}| Field | Description |
|---|---|
message_id | UUID of the created message batch — use it with Get Message |
cost | Total SMS parts charged: parts per message × accepted recipients (details.sent) |
details.sent | Contacts accepted for sending, after removing duplicate numbers and contacts whose network the sender ID is not registered on |
details.total | Total contacts in the group |
details.skipped_unavailable | Contacts dropped because their network operator is temporarily unreachable — a subset of the gap between sent and total |
cost is billed against details.sent, not details.total. Contacts on a network your sender ID is not registered on are dropped and never charged, so details.sent is often lower than details.total.
A non-zero skipped_unavailable is retryable, unlike the rest of the gap. Those contacts were valid and reachable by your sender ID; the operator was simply down at the time. Re-send to the group once it is back — with a new Idempotency-Key, since the original key is bound to the batch that already went out.
A 200 means the batch was accepted and your balance reserved, not that the messages have reached the network. Poll Get Message for per-recipient delivery status.
Error responses
422 Unprocessable Entity — Validation failed
{
"message": "The contact group id field must be a valid UUID.",
"errors": {
"contact_group_id": ["The contact group id field must be a valid UUID."]
}
}403 Forbidden — Company not verified
Contact-group sending is unavailable until your company is verified.
{ "message": "You can not use this feature until verify your company" }400 Bad Request — Group not found
The group does not exist or is not linked to this project.
{ "message": "Contact group not found" }404 Not Found — Sender not found
{ "message": "Sender not found" }400 Bad Request — Incompatible sender/receivers
Returned when no contact in the group belongs to a network the sender ID is registered on, and none were dropped for operator unavailability.
{ "message": "The sender and receivers are not compatible." }401 Unauthorized
{ "message": "Invalid or missing token." }400 Bad Request — Insufficient balance
{ "message": "Insufficient balance" }409 Conflict — Idempotency key reused
{ "message": "Idempotency key is already in use" }503 Service Unavailable — Every contact unreachable
Returned when the group is left with nothing to send and at least one contact was dropped because its network operator is temporarily unreachable. Nothing is charged. Retry once the operator is back.
{ "message": "The provider for these receivers is temporarily unavailable" }A group that still has at least one reachable contact returns 200 instead, with the dropped ones counted in details.skipped_unavailable.
503 Service Unavailable — Ingest unavailable
{ "message": "SMS ingest unavailable" }Getting a contact group ID
Find group IDs from the dashboard under Contacts → Groups, or via the List Project Contacts endpoint.