Skip to content

Commit 246cec7

Browse files
authored
Merge branch 'v2.1-next' into bugfix/DEVEXP-765-syncronize-token-managers
2 parents 1dfaa33 + 11bc931 commit 246cec7

90 files changed

Lines changed: 3907 additions & 374 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.

.github/workflows/ci.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,7 @@ jobs:
8484
cp sinch-sdk-mockserver/features/numbers/callback-configuration.feature ./tests/e2e/numbers/features/
8585
cp sinch-sdk-mockserver/features/numbers/numbers.feature ./tests/e2e/numbers/features/
8686
cp sinch-sdk-mockserver/features/numbers/webhooks.feature ./tests/e2e/numbers/features/
87-
cp sinch-sdk-mockserver/features/sms/delivery-reports.feature ./tests/e2e/sms/features/
88-
cp sinch-sdk-mockserver/features/sms/delivery-reports_servicePlanId.feature ./tests/e2e/sms/features/
89-
cp sinch-sdk-mockserver/features/sms/batches.feature ./tests/e2e/sms/features/
90-
cp sinch-sdk-mockserver/features/sms/batches_servicePlanId.feature ./tests/e2e/sms/features/
91-
cp sinch-sdk-mockserver/features/sms/webhooks.feature ./tests/e2e/sms/features/
87+
cp sinch-sdk-mockserver/features/sms/* ./tests/e2e/sms/features/
9288
cp sinch-sdk-mockserver/features/number-lookup/lookups.feature ./tests/e2e/number-lookup/features/
9389
cp sinch-sdk-mockserver/features/conversation/messages.feature ./tests/e2e/conversation/features/
9490
cp sinch-sdk-mockserver/features/conversation/webhooks-events.feature ./tests/e2e/conversation/features/

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ coverage.xml
5151
.hypothesis/
5252
.pytest_cache/
5353
cover/
54+
lcov.info
5455

5556
# E2E features
5657
*.feature

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ All notable changes to the **Sinch Python SDK** are documented in this file.
1616
1717
---
1818

19+
## v2.1.0 – 2026-06-05
20+
21+
### SDK
22+
23+
- **[dependency]** Set up minimum version for `requests` to `>=2.0.0` to prevent pulling in versions with known vulnerabilities (#152).
24+
25+
26+
### SMS
27+
28+
- **[feature]** SMS Groups API: `create`, `list`, `get`, `update`, `replace`, `delete`, and `list_members` operations, with full model, endpoint, and unit test coverage (see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md#groups-api)).
29+
- **[feature]** SMS Inbounds API: `get` and `list` operations, with full model, endpoint, and unit test coverage (see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md#inbounds-api)).
30+
- **[design]** SMS Sinch Events inbound payload models unified with the Inbounds API: `MOTextSinchEvent`, `MOBinarySinchEvent`, `MOMediaSinchEvent`, `MediaBody`, and `MediaItem` removed from `sinch_events`; use `InboundMessage` (and its variants) from `sinch.domains.sms.models.v1.types` instead (see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md#sms-sinch-events)).
31+
32+
---
33+
1934
## v2.0.1 – 2026-06-02
2035

2136
### SMS

MIGRATION_GUIDE.md

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Sinch Python SDK Migration Guide
22

3-
## 2.0.0
3+
## 2.1.0
44

55
This release removes legacy SDK support.
66

@@ -205,9 +205,7 @@ The Conversation HTTP API still expects the JSON field **`callback_url`**. In V2
205205

206206
#### Replacement APIs
207207

208-
The SMS domain API access remains the same: `sinch.sms.batches` and `sinch.sms.delivery_reports`. However, the underlying models and method signatures have changed.
209-
210-
Note that `sinch.sms.groups` and `sinch.sms.inbounds` are not supported yet and will be available in future minor versions.
208+
The SMS domain API access remains the same: `sinch.sms.batches`, `sinch.sms.delivery_reports`, `sinch.sms.inbounds` and `sinch.sms.groups`. However, the underlying models and method signatures have changed. See the sections below for the full list of changes: [Batches](#batches-api), [Delivery Reports](#delivery-reports-api), [Groups](#groups-api), [Inbounds](#inbounds-api).
211209

212210
##### Batches API
213211

@@ -230,6 +228,71 @@ Note that `sinch.sms.groups` and `sinch.sms.inbounds` are not supported yet and
230228
| `get_for_batch()` with `GetSMSDeliveryReportForBatchRequest` | `get()` with `batch_id: str` and optional parameters: `report_type`, `status`, `code`, `client_reference` |
231229
| `get_for_number()` with `GetSMSDeliveryReportForNumberRequest` | `get_for_number()` with `batch_id: str` and `recipient: str` parameters |
232230

231+
##### Groups API
232+
233+
###### Replacement models
234+
235+
| Old class | New class |
236+
|-----------|-----------|
237+
| `sinch.domains.sms.models.groups.requests.CreateSMSGroupRequest` | [`sinch.domains.sms.models.v1.internal.GroupRequest`](sinch/domains/sms/models/v1/internal/group_request.py) |
238+
| `sinch.domains.sms.models.groups.requests.ListSMSGroupRequest` | [`sinch.domains.sms.models.v1.internal.ListGroupsRequest`](sinch/domains/sms/models/v1/internal/list_groups_request.py) |
239+
| `sinch.domains.sms.models.groups.requests.GetSMSGroupRequest` | [`sinch.domains.sms.models.v1.internal.GroupIdRequest`](sinch/domains/sms/models/v1/internal/group_id_request.py) |
240+
| `sinch.domains.sms.models.groups.requests.DeleteSMSGroupRequest` | [`sinch.domains.sms.models.v1.internal.GroupIdRequest`](sinch/domains/sms/models/v1/internal/group_id_request.py) |
241+
| `sinch.domains.sms.models.groups.requests.GetSMSGroupPhoneNumbersRequest` | [`sinch.domains.sms.models.v1.internal.GroupIdRequest`](sinch/domains/sms/models/v1/internal/group_id_request.py) |
242+
| `sinch.domains.sms.models.groups.requests.UpdateSMSGroupRequest` | [`sinch.domains.sms.models.v1.internal.UpdateGroupRequest`](sinch/domains/sms/models/v1/internal/update_group_request.py) |
243+
| `sinch.domains.sms.models.groups.requests.ReplaceSMSGroupPhoneNumbersRequest` | [`sinch.domains.sms.models.v1.internal.ReplaceGroupRequest`](sinch/domains/sms/models/v1/internal/replace_group_request.py) |
244+
| `sinch.domains.sms.models.groups.responses.CreateSMSGroupResponse` | [`sinch.domains.sms.models.v1.response.GroupResponse`](sinch/domains/sms/models/v1/response/group_response.py) |
245+
| `sinch.domains.sms.models.groups.responses.GetSMSGroupResponse` | [`sinch.domains.sms.models.v1.response.GroupResponse`](sinch/domains/sms/models/v1/response/group_response.py) |
246+
| `sinch.domains.sms.models.groups.responses.UpdateSMSGroupResponse` | [`sinch.domains.sms.models.v1.response.GroupResponse`](sinch/domains/sms/models/v1/response/group_response.py) |
247+
| `sinch.domains.sms.models.groups.responses.ReplaceSMSGroupResponse` | [`sinch.domains.sms.models.v1.response.GroupResponse`](sinch/domains/sms/models/v1/response/group_response.py) |
248+
| `sinch.domains.sms.models.groups.responses.SinchListSMSGroupResponse` | [`sinch.domains.sms.models.v1.response.ListGroupsResponse`](sinch/domains/sms/models/v1/response/list_groups_response.py) |
249+
| `sinch.domains.sms.models.groups.responses.SinchGetSMSGroupPhoneNumbersResponse` | [`sinch.domains.sms.models.v1.response.ListGroupMembersResponse`](sinch/domains/sms/models/v1/response/list_group_members_response.py) |
250+
| `sinch.domains.sms.models.groups.responses.SinchDeleteSMSGroupResponse` | `None` (method returns `None`) |
251+
252+
###### Replacement APIs
253+
254+
| Old method | New method in `sms.groups` |
255+
|------------|---------------------------|
256+
| `create()` with `CreateSMSGroupRequest` | `create()` with individual parameters: `name`, `members`, `child_groups`, `auto_update` |
257+
| `list()` with `ListSMSGroupRequest` | `list()` with individual parameters: `page`, `page_size`. Returns **`Paginator[GroupResponse]`** |
258+
| `get()` with `GetSMSGroupRequest` | `get()` with `group_id: str` parameter |
259+
| `update()` with `UpdateSMSGroupRequest` | `update()` with `group_id: str` and optional parameters: `add`, `remove`, `name`, `add_from_group`, `remove_from_group`, `auto_update` |
260+
| `replace()` with `ReplaceSMSGroupPhoneNumbersRequest` | `replace()` with `group_id: str` and optional parameters: `name`, `members`, `child_groups`, `auto_update` |
261+
| `delete()` with `DeleteSMSGroupRequest` | `delete()` with `group_id: str` parameter |
262+
| `get_phone_numbers()` / phone number listing | `list_members()` with `group_id: str`. Returns **`Paginator[str]`** |
263+
264+
##### Inbounds API
265+
266+
###### Replacement models
267+
268+
| Old class | New class |
269+
|-----------|-----------|
270+
| `sinch.domains.sms.models.inbounds.requests.ListSMSInboundMessageRequest` | [`sinch.domains.sms.models.v1.internal.ListInboundsRequest`](sinch/domains/sms/models/v1/internal/list_inbounds_request.py) |
271+
| `sinch.domains.sms.models.inbounds.requests.GetSMSInboundMessageRequest` | [`sinch.domains.sms.models.v1.internal.InboundIdRequest`](sinch/domains/sms/models/v1/internal/inbound_id_request.py) |
272+
| `sinch.domains.sms.models.inbounds.responses.SinchListInboundMessagesResponse` | [`sinch.domains.sms.models.v1.internal.ListInboundsResponse`](sinch/domains/sms/models/v1/internal/list_inbounds_response.py) |
273+
| `sinch.domains.sms.models.inbounds.responses.GetInboundMessagesResponse` | [`sinch.domains.sms.models.v1.types.InboundMessage`](sinch/domains/sms/models/v1/types/inbound_message.py) (Union of `MOTextMessage`, `MOBinaryMessage`, `MOMediaMessage`) |
274+
275+
###### Replacement APIs
276+
277+
| Old method | New method in `sms.inbounds` |
278+
|------------|------------------------------|
279+
| `list()` with `ListSMSInboundMessageRequest` | `list()` with individual parameters: `page`, `page_size`, `to`, `start_date`, `end_date`, `client_reference`. Returns **`Paginator[InboundMessage]`** |
280+
| `get()` with `GetSMSInboundMessageRequest` | `get()` with `inbound_id: str` parameter |
281+
282+
##### SMS Sinch Events
283+
284+
The inbound payload models in `sinch_events` have been unified with the Inbounds API models. The following classes have been removed:
285+
286+
| Removed class | Replacement |
287+
|---------------|-------------|
288+
| `sinch.domains.sms.sinch_events.v1.events.MOTextSinchEvent` | [`sinch.domains.sms.models.v1.shared.MOTextMessage`](sinch/domains/sms/models/v1/shared/mo_text_message.py) |
289+
| `sinch.domains.sms.sinch_events.v1.events.MOBinarySinchEvent` | [`sinch.domains.sms.models.v1.shared.MOBinaryMessage`](sinch/domains/sms/models/v1/shared/mo_binary_message.py) |
290+
| `sinch.domains.sms.sinch_events.v1.events.MOMediaSinchEvent` | [`sinch.domains.sms.models.v1.shared.MOMediaMessage`](sinch/domains/sms/models/v1/shared/mo_media_message.py) |
291+
| `sinch.domains.sms.sinch_events.v1.events.MediaBody` | Embedded in `MOMediaMessage` |
292+
| `sinch.domains.sms.sinch_events.v1.events.MediaItem` | Embedded in `MOMediaMessage` |
293+
294+
`IncomingSMSSinchEvent` is now a type alias for [`InboundMessage`](sinch/domains/sms/models/v1/types/inbound_message.py) (discriminated union of `MOTextMessage`, `MOBinaryMessage`, `MOMediaMessage`). Code that previously type-checked against `MOTextSinchEvent` and siblings should switch to their `MO*Message` equivalents.
295+
233296
---
234297

235298
### [`Numbers` (Virtual Numbers)](https://github.com/sinch/sinch-sdk-python/tree/main/sinch/domains/numbers)
@@ -244,6 +307,7 @@ Note that `sinch.sms.groups` and `sinch.sms.inbounds` are not supported yet and
244307

245308
##### Replacement models
246309

310+
247311
| Old class | New class |
248312
|-----------|-----------|
249313
| `UpdateNumbersCallbackConfigurationRequest` | `UpdateEventDestinationRequest` |
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
9+
from dotenv import load_dotenv
10+
11+
from sinch import SinchClient
12+
13+
load_dotenv()
14+
15+
sinch_client = SinchClient(
16+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
17+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
18+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
19+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
20+
)
21+
22+
response = sinch_client.sms.groups.create(
23+
name="Sinch Python SDK group", members=["+1234567890", "+1987654321"]
24+
)
25+
26+
print(f"Group created:\n{response}")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
9+
from dotenv import load_dotenv
10+
11+
from sinch import SinchClient
12+
13+
load_dotenv()
14+
15+
sinch_client = SinchClient(
16+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
17+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
18+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
19+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
20+
)
21+
22+
# The ID of the group to delete
23+
group_id = "GROUP_ID"
24+
25+
sinch_client.sms.groups.delete(group_id=group_id)
26+
27+
print(f"Group {group_id} deleted")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
9+
from dotenv import load_dotenv
10+
11+
from sinch import SinchClient
12+
13+
load_dotenv()
14+
15+
sinch_client = SinchClient(
16+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
17+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
18+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
19+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
20+
)
21+
22+
# The ID of the group to retrieve
23+
GROUP_ID = "GROUP_ID"
24+
25+
response = sinch_client.sms.groups.get(
26+
group_id=GROUP_ID
27+
)
28+
29+
print(f"Group details:\n{response}")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
9+
from dotenv import load_dotenv
10+
11+
from sinch import SinchClient
12+
13+
load_dotenv()
14+
15+
sinch_client = SinchClient(
16+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
17+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
18+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
19+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
20+
)
21+
22+
groups = sinch_client.sms.groups.list()
23+
24+
print("List of groups:\n")
25+
for group in groups.iterator():
26+
print(group)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
from typing import List
9+
10+
from dotenv import load_dotenv
11+
12+
from sinch import SinchClient
13+
14+
load_dotenv()
15+
16+
sinch_client = SinchClient(
17+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
18+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
19+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
20+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
21+
)
22+
23+
# The ID of the group to list members for
24+
group_id = "GROUP_ID"
25+
26+
members = sinch_client.sms.groups.list_members(group_id=group_id)
27+
28+
print("List of members:\n")
29+
for member in members.iterator():
30+
print(member)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
Sinch Python Snippet
3+
4+
This snippet is available at https://github.com/sinch/sinch-sdk-python/tree/main/examples/snippets
5+
"""
6+
7+
import os
8+
9+
from dotenv import load_dotenv
10+
11+
from sinch import SinchClient
12+
13+
load_dotenv()
14+
15+
sinch_client = SinchClient(
16+
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
17+
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
18+
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
19+
sms_region=os.environ.get("SINCH_SMS_REGION") or "MY_SMS_REGION"
20+
)
21+
22+
# The ID of the group to replace
23+
group_id = "GROUP_ID"
24+
25+
response = sinch_client.sms.groups.replace(
26+
group_id=group_id,
27+
members=["+1234567890", "+1987654321"],
28+
)
29+
30+
print(f"Group replaced:\n{response}")

0 commit comments

Comments
 (0)