Send your first message

Check what a text will cost, send it, schedule it, and see who got it. You need a key first: see the Quickstart.

Pick an audience

Every API send is a broadcast to one audience. You can't text a single person through the API.

Urgent alerts aren't available through the API. Send those from the dashboard.

Check the cost first

POST /api/v1/messages/estimate takes the same body as a send and runs the same checks, but sends nothing, and it doesn't count toward the send limit. segments_per_recipient includes your team prefix and the opt-out line. So estimated_credits is an upper bound for your roster as it is now: the real send can use a little less, but more only if people join before you send.

curl -X POST https://rallytext.app/api/v1/messages/estimate \
  -H "Authorization: Bearer rt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"text": "Game moved to Field 3, 10am.", "audience": "families"}'

Send it

curl -X POST https://rallytext.app/api/v1/messages \
  -H "Authorization: Bearer rt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"text": "Practice moved to 5pm today.", "audience": "all"}'

You can also send a saved template with "template_id" instead of "text". The API refuses urgent alert templates (urgent_not_allowed). Merge tags such as {first_name} only work from the dashboard: a send that contains them, typed or from a template, returns 400 merge_tags_unsupported. If your team requires approval, the send comes back pending_approval and waits in the dashboard's Approvals queue.

Schedule it, or repeat it every week

scheduled_for needs a timezone offset and can be from 1 minute to 1 year ahead. repeat sends the same text every week until the date you give (a date in your team's time zone, up to a year ahead). Each week is checked like a new send when it goes out, including your team's approval rules. If a week is refused, for example because the key was revoked, the series stops. A week that waits for approval counts as sent, so the next week is scheduled even if that approval is rejected. List scheduled texts with GET /api/v1/scheduled, and cancel one with DELETE /api/v1/scheduled/{scheduled_id}, which also ends its series.

curl -X POST https://rallytext.app/api/v1/messages \
  -H "Authorization: Bearer rt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"text": "Practice tonight 6-7:30 at Lincoln Field.", "audience": "all",
       "scheduled_for": "2027-03-02T15:00:00-05:00",
       "repeat": {"every": "week", "until": "2027-05-25"}}'

See who got it

Use the message id from a queued send. Numbers in the delivery report are masked, with the matching member ids so you can join them to your own records.

curl https://rallytext.app/api/v1/messages/MESSAGE_ID \
  -H "Authorization: Bearer rt_live_your_key_here"

curl "https://rallytext.app/api/v1/messages/MESSAGE_ID/deliveries?limit=200" \
  -H "Authorization: Bearer rt_live_your_key_here"