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

# Search message history

> Search the Messages Hub with the `q=` search DSL — every searchable field, operator, and per-channel provider reference, with full multi-field examples — so a receipt ref, Meta wamid, Resend email id, or jambonz CallSid resolves to the exact message.

# Search message history

The Messages Hub search box — and the `GET /api/v1/messages` list endpoint — accepts a fielded search DSL in its `q` parameter instead of a plain free-text scan, so you can look a message up by a provider-side identifier or combine constraints on channel, status, recipient, or time. Pass the same expression to the SDK or in the dashboard search box.

A DSL expression is a set of `field:value` clauses. Clauses are AND-joined by default; parentheses and `AND`/`OR`/`NOT` combine them further (precedence: `NOT` > `AND` > `OR`). A malformed `q` returns a `422 INVALID_QUERY` — check the error message for the rejected field, operator, or syntax.

## Field reference

These are the complete set of searchable fields for messages. Anything not on this list is rejected with `INVALID_QUERY_FIELD`.

| Field             | Type   | Operators                                      | Description                                                                                                                                 |
| ----------------- | ------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `message_id`      | string | `:`, `IN`, `NOT`, `field:null` / `field:!null` | Provider-side identifier (Jasmin/SMPP receipt ref, Meta `wamid`, Resend email id, jambonz `CallSid`, Telnyx fax id). `*` wildcards allowed. |
| `external_id`     | string | same operators as `message_id`                 | Legacy alias for `message_id` — same column, kept so saved and linked queries keep working.                                                 |
| `status`          | enum   | `:`, `IN`, `NOT`, `field:null` / `field:!null` | One of `queued`, `sent`, `delivered`, `read`, `failed`, `rejected`.                                                                         |
| `channel`         | enum   | `:`, `IN`, `NOT`, `field:null` / `field:!null` | One of `sms`, `whatsapp`, `email`, `rcs`, `viber`, `voice`, `fax`, `instagram`, `messenger`, `line`, `telegram`.                            |
| `direction`       | enum   | `:`, `IN`, `NOT`, `field:null` / `field:!null` | `inbound` or `outbound`.                                                                                                                    |
| `from`            | phone  | `:`, `IN`, `NOT`, wildcards                    | Sender address; a leading `+` is treated as part of the phone number, not a numeric sign.                                                   |
| `to`              | phone  | `:`, `IN`, `NOT`, wildcards                    | Recipient address.                                                                                                                          |
| `body`            | string | `:`, `NOT`, wildcards                          | Message text; matches with or without wildcards. Comparison operators (`>`, `<`) and `IN` lists are not allowed on `body`.                  |
| `created`         | date   | `:`, `>`, `>=`, `<`, `<=`, `[lo TO hi]`        | When the message row was created. Accepts `YYYY-MM-DD`; range with `[2026-08-01 TO 2026-08-24]`.                                            |
| `updated`         | date   | same operators as `created`                    | Last status change on the row.                                                                                                              |
| `conversation_id` | string | `:`, `IN`, `NOT`, wildcards                    | Thread id grouping messages into a conversation.                                                                                            |
| `contact_id`      | string | `:`, `IN`, `NOT`, wildcards                    | Contact the message is linked to.                                                                                                           |

## Operator reference

| Operator        | Syntax                                                       | Applies to                                                                                                   |
| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| Equals          | `field:value`                                                | All fields                                                                                                   |
| Wildcard        | `field:val*` (up to 8 `*` per value, max 256 chars)          | String and phone fields (`message_id`, `external_id`, `from`, `to`, `body`, `conversation_id`, `contact_id`) |
| In list         | `field:(a,b,c)`                                              | All fields                                                                                                   |
| Greater / less  | `field>value`, `field>=value`, `field<value`, `field<=value` | Date fields (`created`, `updated`)                                                                           |
| Between range   | `field:[lo TO hi]`                                           | Date fields (`created`, `updated`)                                                                           |
| Null / not-null | `field:null`, `field:!null`                                  | All fields                                                                                                   |
| Negation        | `NOT field:value`                                            | All fields                                                                                                   |

Whichever operator you use, the full expression is capped at 2,048 characters, 8 nested levels deep, and 64 clauses — generous headroom for any realistic filter.

## Look up a provider SID with `message_id:` / `external_id:`

Every outbound message carries two identifiers: the canonical Orbit id (`msg_...`, returned by the send API) and the provider-side identifier stamped when the send reaches its provider. `message_id:` and `external_id:` both match that provider-side identifier — use whichever your saved integration or report already names:

```text theme={null}
message_id:SMc1f8a9d27b
external_id:SMc1f8a9d27b
```

### Provider reference per channel

| Channel               | Where the provider ref comes from                                           |
| --------------------- | --------------------------------------------------------------------------- |
| SMS                   | The Jasmin/SMPP receipt reference returned in `submit_sm_resp`.             |
| WhatsApp              | The Meta `wamid` from a WABA dashboard or delivery receipt.                 |
| RCS                   | The provider message id returned on send (exposed in the delivery receipt). |
| Viber                 | The provider message token carried by the delivery webhook.                 |
| Email                 | The mail provider email id shown in your mail console.                      |
| Voice                 | The jambonz `CallSid` from a voice webhook or call log.                     |
| Fax                   | The Telnyx fax id carried by the webhook.                                   |
| Instagram / Messenger | The Meta message id from the page conversation or webhook.                  |
| LINE / Telegram       | The channel's message id from the bot API webhook.                          |

Because a provider dashboard shows only these refs, pasting one straight into the search is the fastest path from a carrier or Meta console back to the Orbit message.

## Full multi-field examples per channel

Clauses AND together, so combine a provider-SID or body fragment with channel, status, and time constraints. Two worked examples per channel:

**SMS**

```text theme={null}
channel:sms status:failed created>2026-08-20
message_id:SMc1f8a9d27b channel:sms direction:outbound
```

**WhatsApp**

```text theme={null}
channel:whatsapp status:delivered to:+1415* created>=2026-08-01
external_id:wamid.HBgL* channel:whatsapp direction:outbound
```

**Email**

```text theme={null}
channel:email status:(failed,rejected) created>=2026-08-01
direction:outbound to:*@example.com channel:email created>2026-08-20
```

**RCS**

```text theme={null}
channel:rcs status:sent created>2026-08-20
body:delivery* channel:rcs direction:inbound
```

**Viber**

```text theme={null}
channel:viber status:delivered created<=2026-08-24
external_id:79ka* channel:viber direction:outbound
```

**Voice**

```text theme={null}
channel:voice status:delivered from:+1415*
message_id:CAa1b2* channel:voice direction:outbound
```

**Fax**

```text theme={null}
channel:fax status:failed created:[2026-08-01 TO 2026-08-24]
direction:outbound to:+1212555* channel:fax
```

**Instagram / Messenger**

```text theme={null}
channel:instagram body:refund* direction:inbound
channel:messenger status:(failed,rejected) created>2026-08-20
```

**LINE / Telegram**

```text theme={null}
channel:line status:delivered contact_id:ct_x7k2p9
channel:telegram direction:inbound body:booking* created>2026-08-01
```

## Quoting rules for body fragments and whitespace

Values containing whitespace must be double-quoted; anything else can stay bare. Inside quotes, internal whitespace and wildcards are preserved:

```text theme={null}
body:"payment received"
body:"your order #4021*"
```

`\"` and `\\` are the only escape sequences; a backslash before any other character is kept literally. An unterminated quote is a `422 INVALID_QUERY_SYNTAX`, not a silent truncation. Phone values need no quoting — a leading `+` never turns the value into a number.

## Bookmarkable filtered views — the `q=` URL parameter

The same `q` expression that the Messages Hub search box runs also rides the dashboard URL, so a filtered view is a link, not a keystroke ritual. Compose the filter once, then copy the address bar:

```text theme={null}
https://orbit.devotel.io/dashboard/messages?q=channel%3Awhatsapp%20status%3Afailed%20created%3E2026-08-20
```

Anyone on the tenant with messages access who opens the link lands on the same filtered result set, which makes investigations and support hand-offs one paste instead of a screenshot plus instructions. The Delivery log page works the same way for its own filter parameters — see the [Delivery log](/guides/delivery-log) guide.

## Both identifiers come back in the response

Each matching row carries both the raw provider SID (`external_id`) and the canonical Orbit `id` (`msg_...`) — so the lookup can deep-link to the message detail page and your downstream reconciliation logic can still record whichever identifier it prefers. The Delivery log page in the dashboard surfaces the same correlation: a `msg_...` pasted into its search box flags a *correlated lookup* and shows the matching channels across the results strip.
