RELAY

Message

View as MarkdownOpen in Claude

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.send_message() or from the @client.on_message handler for inbound messages.

1import asyncio
2from signalwire.relay import RelayClient
3
4client = RelayClient(
5 project="your-project-id",
6 token="your-api-token",
7 host="your-space.signalwire.com",
8 contexts=["default"],
9)
10
11async def send_sms():
12 async with client:
13 message = await client.send_message(
14 to_number="+15551234567",
15 from_number="+15559876543",
16 body="Hello from SignalWire!",
17 )
18
19 # Wait for delivery confirmation
20 result = await message.wait(timeout=30)
21 print(f"Final state: {message.state}")
22
23asyncio.run(send_sms())

Properties

message_id
str

Unique identifier for this message, assigned by SignalWire.

context
str

The messaging context this message belongs to.

direction
str

Message direction. Valid values:

  • "inbound" — incoming message
  • "outbound" — outgoing message
from_number
str

Sender phone number in E.164 format.

to_number
str

Recipient phone number in E.164 format.

body
str

Text content of the message.

media
list[str]

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

segments
int

Number of SMS segments required for this message.

state
str

Current message state. See 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
str

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

tags
list[str]

Optional tags associated with this message.

is_done
bool

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

result
Optional[RelayEvent]

The terminal RelayEvent that resolved this message, or None if the message has not yet completed.

Events

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

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


Methods

Examples

Listening for state changes

1import asyncio
2from signalwire.relay import RelayClient
3
4client = RelayClient(
5 project="your-project-id",
6 token="your-api-token",
7 host="your-space.signalwire.com",
8 contexts=["default"],
9)
10
11async def track_state():
12 async with client:
13 message = await client.send_message(
14 to_number="+15551234567",
15 from_number="+15559876543",
16 body="Order confirmed",
17 )
18
19 def on_state_change(event):
20 print(f"Message {message.message_id} -> {message.state}")
21
22 message.on(on_state_change)
23 await message.wait()
24
25asyncio.run(track_state())

Waiting for delivery with timeout

1import asyncio
2from signalwire.relay import RelayClient
3
4client = RelayClient(
5 project="your-project-id",
6 token="your-api-token",
7 host="your-space.signalwire.com",
8 contexts=["default"],
9)
10
11async def send_with_timeout():
12 async with client:
13 message = await client.send_message(
14 to_number="+15551234567",
15 from_number="+15559876543",
16 body="Your verification code is 123456",
17 )
18
19 try:
20 event = await message.wait(timeout=30)
21 if message.state == "delivered":
22 print("Message delivered successfully")
23 else:
24 print(f"Message failed: {message.reason}")
25 except asyncio.TimeoutError:
26 print("Timed out waiting for delivery confirmation")
27
28asyncio.run(send_with_timeout())