Skip to content

Commit a2d286f

Browse files
authored
DEVEXP-1310: Redesign Webhooks - Conversation (#133)
1 parent b153152 commit a2d286f

47 files changed

Lines changed: 344 additions & 296 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,7 @@ poetry.lock
138138
# .DS_Store files
139139
.DS_Store
140140

141-
qodana.yaml
141+
qodana.yaml
142+
143+
# AI stuff
144+
.claude

MIGRATION_GUIDE.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,38 @@ The Conversation domain API access remains `sinch_client.conversation`; message
126126
| `list()` with `ListConversationMessagesRequest` | In Progress |
127127
|| **New in V2:** `update()` with `message_id`, `metadata`, and optional `messages_source`|
128128

129+
##### Replacement APIs / attributes
130+
131+
| Old | New |
132+
|-----|-----|
133+
| `sinch_client.conversation.webhook` (REST: create, list, get, update, delete webhooks; models under `sinch.domains.conversation.models.webhook`, e.g. `CreateConversationWebhookRequest`, `SinchListWebhooksResponse`) | **Not available in V2.** The Conversation client only exposes `messages` and `sinch_events`; More features are planned for future releases. To validate and parse inbound Sinch Events payloads, use `sinch_client.conversation.sinch_events(callback_secret)`—see **Sinch Events** below. |
134+
135+
#### Sinch Events (Event Destinations payload models and package path)
136+
137+
| Old | New |
138+
|-----|-----|
139+
|_(N/A)_ | `sinch.domains.conversation.models.v1.sinch_events` (package path for inbound payload models) |
140+
|| [`ConversationSinchEvent`](sinch/domains/conversation/sinch_events/v1/conversation_sinch_event.py) (handler: signature validation and `parse_event`) |
141+
|| `ConversationSinchEventPayload`, `ConversationSinchEventBase`, and concrete event types (e.g. `MessageInboundEvent`, `MessageDeliveryReceiptEvent`, `MessageSubmitEvent`) |
142+
143+
To obtain a Conversation Sinch Events handler: `sinch_client.conversation.sinch_events(callback_secret)` returns a [`ConversationSinchEvent`](sinch/domains/conversation/sinch_events/v1/conversation_sinch_event.py) instance; `handler.parse_event(request_body)` returns a `ConversationSinchEventPayload`.
144+
145+
```python
146+
# New
147+
handler = sinch_client.conversation.sinch_events("your_callback_secret")
148+
event = handler.parse_event(request_body)
149+
```
150+
151+
#### Request and response fields: callback URL → event destination target
152+
153+
| | Old | New |
154+
|---|-----|-----|
155+
| **Messages (`send`)** | `sinch.domains.conversation.models.message.requests.SendConversationMessageRequest` field `callback_url` | [`SendMessageRequest`](sinch/domains/conversation/models/v1/messages/internal/request/send_message_request.py) field `event_destination_target` |
156+
| **Messages (methods)** | `ConversationMessage.send(..., callback_url=...)` | `sinch_client.conversation.messages.send()`, `send_text_message()`, and other `send_*_message()` methods with `event_destination_target=...` |
157+
| **Send event** | `sinch.domains.conversation.models.event.requests.SendConversationEventRequest` field `callback_url` | `event_destination_target` on the V2 send-event request model when that API is exposed |
158+
159+
The Conversation HTTP API still expects the JSON field **`callback_url`**. In V2, use the Python parameter / model field `event_destination_target`; it is serialized as `callback_url` on the wire (same pattern as other domains, e.g. SMS).
160+
129161
<br>
130162

131163
### [`SMS`](https://github.com/sinch/sinch-sdk-python/tree/main/sinch/domains/sms)

examples/getting-started/conversation/send_handle_incoming_sms/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ The server listens on the port set in your `.env` file (default: 3001).
7070

7171
### Exposing the server with ngrok
7272

73-
To receive webhooks on your machine, expose the server with a tunnel (e.g. ngrok).
73+
To receive Conversation API Sinch Events on your machine, expose the server with a tunnel (e.g. ngrok).
7474

7575

7676
```bash

examples/getting-started/conversation/send_handle_incoming_sms/controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ def conversation_event(self):
1111
headers = dict(request.headers)
1212
raw_body = getattr(request, "raw_body", None) or b""
1313

14-
webhooks_service = self.sinch_client.conversation.webhooks()
15-
event = webhooks_service.parse_event(raw_body, headers)
14+
sinch_events_service = self.sinch_client.conversation.sinch_events()
15+
event = sinch_events_service.parse_event(raw_body, headers)
1616
handle_conversation_event(
1717
event=event,
1818
logger=self.logger,

examples/getting-started/conversation/send_handle_incoming_sms/server_business_logic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
Uses channel identity (SMS + phone number) only; app is in DISPATCH mode.
44
"""
55

6-
from sinch.domains.conversation.models.v1.webhooks import MessageInboundEvent
6+
from sinch.domains.conversation.models.v1.sinch_events import MessageInboundEvent
77

88

99
def handle_conversation_event(event, logger, sinch_client):
10-
"""Webhook entry: handle only MESSAGE_INBOUND; delegate to inbound handler."""
10+
"""Sinch Event entry: handle only MESSAGE_INBOUND; delegate to inbound handler."""
1111
if not isinstance(event, MessageInboundEvent):
1212
return
1313
_handle_message_inbound(event, logger, sinch_client)

examples/sinch_events/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Sinch Events Handlers for Sinch Python SDK
22

33
This directory contains a server application built with [Sinch Python SDK](https://github.com/sinch/sinch-sdk-python)
4-
to process incoming webhooks from Sinch services.
4+
to process incoming events from Sinch services.
55

66
The Sinch Events Handlers are organized by service:
77
- **SMS**: Handlers for SMS events (`sms_api/`)
@@ -40,7 +40,7 @@ This directory contains both the Event handlers and the server application (`ser
4040
```
4141
SMS_SINCH_EVENT_SECRET=Your Sinch SMS Sinch Event Secret
4242
```
43-
- Conversation controller: Set the webhook secret you configured when creating the webhook (see [Conversation API callbacks](https://developers.sinch.com/docs/conversation/callbacks)):
43+
- Conversation controller: Set the Sinch Event secret you configured for your Conversation app event destination (see [Conversation API callbacks](https://developers.sinch.com/docs/conversation/callbacks)):
4444
```
4545
CONVERSATION_SINCH_EVENT_SECRET=Your Conversation Sinch Event Secret
4646
```
@@ -82,7 +82,7 @@ The server exposes the following endpoints:
8282

8383
## Using ngrok to expose your local server
8484

85-
To test your webhook locally, you can tunnel requests to your local server using ngrok.
85+
To test your "Sinch Events" processing locally, you can tunnel requests to your local server using ngrok.
8686

8787
*Note: The default port is `3001`, but this can be changed (see [Server port](#Configuration))*
8888

@@ -109,5 +109,5 @@ Use this value to configure the Sinch Events URLs:
109109
You can also set these Sinch Events URLs in the Sinch dashboard; the API parameters above override the default values configured there.
110110

111111
> **Note**: If you have set a Sinch Event secret (e.g., `SMS_SINCH_EVENT_SECRET`), the Sinch Event URL must be configured in the Sinch dashboard
112-
> and cannot be overridden via API parameters. The Sinch Event secret is used to validate incoming webhook requests,
112+
> and cannot be overridden via API parameters. The Sinch Event secret is used to validate incoming Sinch Events requests,
113113
> and the URL associated with it must be set in the dashboard.

examples/sinch_events/conversation_api/controller.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ def conversation_event(self):
1212
headers = dict(request.headers)
1313
raw_body = request.raw_body if request.raw_body else b""
1414

15-
webhooks_service = self.sinch_client.conversation.webhooks(
15+
sinch_events_service = self.sinch_client.conversation.sinch_events(
1616
self.sinch_event_secret
1717
)
1818

1919
# Set to True to enforce signature validation (recommended in production)
2020
ensure_valid_signature = False
2121
if ensure_valid_signature:
22-
valid = webhooks_service.validate_authentication_header(
22+
valid = sinch_events_service.validate_authentication_header(
2323
headers=headers,
2424
json_payload=raw_body,
2525
)
2626
if not valid:
2727
return Response(status=401)
2828

29-
event = webhooks_service.parse_event(raw_body, headers)
29+
event = sinch_events_service.parse_event(raw_body, headers)
3030
handle_conversation_event(event=event, logger=self.logger)
3131

3232
return Response(status=200)

examples/sinch_events/conversation_api/server_business_logic.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
from sinch.domains.conversation.models.v1.webhooks import (
2-
ConversationWebhookEventBase,
1+
from sinch.domains.conversation.models.v1.sinch_events import (
2+
ConversationSinchEventBase,
33
MessageDeliveryReceiptEvent,
44
MessageInboundEvent,
55
MessageSubmitEvent,
66
)
77

88

9-
def handle_conversation_event(event: ConversationWebhookEventBase, logger):
9+
def handle_conversation_event(event: ConversationSinchEventBase, logger):
1010
"""
11-
Dispatch a Conversation webhook event to the appropriate handler by trigger type.
11+
Dispatch a Conversation Sinch Event to the appropriate handler by trigger type.
1212
13-
:param event: Parsed webhook event (MessageDeliveryReceiptEvent, MessageInboundEvent, etc.).
13+
:param event: Parsed Sinch Event (MessageDeliveryReceiptEvent, MessageInboundEvent, etc.).
1414
:param logger: Logger instance for output.
1515
"""
1616
if isinstance(event, MessageInboundEvent):

examples/sinch_events/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22
name = "sinch-sdk-python-quickstart-server"
33
version = "0.1.0"
4-
description = "Sinch SDK Python Quickstart Webhooks Server"
4+
description = "Sinch SDK Python Quickstart Sinch Events Server"
55
readme = "README.md"
66
package-mode = false
77

File renamed without changes.

0 commit comments

Comments
 (0)