Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ SINCH_KEY_SECRET=
# Conversation API: existing app (already created and configured for SMS).
# SINCH_CONVERSATION_REGION is required.
# Set it to the same region as the one your app was created in (e.g. eu).
CONVERSATION_APP_ID=
SINCH_CONVERSATION_REGION=

# Webhook secret (set when configuring the callback in Sinch dashboard)
CONVERSATION_WEBHOOKS_SECRET=

# Server
SERVER_PORT=3001
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,11 @@ see that the MO was received and processed.
SINCH_KEY_SECRET=your_key_secret
```

- Conversation API app (existing app, already configured for SMS). Set `SINCH_CONVERSATION_REGION` to the same region as the one your app was created in (e.g. `eu`):
- Conversation API: set `SINCH_CONVERSATION_REGION` to the same region as the one your app was created in (e.g. `eu`).
```
CONVERSATION_APP_ID=your_conversation_app_id
SINCH_CONVERSATION_REGION=
```

- Webhook secret (the value you set when configuring the callback URL for this app).
See [Conversation API callbacks](https://developers.sinch.com/docs/conversation/callbacks):
```
CONVERSATION_WEBHOOKS_SECRET=your_webhook_secret
```

- Server port (optional; default 3001):
```
SERVER_PORT=3001
Expand Down Expand Up @@ -92,8 +85,7 @@ Forwarding https://abc123.ngrok-free.app -> http://localhost:3001
Use the **HTTPS** URL when configuring the callback:
`https://<your-ngrok-host>/ConversationEvent`

Configure this callback URL (and the webhook secret) in the Sinch dashboard for your Conversation API app.
The webhook secret must match `CONVERSATION_WEBHOOKS_SECRET` in your `.env`.
Configure this callback URL in the Sinch dashboard for your Conversation API app.

### Sending an SMS to your Sinch number

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,20 @@


class ConversationController:
def __init__(self, sinch_client, webhooks_secret, app_id):
def __init__(self, sinch_client):
self.sinch_client = sinch_client
self.webhooks_secret = webhooks_secret
self.app_id = app_id
self.logger = self.sinch_client.configuration.logger

def conversation_event(self):
headers = dict(request.headers)
raw_body = getattr(request, "raw_body", None) or b""

webhooks_service = self.sinch_client.conversation.webhooks(self.webhooks_secret)

# Set to True to enforce signature validation (recommended in production)
ensure_valid_signature = False
if ensure_valid_signature:
valid = webhooks_service.validate_authentication_header(
headers=headers,
json_payload=raw_body,
)
if not valid:
return Response(status=401)

webhooks_service = self.sinch_client.conversation.webhooks()
event = webhooks_service.parse_event(raw_body, headers)
handle_conversation_event(
event=event,
logger=self.logger,
sinch_client=self.sinch_client,
app_id=self.app_id,
)

return Response(status=200)
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ def load_config():

config = load_config()
port = int(config.get("SERVER_PORT") or "3001")
app_id = config.get("CONVERSATION_APP_ID") or ""
webhooks_secret = config.get("CONVERSATION_WEBHOOKS_SECRET") or ""
conversation_region = (config.get("SINCH_CONVERSATION_REGION") or "").strip()
if not conversation_region:
raise ValueError(
Expand All @@ -39,9 +37,7 @@ def load_config():
logging.basicConfig()
sinch_client.configuration.logger.setLevel(logging.INFO)

conversation_controller = ConversationController(
sinch_client, webhooks_secret, app_id
)
conversation_controller = ConversationController(sinch_client)


@app.before_request
Expand All @@ -57,6 +53,5 @@ def before_request():

if __name__ == "__main__":
print("Getting Started: MO SMS → MT reply (Conversation API, DISPATCH, channel identity)")
print(f"App ID: {app_id or '(set CONVERSATION_APP_ID in .env)'}")
print(f"Listening on port {port}. Expose with: ngrok http {port}")
app.run(port=port)
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from sinch.domains.conversation.models.v1.webhooks import MessageInboundEvent


def handle_conversation_event(event, logger, sinch_client, app_id):
def handle_conversation_event(event, logger, sinch_client):
"""Webhook entry: handle only MESSAGE_INBOUND; delegate to inbound handler."""
if not isinstance(event, MessageInboundEvent):
return
_handle_message_inbound(event, logger, sinch_client, app_id)
_handle_message_inbound(event, logger, sinch_client)


def _get_mo_text(event: MessageInboundEvent) -> str:
Expand All @@ -22,7 +22,7 @@ def _get_mo_text(event: MessageInboundEvent) -> str:
return "(no text content)"


def _handle_message_inbound(event: MessageInboundEvent, logger, sinch_client, app_id):
def _handle_message_inbound(event: MessageInboundEvent, logger, sinch_client):
"""Parse MO, then send MT echo to the same number via Conversation API."""
msg = event.message
channel_identity = msg.channel_identity
Expand All @@ -34,8 +34,9 @@ def _handle_message_inbound(event: MessageInboundEvent, logger, sinch_client, ap
mo_text = _get_mo_text(event)
logger.info("MO SMS from %s: %s", identity, mo_text)

app_id = event.app_id
if not app_id:
logger.warning("CONVERSATION_APP_ID not set; skipping MT reply.")
logger.warning("Event has no app_id; skipping MT reply.")
return

reply_text = f"Your message said: {mo_text}"
Expand Down
2 changes: 1 addition & 1 deletion sinch/domains/conversation/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, sinch):
self._sinch = sinch
self.messages = Messages(self._sinch)

def webhooks(self, callback_secret: str) -> ConversationWebhooks:
def webhooks(self, callback_secret: str = "") -> ConversationWebhooks:
"""
Create a Conversation API webhooks handler with the given webhook secret.
Expand Down