Transactional Messaging

Transactional messages are 1:1, event-driven messages — a single message to a single recipient, triggered by something that happens in your application. An order ships, an appointment approaches, a password reset is requested. Send with POST /v1/messages and a single phone number in toNumbers.

Transactional vs. Campaign: Both use the same /v1/messages endpoint. A single number in toNumbers is transactional. Multiple numbers or any use of groupIds makes it a campaign.

Send an SMS

Two fields are required: toNumbers and message. messageType is optional — EZ Texting auto-detects (SMS vs. MMS) based on whether media is attached. A 201 response means the message is queued for delivery.

curl --request POST \
     --url https://a.eztexting.com/v1/messages \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --user 'your_username:your_password' \
     --data '{
  "toNumbers": [
    "15551234567"
  ],
  "message": "Your appointment is confirmed for tomorrow at 2pm."
}'

Send an MMS

Set messageType to "MMS" (or let auto-detect handle it when you include media) and attach media via mediaUrl — a publicly accessible URL, up to 5 MB — or mediaFileId for a file uploaded through the Media Files API.

For high-volume or time-sensitive sends, pre-upload media via POST /v1/media-files and reference the returned mediaFileId. This avoids latency from fetching the URL at send time.

curl --request POST \
     --url https://a.eztexting.com/v1/messages \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --user 'your_username:your_password' \
     --data '{
  "toNumbers": [
    "15551234567"
  ],
  "message": "Check out our new menu!",
  "mediaUrl": "https://example.com/menu.jpg"
}'

Schedule a message

Include sendAt with an ISO 8601 timestamp to schedule future delivery. Omit it to send immediately. Save the returned message ID so you can cancel with DELETE /v1/messages if plans change.

curl --request POST \
     --url https://a.eztexting.com/v1/messages \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --user 'your_username:your_password' \
     --data '{
  "toNumbers": [
    "15551234567"
  ],
  "message": "Your appointment is in 1 hour.",
  "sendAt": "2026-01-15T14:00:00Z"
}'

Check delivery status

Retrieve a message's delivery status with GET /v1/message-details/{id}. For production systems, use webhooksinstead of polling — you'll get real-time delivery notifications pushed to your server.

curl --request GET \
     --url https://a.eztexting.com/v1/message-details/123456789 \
     --header 'accept: application/json' \
     --user 'your_username:your_password'

All message parameters

ParameterTypeDescription
messagestringThe text content of your message
toNumbersstring[]Recipient phone numbers. One number = transactional; multiple = campaign.
groupIdsstring[]Contact group IDs to send to (always a campaign). Cannot combine with toNumbers.
messageTypestringSMS or MMS. Optional — auto-detected based on whether media is attached.
sendAtstringISO 8601 timestamp for scheduled delivery. Omit to send immediately.
companyNamestringPrefix added to the beginning of your message
mediaUrlstringPublicly accessible media URL for MMS (up to 5 MB)
mediaFileIdstringID of a pre-uploaded media file
messageTemplateIdstringID of a saved message template to use
fromNumberstringNumber to send from. If omitted, sends from your default number. Only needed when you have multiple numbers.
strictValidationbooleantrue: entire send fails if any number is invalid. false (default): invalid numbers are skipped.

Message types

SMS— Standard text. Up to 160 characters (GSM-7) sends as one segment; longer messages split into multiple segments and reassemble on the recipient's device. Emoji/Unicode use UCS-2 (70 chars per segment).

MMS — Rich media messages with images, video, or audio alongside text. Attach via mediaUrl or mediaFileId.

Message templates

Templates let you define reusable messages with variable placeholders that are filled in with contact data at send time. Create a template with POST /v1/message-templates, then reference it via messageTemplateId when sending. This keeps your sending code clean and lets non-technical teams manage content separately.

Template variables

Templates support the following variables, which are replaced with the contact's stored data:

  • ${FirstName} — Contact's first name
  • ${LastName} — Contact's last name
  • ${PhoneNumber} — Contact's phone number
  • ${Email} — Contact's email address
  • ${Note} — Contact's note field
  • ${CustomField} — Any custom field you've created

If a variable has no value for a contact, it's replaced with an empty string. For example, if you send to a contact with no email on file, ${Email} becomes blank in the rendered message.

Creating and using templates

Create a template with POST /v1/message-templates, specifying name and message. The template can also include mediaFileId or mediaFileUrl for media. When sending, pass the returned template ID in the messageTemplateId field, and the variables will be expanded from the contact data.

For details on managing templates, see the Message Templates API reference.

curl --request POST \
     --url https://a.eztexting.com/v1/message-templates \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --user 'your_username:your_password' \
     --data '{
  "name": "Appointment Reminder",
  "message": "Hi ${FirstName}, your appointment is tomorrow at 2pm. Reply YES to confirm.",
  "companyName": "Acme Health"
}'

Media files

Upload media once via POST /v1/media-files and reference it in multiple messages via mediaFileId. This is especially useful for high-volume sends, time-sensitive messages, or when you want to avoid re-fetching a URL on every send.

Uploading media

Post a media file using a publicly accessible URL (mediaUrl). The file must be under 5 MB and in a supported format (JPEG, PNG, GIF, MP4, etc.). The API returns an id, name, type, url, and uploadAt timestamp.

Using media in messages

When sending an MMS, reference the media via mediaFileId instead of mediaUrl. This skips the latency of fetching the URL at send time and is the recommended approach for production systems.

Managing media files

  • GET /v1/media-files — List all uploaded files
  • GET /v1/media-files/{id} — Get details on a single file
  • DELETE /v1/media-files/{id} — Delete a file

For the full API reference, see Media Files API.

curl --request POST \
     --url https://a.eztexting.com/v1/media-files \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --user 'your_username:your_password' \
     --data '{
  "mediaUrl": "https://example.com/promo-image.jpg"
}'

Delivery reports

For detailed per-recipient reporting, use the Message Reports endpoints:

  • GET /v1/message-reports/{id} — Overall delivery summary
  • GET /v1/message-reports/{id}/responses/delivery — Per-recipient delivery statuses
  • GET /v1/message-reports/{id}/responses/engagement — Engagement metrics
  • GET /v1/message-reports/{id}/responses/link — Link click tracking

Error handling

StatusMeaningWhat to do
400Bad RequestCheck required fields (message, toNumbers). Verify phone number format.
401UnauthorizedCredentials invalid or token expired. Refresh your token.
404Not FoundThe message ID doesn't exist. Verify the ID.
422UnprocessableRequest is well-formed but can't be processed — e.g., sending to an opted-out number.
429Rate Limited200 req/min exceeded. Wait for the duration in the X-Rate-Limit-Retry-After-Milliseconds header.
500Server ErrorRetry with exponential backoff. Contact support if it persists.

Next steps