> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# MMS send & receive

> Send single and group MMS with images, GIFs, and video from the dashboard or the API, and track per-recipient delivery reports on the MMS channel.

# MMS send & receive

MMS carries rich media — images, GIFs, and short video — on the same SMS rails and sender identity you already use for text. This guide covers when to pick MMS over SMS or WhatsApp, how to attach media, how to compose a single send or a multi-recipient group send, and how to read per-recipient delivery reports.

**You will:**

1. [Decide MMS vs SMS vs WhatsApp](#1-decide-mms-vs-sms-vs-whatsapp)
2. [Attach media](#2-attach-media)
3. [Send a single MMS](#3-send-a-single-mms)
4. [Send a group MMS](#4-send-a-group-mms)
5. [Read delivery reports](#5-read-delivery-reports)
6. [Understand provider behavior and cost](#6-provider-behavior-and-cost)

## 1. Decide MMS vs SMS vs WhatsApp

MMS is the right surface when the message needs inline media on US/Canada (NANP, `+1`) numbers — and the wrong surface anywhere else. Decide before you build:

* **Inline image, GIF, or short video to a US/Canada number** — use MMS. Attachments render directly in the recipient's messaging app; no link tap required.
* **Text-only copy** — use [plain SMS](/channels/sms). If no attachment is present, SMS is the cheaper surface; MMS only buys you the media fields.
* **Non-NANP recipients** — MMS stops at `+1` destinations. A recipient that rejects with `MMS_NANP_ONLY` is telling you to switch to [WhatsApp](/channels/whatsapp) or [RCS](/channels/rcs), not to retry MMS.
* **Documents and contact cards** — MMS rejects PDFs and vCards at send time. Host the file over HTTPS and put the link in the message body instead.

<Note>
  MMS uses your SMS sender identity and Messaging Profile. If SMS is not connected yet, connect it in **Settings → Channels** first — the MMS workspace activates on the same sender.
</Note>

## 2. Attach media

Attach media by pasting an HTTPS URL, or by uploading a file in the dashboard composer (uploads land on Orbit-hosted HTTPS storage, which then flows through the same URL path). Two constraints are enforced before dispatch:

**Accepted content types**

| Category | Accepted types                                       |
| -------- | ---------------------------------------------------- |
| Image    | `image/jpeg`, `image/png`, `image/gif`, `image/webp` |
| Video    | `video/mp4`, `video/3gpp`                            |
| Audio    | `audio/mpeg`, `audio/ogg`, `audio/aac`               |

**Size limit**

Each attachment is capped at **5 MB**; anything larger is rejected before dispatch. For reliable carrier delivery keep each attachment under **1 MB** — larger media is frequently down-rendered or dropped by individual carrier gateways even under the 5 MB ceiling.

Media URLs must be HTTPS and pass the send-time URL allowlist; URLs that fail validation are rejected before the send rather than silently dropped. Up to **10 attachments** ride on one message, and the body is optional when at least one attachment is present.

## 3. Send a single MMS

### From the dashboard

1. Open **Messages → MMS** (members with the owner, admin, or developer workspace role).
2. Click **Compose** to open the MMS composer.
3. Add **one recipient** (`+1` E.164 number), an optional body, and your media — upload the file or paste its HTTPS URL.
4. Send. The composer shows the per-recipient result immediately, and the message appears in the MMS workspace history.

The same composer handles one recipient or twenty — a group send is just more recipients on the same surface.

### From the API

Send through the standard SMS endpoint with a media field — the send auto-upgrades to MMS as soon as an attachment is present:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/sms \
  -H "X-API-Key: dv_live_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-flyer-98421" \
  -d '{
    "to": "+14155552671",
    "from": "+18005551234",
    "body": "Check out our new store!",
    "media_urls": ["https://storage.googleapis.com/your-bucket/flyer.jpg"]
  }'
```

The response confirms the upgrade with `"channel": "mms"`:

```json theme={null}
{
  "data": {
    "id": "msg_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "status": "queued",
    "channel": "mms"
  },
  "meta": {
    "request_id": "req_xyz789",
    "timestamp": "2026-09-03T00:00:00Z"
  }
}
```

## 4. Send a group MMS

Group MMS fans one payload (body + media) out to up to **20 recipients** in a single operation, with per-recipient status in the response.

### From the dashboard

1. Open **Messages → MMS** and click **Compose**.
2. Add up to **20 recipients** — paste a comma- or newline-separated list and the composer splits it into chips; non-`+1` numbers and duplicates are flagged before send.
3. Add the body and media as for a single send.
4. Send, then read the per-recipient result panel: each recipient shows as sent or failed with its reason (for example `MMS_NANP_ONLY` for a non-US/Canada number).

The recipient cap is 20 per send. For larger broadcasts use the [batch SMS endpoint](/guides/messages-batch-sms) (with media upgrade) or the campaigns module.

### From the API

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/group \
  -H "X-API-Key: dv_live_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+18005551234",
    "to": ["+14155552671", "+14155552672"],
    "body": "Weekend sale — 20% off everything!",
    "media_urls": ["https://storage.googleapis.com/your-bucket/sale.jpg"]
  }'
```

The endpoint returns a per-recipient breakdown — `200 OK` when every recipient succeeded, `207 Multi-Status` on partial failure:

```json theme={null}
{
  "group_id": "batch_grp_abc123",
  "messages": [
    { "message_id": "msg_0f1e2d3c4b5a69788796a5b4c3d2e1f0", "to": "+14155552671", "status": "sent" }
  ],
  "summary": { "total": 2, "succeeded": 2, "failed": 0, "scheduled": 0 }
}
```

Every recipient is recorded before dispatch, so a pre-send rejection (validation, compliance, media check) lands as a visible `failed` row rather than a silent drop.

## 5. Read delivery reports

Each MMS moves through the standard lifecycle — `queued → sending → sent → delivered` (or `failed` / `undelivered`) — and you have three ways to follow it:

**MMS workspace.** **Messages → MMS** lists history, delivery status, and analytics filtered to the MMS channel in one place; search by recipient or message body, and export the list.

**Delivery log.** Open **Messages → Tools → Delivery log** and set the Channel filter to MMS — or share a pre-filtered link:

```text theme={null}
/en/messages/delivery-log?channel=mms
```

**API.** Query with the `channel=mms` filter, or subscribe to `message.sent` / `message.delivered` / `message.failed` [webhooks](/webhooks/overview). For group sends one event fires per recipient, so a 20-recipient send produces 20 delivery traces — diagnose each one individually.

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/messages?channel=mms&direction=outbound" \
  -H "X-API-Key: dv_live_sk_YOUR_KEY"
```

## 6. Provider behavior and cost

Outbound MMS is delivered through **Telnyx** — MMS and fax are the named exceptions to Orbit's outbound policy, which otherwise terminates voice and SMS on the Devotel softswitch. All MMS traffic routes through the standard messaging router; there is no provider bypass to wire up. Inbound MMS replies arrive over the reverse path and surface as inbound messages on your sender numbers, the same as SMS.

On cost: MMS is billed **per message, not per attachment** — a message with three attachments costs the same as one with one. In a group send, each recipient is billed as an individual message, and the composer shows a cost estimate before you confirm. Rates vary by destination; check the [pricing page](https://orbit.devotel.io/pricing) or the pricing endpoint for current rates.

## Common errors

| Code                   | HTTP | Meaning                               | Fix                                       |
| ---------------------- | ---- | ------------------------------------- | ----------------------------------------- |
| `MMS_NANP_ONLY`        | 422  | Recipient is not a NANP (`+1`) number | Route to WhatsApp or RCS                  |
| `VALIDATION_ERROR`     | 422  | Media type, size, or URL check failed | Read `details.issues`; fix the attachment |
| `INSUFFICIENT_BALANCE` | 402  | Wallet below the group floor          | Top up before the send                    |
| `RATE_LIMITED`         | 429  | Group sends exceed 30 req/min         | Space the calls; use batch for volume     |

## Next steps

* [MMS channel reference](/channels/mms) — every request field, cap, and response shape
* [Delivery log](/guides/delivery-log) — cross-channel search and shareable filtered links
* [Batch SMS](/guides/messages-batch-sms) — same media upgrade at higher volume
* [Send & receive messages](/guides/send-receive-messages) — the three-step send → track → receive pattern across channels
