API reference

Messages

Messages go out from a messaging line, a dedicated number separate from your calling numbers. One request sends iMessage, SMS, MMS or WhatsApp. Before a message is sent we check your do-not-call list, opt-outs and quiet hours. Replies arrive as message.received.

Guide: Messaging.

Endpoints

POST/v1/messagesSend a message
GET/v1/messages/{id}Retrieve a message
GET/v1/messagesList messages
GET/v1/messaging_linesList messaging lines
GET/v1/messaging_lines/{id}Retrieve a messaging line
GET/v1/opt_outsList opt-outs

The message object

FieldTypeDescription
id string Unique ID, starts with msg_.
direction string outbound or inbound.
channel string The channel used: imessage, sms, mms or whatsapp.
messaging_line_id string The messaging line that sent or received the message.
from string Sender, E.164.
to string Recipient, E.164.
body string The text, up to 1,600 characters.
media_urls string[] Attached images or files.
lead_id string | null The lead the message is linked to.
last_call_id string | null The lead's last call.
status string queued, sent, delivered or failed for outbound. received for inbound.
send_at string | null When a queued message goes out, after quiet hours end for the recipient.
error object | null code and message when status is failed. code is unreachable, opted_out or template_required.
created_at string When the message was accepted or received, ISO 8601.
delivered_at string | null When delivery was confirmed.

Send a message

Sends a message from one of your messaging lines. Outside 8 am to 9 pm in the recipient's local time the message is queued until the window opens. A message to a number on your do-not-call list or opt-out list returns 422 with the rule. On WhatsApp, a free-form message more than 24 hours after the recipient last wrote fails with template_required. Send template instead.

POST/v1/messages

Body parametersTypeDescription
torequired string The recipient, E.164.
fromrequired string Your messaging line number.
channel string auto, imessage, sms, mms or whatsapp. auto sends iMessage when the recipient has it, and SMS or MMS otherwise. Default auto.
body string Up to 1,600 characters. Send body, media_urls or both.
media_urls string[] Public HTTPS links to images or files. Sent as MMS on the SMS path. MMS takes up to 5 MB and 10 files per message. iMessage takes up to 16 MB per file. WhatsApp takes 1 file up to 16 MB.
lead_id string Links the message to the lead and their last call.
template object WhatsApp only. An approved template with name, language and variables. Needed when the recipient has not written to you in the last 24 hours.
metadata object Up to 20 keys. Returned on every event for the message.
POST/v1/messages
curl https://api.liveleg.dev/v1/messages \
  -H "Authorization: Bearer $LIVELEG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+15125550147",
    "from": "+15125550188",
    "channel": "auto",
    "body": "Thanks for the time today, Dana. Here is the inspection checklist we talked about.",
    "lead_id": "led_44Hc2"
  }'
Response
{
  "id": "msg_Rq40",
  "object": "message",
  "direction": "outbound",
  "channel": "imessage",
  "messaging_line_id": "mln_8Rd2",
  "from": "+15125550188",
  "to": "+15125550147",
  "body": "Thanks for the time today, Dana. Here is the inspection checklist we talked about.",
  "media_urls": [],
  "lead_id": "led_44Hc2",
  "last_call_id": "cal_8Jq2mT4x",
  "status": "sent",
  "send_at": null,
  "error": null,
  "created_at": "2026-11-03T15:50:12Z",
  "delivered_at": null
}

Retrieve a message

Returns one message with its current status.

GET/v1/messages/{id}

GET/v1/messages/{id}
curl https://api.liveleg.dev/v1/messages/msg_Rq40 \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "id": "msg_Rq40",
  "object": "message",
  "direction": "outbound",
  "channel": "imessage",
  "messaging_line_id": "mln_8Rd2",
  "from": "+15125550188",
  "to": "+15125550147",
  "body": "Thanks for the time today, Dana. Here is the inspection checklist we talked about.",
  "media_urls": [],
  "lead_id": "led_44Hc2",
  "last_call_id": "cal_8Jq2mT4x",
  "status": "delivered",
  "send_at": null,
  "error": null,
  "created_at": "2026-11-03T15:50:12Z",
  "delivered_at": "2026-11-03T15:50:13Z"
}

List messages

Returns sent and received messages, newest first.

GET/v1/messages

Query parametersTypeDescription
lead_id string Only messages with this lead.
messaging_line_id string Only messages on this line.
phone_number string Only messages to or from this number.
direction string outbound or inbound.
channel string imessage, sms, mms or whatsapp.
status string queued, sent, delivered, failed or received.
limit integer 1 to 100. Default 20.
starting_after string The last ID from the previous page.
GET/v1/messages
curl "https://api.liveleg.dev/v1/messages?lead_id=led_44Hc2&limit=20" \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "msg_Rr51",
      "object": "message",
      "direction": "inbound",
      "channel": "imessage",
      "messaging_line_id": "mln_8Rd2",
      "from": "+15125550147",
      "to": "+15125550188",
      "body": "Got it. Can we talk Thursday?",
      "media_urls": [],
      "lead_id": "led_44Hc2",
      "last_call_id": "cal_8Jq2mT4x",
      "status": "received",
      "send_at": null,
      "error": null,
      "created_at": "2026-11-03T16:03:51Z",
      "delivered_at": null
    },
    {
      "id": "msg_Rq40",
      "object": "message",
      "direction": "outbound",
      "channel": "imessage",
      "messaging_line_id": "mln_8Rd2",
      "from": "+15125550188",
      "to": "+15125550147",
      "body": "Thanks for the time today, Dana. Here is the inspection checklist we talked about.",
      "media_urls": [],
      "lead_id": "led_44Hc2",
      "last_call_id": "cal_8Jq2mT4x",
      "status": "delivered",
      "send_at": null,
      "error": null,
      "created_at": "2026-11-03T15:50:12Z",
      "delivered_at": "2026-11-03T15:50:13Z"
    }
  ],
  "has_more": false
}

List messaging lines

Returns the messaging lines on the account. We set up each line and register it for SMS in your business name. For a subaccount, that is the client's business name.

GET/v1/messaging_lines

Query parametersTypeDescription
limit integer 1 to 100. Default 20.
starting_after string The last ID from the previous page.
GET/v1/messaging_lines
curl https://api.liveleg.dev/v1/messaging_lines \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "mln_8Rd2",
      "object": "messaging_line",
      "phone_number": "+15125550188",
      "name": "Ridgeline sales",
      "channels": {
        "imessage": "active",
        "sms": "active",
        "mms": "active",
        "whatsapp": "active"
      },
      "sms_registration": {
        "status": "approved",
        "business_name": "Ridgeline Roofing LLC"
      },
      "whatsapp": {
        "status": "connected",
        "business_name": "Ridgeline Roofing"
      },
      "label_status": "clean",
      "created_at": "2026-10-28T17:03:19Z"
    }
  ],
  "has_more": false
}

Retrieve a messaging line

Returns one line with the status of each channel. sms_registration shows the business name the line is registered under. WhatsApp uses the client's own WhatsApp Business account, connected during setup, and whatsapp shows its status. label_status comes from number reputation, which is included on every line.

GET/v1/messaging_lines/{id}

GET/v1/messaging_lines/{id}
curl https://api.liveleg.dev/v1/messaging_lines/mln_8Rd2 \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "id": "mln_8Rd2",
  "object": "messaging_line",
  "phone_number": "+15125550188",
  "name": "Ridgeline sales",
  "channels": {
    "imessage": "active",
    "sms": "active",
    "mms": "active",
    "whatsapp": "active"
  },
  "sms_registration": {
    "status": "approved",
    "business_name": "Ridgeline Roofing LLC"
  },
  "whatsapp": {
    "status": "connected",
    "business_name": "Ridgeline Roofing"
  },
  "label_status": "clean",
  "created_at": "2026-10-28T17:03:19Z"
}

List opt-outs

Returns numbers that opted out of messages with STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT, REVOKE or OPT OUT. Each opt-out also adds the number to your do-not-call list. A number that texts START or UNSTOP opts back in to messages and leaves this list. The do-not-call entry for calls stays in place.

GET/v1/opt_outs

Query parametersTypeDescription
phone_number string Check one number, E.164.
messaging_line_id string Only opt-outs received on this line.
created_after string ISO 8601.
limit integer 1 to 100. Default 20.
starting_after string The last ID from the previous page.
GET/v1/opt_outs
curl "https://api.liveleg.dev/v1/opt_outs?created_after=2026-11-01T00%3A00%3A00Z&limit=20" \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "opt_7Ln52Hs",
      "object": "opt_out",
      "phone_number": "+15125550163",
      "word": "STOP",
      "channel": "sms",
      "messaging_line_id": "mln_8Rd2",
      "message_id": "msg_Rt77",
      "created_at": "2026-11-03T18:40:02Z"
    }
  ],
  "has_more": false
}