> ## 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.

# SMS CSV export column reference

> Read the SMS message export column by column — what each destination and lifecycle header means, why Submitted At and Created At share one timestamp, and how blank Country/Network/MCC cells behave.

# SMS CSV export column reference

The Messages → SMS page downloads a CSV from the **Export** menu in two scopes. Both scopes emit the same column set in the same order, so the file you open is stable across exports. This reference explains every column, with special attention to the destination and lifecycle headers (Currency, Submitted At, Sent At, Delivered At, Country, Network, MCC, MNC) added to the export.

## Export scopes: this page vs all results

| Scope | What it contains | Source |
| - | - | - |
| **Export this page** | The rows currently loaded in the table — one page (25 rows) | Serializes the list you already see. Fast, but only what's on screen. |
| **Export all results** | Every row matching the server's channel/status/date filters, up to 10,000 rows | Posts the active filters to `POST /messages/export` and downloads the full result set. If the returned count hits the 10,000 cap, the dashboard warns the export was truncated. |

"Export all results" filters on channel, status, and a created-date window only. Direction and free-text search refinements you applied in the list are not sent to the server — the full-set file can be broader than the on-screen list.

Both scopes produce the same columns in the same order. The difference is row count, not schema.

## Column-by-column reference

The first six columns are the shared message baseline every channel exports:

| Column | Source | Notes |
| - | - | - |
| Direction | `direction` | `outbound` / `inbound`. |
| From | `from` | Sender address. Exported as text so leading `+` survives Excel. |
| To | `to` | Recipient, E.164. Exported as text. |
| Body | `body` | Message text. |
| Status | `status` | Lifecycle status (`queued`, `sent`, `delivered`, `failed`, …). |
| Created At | `created_at` | Platform accept-stamp; see "Submitted At vs Created At" below. |

The SMS page then appends eleven SMS-specific columns:

| Column | Source | Notes |
| - | - | - |
| Segments | `segments` | Charged segment count for the body. |
| External ID | `external_id` | Your idempotency/external reference, if you set one. |
| Price | resolved | The billed price. A stored positive `price` wins verbatim; if the price column never persisted, the exact wallet debit stamped on the row's metadata (`charge_amount_cents` or `mccmnc_price`) is read instead; a send that failed before transmission exports `0` by design; otherwise a segment-based estimate fills in. The column always agrees with the dashboard's Cost cell. |
| Currency | `currency` on the message row | The ISO currency code, exported verbatim — it annotates Price and is never re-derived or converted. |
| Submitted At | `created_at`, re-emitted under its own header | The same timestamp as Created At, deliberately exported as a distinct column. Design: Created At is the baseline shared across all channels; Submitted At names the lifecycle stage SMS operators actually filter on. Both render one value. |
| Sent At | `sent_at` | The wire-dispatch time — when the softswitch handed the message to the downstream carrier. Distinct from Created At by the queue→send latency. Blank for rows never dispatched. |
| Delivered At | `delivered_at` | The carrier DLR (delivery receipt) timestamp. Blank until a final DLR arrives. |
| Country | `metadata.dest_country` | The destination country the send pipeline resolved from the recipient's E.164 at send time. Exported verbatim, never re-derived from a prefix lookup. |
| Network | `metadata.mccmnc_operator` | The operator name resolved at send time from the HLR result or the MCCMNC directory. Never the internal routing supplier. |
| MCC | first 3 digits of the row's `mccmnc` | Mobile Country Code. Exported as text so leading zeros survive spreadsheet round-trips. |
| MNC | remainder of the row's `mccmnc` (2–3 digits) | Mobile Network Code. Also exported as text. |

All five timestamp columns (Created At, Submitted At, Sent At, Delivered At, plus scheduled/read/etc. on other channels) are formatted in your dashboard timezone and locale to the second, so the CSV agrees with the on-screen wall clock.

## Submitted At vs Created At — one timestamp, two headers

The baseline column set every channel exports includes `Created At`. The SMS export then adds a synthetic `Submitted At` column that re-emits `created_at` under its own header. This is deliberate: operators reconciling SMS against carrier submission logs ask for "submitted at", not "created at", and having a dedicated header keeps both vocabularies present without splitting the value. The two cells always carry the same timestamp.

## Blank rows and cells — no fallback, no guessing

The export honours a strict blank-cell contract:

* **Country / Network / MCC / MNC blank** — the send pipeline never recorded a destination stamp on that row. The exporter surfaces the recorded `metadata.dest_country` / `metadata.mccmnc_operator` only; it will not substitute a prefix guess, an HLR re-lookup, or the internal routing supplier. An inbound row follows the same symmetric stamping rule.
* **Delivered At blank** — no final DLR has arrived yet.
* **Sent At blank** — the row was never dispatched (e.g. still queued, or failed pre-transmission).
* **Price = 0** — the send was never billed (a pre-transmission failure, or a BYO-carrier/absorbed-channel leg billed \$0 by design). A positive price always reflects the billed amount.

Treat blank as "not recorded", not "zero".

## Worked example

Export all results for outbound SMS in a date window; open the file and check one row end to end. A delivered send to a UK recipient:

```csv theme={null}
Direction,From,To,Body,Status,Created At,Segments,External ID,Price,Currency,Submitted At,Sent At,Delivered At,Country,Network,MCC,MNC
outbound,+14155550123,+447700900123,"Your code is 481 516",delivered,2026-09-29 14:02:11,1,ord_9f3ab,0.0075,USD,2026-09-29 14:02:11,2026-09-29 14:02:13,2026-09-29 14:02:19,GB,Vodafone UK,234,15
```

Reading it right to left:

1. **MCC `234`, MNC `15`** — the UK + Vodafone pair the send resolved; exported as text so the leading values stay intact in Excel.
2. **Network `Vodafone UK`** — the operator resolved at send time from the HLR/directory, not a supplier name.
3. **Country `GB`** — the destination country stamped when the send was accepted.
4. **Delivered At** 6 seconds after Sent At — the carrier DLR round trip.
5. **Sent At vs Submitted At** — 2-second queue→dispatch latency between accept-stamp and wire-handoff; Submitted At equals Created At by design.
6. **Currency `USD`** — the code attached to Price `0.0075`, verbatim from the message row.

For an undelivered send (no DLR yet), the same row exports with `Delivered At` blank and often blank `Country`/`Network`/`MCC`/`MNC` if the pipeline never recorded destination resolution; nothing is inferred.

## Troubleshooting

* **Delivered At is blank but you saw "Delivered" in the dashboard.** The status chip reflects the latest lifecycle state; the exported `delivered_at` cell carries only the recorded DLR timestamp. If a status advanced via a path that doesn't persist a delivered timestamp, the cell stays blank — trust Status for the verdict and Delivered At for the receipt time.
* **Country / Network / MCC are blank on some rows.** Expected when the send-time destination resolution never recorded a stamp — the export deliberately does not re-derive country from the phone prefix or re-run HLR at export time. Filter the list by status `submitted_no_receipt` or check the message detail drawer for what was recorded.
* **Price reads 0 for a row you expect to cost.** Only rows that failed before transmission, or legitimate \$0-billed legs (BYO-carrier, absorbed-channel), export 0. If a delivered row shows 0, check the message detail drawer's metadata charge — a mismatch there is a billing-path problem, not an export problem.
* **Excel mangles MCC/MNC.** They are exported as text literals precisely so leading zeros survive; if a spreadsheet still reformats them, re-import the CSV marking those two columns as Text rather than General.
* **"Export all results" returned fewer rows than the list suggested.** The full-set export caps at 10,000 rows and filters on channel/status/date only — direction and free-text search are not applied server-side. Narrow the date window and re-export.

## Related

* [Search message history](/guides/search-message-history) — find the rows before you export them
* [Delivery receipts (DLR)](/concepts/dlr-and-mo-pipeline) — the pipeline that fills Delivered At
* [MCCMNC billing overrides](/guides/billing-mccmnc-overrides) — how per-country/per-network rate overrides interact with the Country/Network/MCC/MNC values you export
* [SMS segments and encoding](/concepts/sms-segments-and-encoding) — what the Segments column counts
* [Billing rate resolution](/concepts/pricing-rate-resolution) — how the platform picks the rate behind the exported Price

Shipped in commit `2fc5d08e5f` (destination/lifecycle columns on both export scopes).
