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

# send_message

> Send an outbound SMS or MMS message.

[message]: /docs/server-sdks/reference/python/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).

All parameters are keyword-only.

At least one of `body` or `media` must be provided. Providing both sends an MMS
with text and attached media.

## **Parameters**

Destination phone number in E.164 format (e.g., `"+15559876543"`).

Sender phone number in E.164 format. Must be a number owned by your SignalWire project.

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.

Text body of the message. Required for SMS. Optional for MMS if `media` is provided.

List of publicly accessible media URLs for MMS attachments (e.g., images, audio files).

Optional tags to attach to the message for filtering or tracking.

Origination region for the message.

Callback function invoked when the message reaches a terminal state
(`delivered`, `undelivered`, or `failed`). Receives the terminal
event as its argument.

## **Returns**

[`Message`][message] -- A message object in the `"queued"` state. Use `await message.wait()` to block until delivery confirmation.

## **Examples**

### Send SMS

```python {13}
import asyncio
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

async def send_sms():
    async with client:
        message = await client.send_message(
            to_number="+15559876543",
            from_number="+15551234567",
            body="Hello from SignalWire RELAY!",
        )
        print(f"Message ID: {message.message_id}")

        # Wait for delivery confirmation
        result = await message.wait(timeout=30.0)
        print(f"Final state: {message.state}")

asyncio.run(send_sms())
```

### Send MMS with media

```python {13}
import asyncio
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

async def send_mms():
    async with client:
        message = await client.send_message(
            to_number="+15559876543",
            from_number="+15551234567",
            body="Check out this image!",
            media=["https://example.com/photo.jpg"],
        )

asyncio.run(send_mms())
```

### With completion callback

```python {16}
import asyncio
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

async def on_delivered(event):
    print(f"Message delivered: {event.params}")

async def send_with_callback():
    async with client:
        message = await client.send_message(
            to_number="+15559876543",
            from_number="+15551234567",
            body="Important notification",
            on_completed=on_delivered,
        )
        # No need to await -- callback fires automatically

asyncio.run(send_with_callback())
```