> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes. # sendMessage > Send an outbound SMS or MMS message. [message]: /docs/server-sdks/reference/typescript/relay/message Send an outbound SMS or MMS message. Returns a [`Message`][message] object that tracks delivery state changes. Use `await message.wait()` to block until the message reaches a terminal state (delivered, undelivered, or failed). > **Note** > > At least one of `body` or `media` must be provided. Providing both sends an MMS > with text and attached media. ## **Parameters** **`toNumber`** `string` — required Destination phone number in E.164 format (e.g., `"+15559876543"`). --- **`fromNumber`** `string` — required Sender phone number in E.164 format. Must be a number owned by your SignalWire project. --- **`context`** `string | undefined` Context for receiving state-change events for this message. Defaults to the server-assigned relay protocol string, or `"default"` if no protocol has been assigned yet. --- **`body`** `string | undefined` Text body of the message. Required for SMS. Optional for MMS if `media` is provided. --- **`media`** `string[] | undefined` List of publicly accessible media URLs for MMS attachments (e.g., images, audio files). --- **`tags`** `string[] | undefined` Optional tags to attach to the message for filtering or tracking. --- **`region`** `string | undefined` Origination region for the message. --- **`onCompleted`** `(event: any) => void | Promise` Callback function invoked when the message reaches a terminal state (`delivered`, `undelivered`, or `failed`). Receives the terminal event as its argument. --- ## **Returns** `Promise<`[`Message`][message]`>` -- A message object in the `"queued"` state. Use `await message.wait()` to block until delivery confirmation. ## **Examples** ### Send SMS ```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: '+15559876543', fromNumber: '+15551234567', body: 'Hello from SignalWire Relay!', }); console.log(`Message ID: ${message.messageId}`); // Wait for delivery confirmation const result = await message.wait(30); console.log(`Final state: ${message.state}`); await client.disconnect(); ``` ### Send MMS with media ```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: '+15559876543', fromNumber: '+15551234567', body: 'Check out this image!', media: ['https://example.com/photo.jpg'], }); await client.disconnect(); ``` ### With completion callback ```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: '+15559876543', fromNumber: '+15551234567', body: 'Important notification', onCompleted: (event) => { console.log(`Message delivered: ${JSON.stringify(event.params)}`); }, }); // No need to await -- callback fires automatically await client.disconnect(); ``` > Send an outbound SMS or MMS message.