> For a complete index of all SignalWire documentation pages, fetch https://signalwire.com/docs/llms.txt

# Message

> SMS/MMS message tracking and state management.

[relayclient-send-message]: /docs/server-sdks/reference/typescript/relay/client/send-message

[message-constants]: /docs/server-sdks/reference/typescript/relay/constants

[relayevent]: /docs/server-sdks/reference/typescript/relay/events

[message-on]: /docs/server-sdks/reference/typescript/relay/message/on

[events]: /docs/server-sdks/reference/typescript/relay/events#messaging-events

[on]: /docs/server-sdks/reference/typescript/relay/message/on

[wait]: /docs/server-sdks/reference/typescript/relay/message/wait

The `Message` class represents a single SMS/MMS message in the Relay messaging
namespace. It tracks the lifecycle of a sent or received message through state
events. Outbound messages progress through `queued`, `initiated`, `sent`, and
then reach a terminal state (`delivered`, `undelivered`, or `failed`). Inbound
messages arrive fully formed with state `received`.

Obtain a `Message` instance from [`RelayClient.sendMessage()`][relayclient-send-message]
or from the `client.onMessage()` handler for inbound messages.

```typescript {11}
import { RelayClient } from '@signalwire/sdk';

const client = new RelayClient({
  project: process.env.SIGNALWIRE_PROJECT_ID!,
  token: process.env.SIGNALWIRE_API_TOKEN!,
  contexts: ['default']
});

await client.connect();

const message = await client.sendMessage({
  toNumber: '+15551234567',
  fromNumber: '+15559876543',
  body: 'Hello from SignalWire!',
});

// Wait for delivery confirmation
const result = await message.wait(30);
console.log(`Final state: ${message.state}`);

await client.disconnect();
```

## **Properties**

**`messageId`** `string`

Unique identifier for this message, assigned by SignalWire.

---

**`context`** `string`

The messaging context this message belongs to.

---

**`direction`** `string`

Message direction. Valid values:

* `"inbound"` -- incoming message
* `"outbound"` -- outgoing message

---

**`fromNumber`** `string`

Sender phone number in E.164 format.

---

**`toNumber`** `string`

Recipient phone number in E.164 format.

---

**`body`** `string`

Text content of the message.

---

**`media`** `string[]`

List of media URLs for MMS messages. Empty list for SMS-only messages.

---

**`segments`** `number`

Number of SMS segments required for this message.

---

**`state`** `string`

Current message state. See [`Message Constants`][message-constants] for valid values.

* `"queued"` -- message has been accepted and is waiting to be processed
* `"initiated"` -- message processing has started
* `"sent"` -- message has been dispatched to the carrier
* `"delivered"` -- message was successfully delivered to the recipient
* `"undelivered"` -- carrier was unable to deliver the message
* `"failed"` -- message could not be sent
* `"received"` -- inbound message received from the network

---

**`reason`** `string`

Failure reason when the message reaches an error state. Empty string if no failure has occurred.

---

**`tags`** `string[]`

Optional tags associated with this message.

---

**`isDone`** `boolean`

`true` if the message has reached a terminal state (`delivered`, `undelivered`, or `failed`).
Read-only property.

---

**`result`** `RelayEvent | null`

The terminal [`RelayEvent`][relayevent] that resolved this message,
or `null` if the message has not yet completed.

---

## **Events**

Events are emitted during the lifecycle of a message. Register handlers using
[`message.on()`][message-on] to react to state changes on outbound messages.

See the [Events][events] reference
for the full list of messaging events, their parameters, and typed event classes.

---

## **Methods**

#### [on](/docs/server-sdks/reference/typescript/relay/message/on)

Register an event listener for state changes on this message.

#### [wait](/docs/server-sdks/reference/typescript/relay/message/wait)

Block until the message reaches a terminal state.

## **Examples**

### Listening for state changes

```typescript {21}
import { RelayClient } from '@signalwire/sdk';

const client = new RelayClient({
  project: process.env.SIGNALWIRE_PROJECT_ID!,
  token: process.env.SIGNALWIRE_API_TOKEN!,
  contexts: ['default']
});

await client.connect();

const message = await client.sendMessage({
  toNumber: '+15551234567',
  fromNumber: '+15559876543',
  body: 'Order confirmed',
});

const onStateChange = (event) => {
  console.log(`Message ${message.messageId} -> ${message.state}`);
};

message.on(onStateChange);
await message.wait();

await client.disconnect();
```

### Waiting for delivery with timeout

```typescript {19}
import { RelayClient } from '@signalwire/sdk';

const client = new RelayClient({
  project: process.env.SIGNALWIRE_PROJECT_ID!,
  token: process.env.SIGNALWIRE_API_TOKEN!,
  contexts: ['default']
});

await client.connect();

const message = await client.sendMessage({
  toNumber: '+15551234567',
  fromNumber: '+15559876543',
  body: 'Your verification code is 123456',
});

try {
  const event = await message.wait(30);
  if (message.state === 'delivered') {
    console.log('Message delivered successfully');
  } else {
    console.log(`Message failed: ${message.reason}`);
  }
} catch (err) {
  console.log('Timed out waiting for delivery confirmation');
}

await client.disconnect();
```