Skip to main content

MMS

Send multimedia messages (images, GIFs, vCards, PDFs, and other attachments) to NANP (US/Canada) destinations. Orbit exposes two MMS surfaces:
  1. Single MMSPOST /api/v1/messages/sms with media_url / media_urls. The SMS endpoint auto-upgrades the send to MMS as soon as one or more attachments are present.
  2. Group MMSPOST /api/v1/messages/group fans a single payload (body + media) out to up to 20 recipients in one call.
Coverage: MMS is delivered to NANP (US/Canada, E.164 +1) numbers only. Non-NANP recipients are rejected per-message with MMS_NANP_ONLY. For non-NANP destinations send picture content as a WhatsApp or RCS message instead.

Single MMS

There is no dedicated single-MMS endpoint — send through the SMS endpoint and attach media. When media_url or a non-empty media_urls array is present, the message is automatically upgraded from SMS to MMS by the Telnyx MMS provider.
curl -X POST https://api.orbit.devotel.io/api/v1/messages/sms \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "from": "+18005551234",
    "body": "Check out our new store!",
    "media_urls": [
      "https://storage.googleapis.com/your-bucket/flyer.jpg",
      "https://storage.googleapis.com/your-bucket/map.png"
    ]
  }'

Media fields

FieldTypeNotes
media_urlstringA single attachment URL.
media_urlsstring[]Up to 10 attachment URLs. Both fields may be combined; together they upgrade the send to MMS.
  • Body is optional when at least one attachment is present — an MMS may be media-only.
  • Each URL must be HTTPS and resolve through the send-time SSRF allowlist (e.g. storage.googleapis.com). URLs that fail the allowlist or DNS-rebind check are rejected before dispatch.
  • Up to 10 attachments per message are forwarded to the provider.

Response

{
  "data": {
    "id": "msg_mms_abc123",
    "status": "queued",
    "channel": "mms",
    "segments": 1
  },
  "meta": {
    "request_id": "req_xyz789",
    "timestamp": "2026-06-08T00:00:00Z"
  }
}

Group MMS

POST /api/v1/messages/group delivers a single MMS payload to up to 20 recipients in one operation (Twilio Notify / Bandwidth group-MMS parity). Each recipient is pre-inserted as a pending row before the per-recipient send pipeline runs, so a pre-send rejection (NANP gate, validation, fraud, quota, sender-validation, media SSRF, compliance) flips that recipient’s row to failed rather than dropping it silently.
curl -X POST https://api.orbit.devotel.io/api/v1/messages/group \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+18005551234",
    "to": ["+14155552671", "+14155552672", "+16505553000"],
    "body": "Weekend sale — 20% off everything!",
    "media_urls": ["https://storage.googleapis.com/your-bucket/sale.jpg"]
  }'

Request body

FieldTypeRequiredNotes
tostring[]yes1–20 E.164 recipients. Duplicates in the same request are rejected.
fromstringnoMMS-capable sender DID. Resolved through the standard sender chain when omitted.
bodystringconditional1–1600 chars. At least one of body or media_urls must be present.
media_urlsstring[]conditionalUp to 10 HTTPS attachment URLs (SSRF-allowlisted at send time).
scheduled_atstring (ISO 8601)noBatch-level scheduling — every recipient lands as scheduled and the worker queue picks them up.
webhook_urlstringnoOne-off DLR webhook URL for this group send.
metadataobject (string→string)noShared metadata merged onto every recipient row.
Cap: 20 recipients per call. The per-leg idempotency key is group-mms:{group_id}:{to}. For larger sends use the batch endpoint or the campaigns module.

Response — 207 Multi-Status

The group endpoint always returns a per-recipient messages array and a summary. The HTTP status is:
  • 200 OK — every recipient succeeded.
  • 207 Multi-Status — any recipient failed (partial or total failure). Inspect the body for per-recipient status / error_code.
  • 402 Payment Required — the org balance cannot cover the group floor (pre-flight check).
  • 500 — bulk pre-insert failure (no recipients dispatched).
{
  "group_id": "batch_grp_abc123",
  "messages": [
    { "message_id": "msg_mms_001", "to": "+14155552671", "status": "sent" },
    { "message_id": "msg_mms_002", "to": "+14155552672", "status": "sent" },
    {
      "message_id": "msg_mms_003",
      "to": "+16505553000",
      "status": "failed",
      "error_code": "MMS_NANP_ONLY",
      "error_message": "MMS is only available for NANP (US/Canada) recipients"
    }
  ],
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1,
    "scheduled": 0
  }
}

Message Status Flow

queuedsendingsentdelivered (or failed / undelivered) Subscribe to status updates via webhooks using the message.sent, message.delivered, and message.failed events. For group MMS, one event fires per recipient, each carrying its own message id.

Rate Limits

SurfaceLimit
Group MMS (POST /messages/group)30 requests / minute per tenant
Single MMS (POST /messages/sms)Same per-plan throughput as SMS

Outbound provider

Outbound MMS is delivered via Telnyx, the named exception to Orbit’s outbound-termination policy: voice and SMS exit only via the Devotel softswitch, but MMS (alongside fax/T.38) outbound may use Telnyx because the softswitch does not support MT MMS. Orbit routes all MMS — single and group — through the standard messaging router; there is no provider bypass.

Pricing

MMS is billed per message (not per attachment) and varies by destination. Check the pricing page or query the GET /api/v1/pricing/messaging?country=<ISO> endpoint for real-time rates (the returned channels array includes mms).