Skip to content

Commit aa82391

Browse files
author
stlc-bot
committed
feat(api): add voice and calls endpoints to the SDKs
Stainless-Generated-From: e30a9e0dd12e2c7c1cb182ff924679ffbab0874c
1 parent 1a37cfd commit aa82391

60 files changed

Lines changed: 6320 additions & 113 deletions

Some content is hidden

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

‎.stats.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
configured_endpoints: 43
1+
configured_endpoints: 60

‎api.md‎

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Types:
66
from sent_dm.types import (
77
APIMeta,
88
APIResponseWebhook,
9+
CallEvent,
10+
CallEventPayload,
911
ChannelEvent,
1012
ChannelEventPayload,
1113
ContactEvent,
@@ -204,6 +206,87 @@ Methods:
204206
- <code title="get /v3/conversations">client.conversations.<a href="./src/sent_dm/resources/conversations.py">list</a>(\*\*<a href="src/sent_dm/types/conversation_list_params.py">params</a>) -> SyncConversationsPage[Message]</code>
205207
- <code title="get /v3/conversations/{id}">client.conversations.<a href="./src/sent_dm/resources/conversations.py">list_messages</a>(id, \*\*<a href="src/sent_dm/types/conversation_list_messages_params.py">params</a>) -> SyncConversationsPage[Message]</code>
206208

209+
# Calls
210+
211+
Types:
212+
213+
```python
214+
from sent_dm.types import (
215+
APIResponseOfCall,
216+
APIResponseOfCallRecordings,
217+
APIResponseOfCallsList,
218+
Call,
219+
CallParty,
220+
CallRecording,
221+
CallRecordings,
222+
CallTimelineEntry,
223+
CallsList,
224+
)
225+
```
226+
227+
Methods:
228+
229+
- <code title="get /v3/calls/{id}">client.calls.<a href="./src/sent_dm/resources/calls/calls.py">retrieve</a>(id) -> <a href="./src/sent_dm/types/api_response_of_call.py">APIResponseOfCall</a></code>
230+
- <code title="get /v3/calls">client.calls.<a href="./src/sent_dm/resources/calls/calls.py">list</a>(\*\*<a href="src/sent_dm/types/call_list_params.py">params</a>) -> <a href="./src/sent_dm/types/call.py">SyncCallsPage[Call]</a></code>
231+
- <code title="post /v3/calls/{id}/hangup">client.calls.<a href="./src/sent_dm/resources/calls/calls.py">hangup</a>(id, \*\*<a href="src/sent_dm/types/call_hangup_params.py">params</a>) -> None</code>
232+
- <code title="get /v3/calls/{id}/recordings">client.calls.<a href="./src/sent_dm/resources/calls/calls.py">list_recordings</a>(id) -> <a href="./src/sent_dm/types/api_response_of_call_recordings.py">APIResponseOfCallRecordings</a></code>
233+
- <code title="post /v3/calls/{id}/recordings">client.calls.<a href="./src/sent_dm/resources/calls/calls.py">record</a>(id, \*\*<a href="src/sent_dm/types/call_record_params.py">params</a>) -> None</code>
234+
235+
## Participants
236+
237+
Types:
238+
239+
```python
240+
from sent_dm.types.calls import (
241+
APIResponseOfListOfCallParticipant,
242+
CallParticipant,
243+
CallParticipantTarget,
244+
)
245+
```
246+
247+
Methods:
248+
249+
- <code title="patch /v3/calls/{id}/participants/{participantId}">client.calls.participants.<a href="./src/sent_dm/resources/calls/participants.py">update</a>(participant_id, \*, id, \*\*<a href="src/sent_dm/types/calls/participant_update_params.py">params</a>) -> None</code>
250+
- <code title="get /v3/calls/{id}/participants">client.calls.participants.<a href="./src/sent_dm/resources/calls/participants.py">list</a>(id) -> <a href="./src/sent_dm/types/calls/api_response_of_list_of_call_participant.py">APIResponseOfListOfCallParticipant</a></code>
251+
- <code title="post /v3/calls/{id}/participants">client.calls.participants.<a href="./src/sent_dm/resources/calls/participants.py">add</a>(id, \*\*<a href="src/sent_dm/types/calls/participant_add_params.py">params</a>) -> <a href="./src/sent_dm/types/api_response_of_call.py">APIResponseOfCall</a></code>
252+
- <code title="delete /v3/calls/{id}/participants/{participantId}">client.calls.participants.<a href="./src/sent_dm/resources/calls/participants.py">remove</a>(participant_id, \*, id, \*\*<a href="src/sent_dm/types/calls/participant_remove_params.py">params</a>) -> None</code>
253+
- <code title="delete /v3/calls/{id}/participants">client.calls.participants.<a href="./src/sent_dm/resources/calls/participants.py">remove_all</a>(id, \*\*<a href="src/sent_dm/types/calls/participant_remove_all_params.py">params</a>) -> None</code>
254+
255+
# Channels
256+
257+
## Voice
258+
259+
Types:
260+
261+
```python
262+
from sent_dm.types.channels import (
263+
APIResponseOfListOfVoiceNumber,
264+
APIResponseOfVoiceCallbackTest,
265+
APIResponseOfVoiceNumber,
266+
APIResponseOfVoiceNumberCreated,
267+
APIResponseOfVoiceSecret,
268+
APIResponseOfVoiceToken,
269+
VoiceCallbackTest,
270+
VoiceCallbackTestErrorInfo,
271+
VoiceCallbackTestRequestInfo,
272+
VoiceCallbackTestResponseInfo,
273+
VoiceNumber,
274+
VoiceNumberCreated,
275+
VoiceSecret,
276+
VoiceToken,
277+
)
278+
```
279+
280+
Methods:
281+
282+
- <code title="post /v3/channels/voice">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">create</a>(\*\*<a href="src/sent_dm/types/channels/voice_create_params.py">params</a>) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_number_created.py">APIResponseOfVoiceNumberCreated</a></code>
283+
- <code title="get /v3/channels/voice/{number}">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">retrieve</a>(number) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_number.py">APIResponseOfVoiceNumber</a></code>
284+
- <code title="patch /v3/channels/voice/{number}">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">update</a>(number, \*\*<a href="src/sent_dm/types/channels/voice_update_params.py">params</a>) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_number.py">APIResponseOfVoiceNumber</a></code>
285+
- <code title="get /v3/channels/voice">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">list</a>() -> <a href="./src/sent_dm/types/channels/api_response_of_list_of_voice_number.py">APIResponseOfListOfVoiceNumber</a></code>
286+
- <code title="post /v3/channels/voice/tokens">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">create_token</a>(\*\*<a href="src/sent_dm/types/channels/voice_create_token_params.py">params</a>) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_token.py">APIResponseOfVoiceToken</a></code>
287+
- <code title="post /v3/channels/voice/{number}/rotate-secret">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">rotate_secret</a>(number, \*\*<a href="src/sent_dm/types/channels/voice_rotate_secret_params.py">params</a>) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_secret.py">APIResponseOfVoiceSecret</a></code>
288+
- <code title="post /v3/channels/voice/{number}/test">client.channels.voice.<a href="./src/sent_dm/resources/channels/voice.py">test</a>(number, \*\*<a href="src/sent_dm/types/channels/voice_test_params.py">params</a>) -> <a href="./src/sent_dm/types/channels/api_response_of_voice_callback_test.py">APIResponseOfVoiceCallbackTest</a></code>
289+
207290
# Me
208291

209292
Types:

‎src/sent_dm/_client.py‎

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,29 @@
3636
)
3737

3838
if TYPE_CHECKING:
39-
from .resources import me, users, numbers, contacts, messages, profiles, webhooks, templates, conversations
39+
from .resources import (
40+
me,
41+
calls,
42+
users,
43+
numbers,
44+
channels,
45+
contacts,
46+
messages,
47+
profiles,
48+
webhooks,
49+
templates,
50+
conversations,
51+
)
4052
from .resources.me import MeResource, AsyncMeResource
4153
from .resources.users import UsersResource, AsyncUsersResource
4254
from .resources.numbers import NumbersResource, AsyncNumbersResource
4355
from .resources.contacts import ContactsResource, AsyncContactsResource
4456
from .resources.messages import MessagesResource, AsyncMessagesResource
4557
from .resources.webhooks import WebhooksResource, AsyncWebhooksResource
4658
from .resources.templates import TemplatesResource, AsyncTemplatesResource
59+
from .resources.calls.calls import CallsResource, AsyncCallsResource
4760
from .resources.conversations import ConversationsResource, AsyncConversationsResource
61+
from .resources.channels.channels import ChannelsResource, AsyncChannelsResource
4862
from .resources.profiles.profiles import ProfilesResource, AsyncProfilesResource
4963

5064
__all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Sent", "AsyncSent", "Client", "AsyncClient"]
@@ -206,6 +220,24 @@ def conversations(self) -> ConversationsResource:
206220

207221
return ConversationsResource(self)
208222

223+
@cached_property
224+
def calls(self) -> CallsResource:
225+
"""Phone calls from the numbers you hold, driven by your own callback URL.
226+
227+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
228+
229+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
230+
"""
231+
from .resources.calls import CallsResource
232+
233+
return CallsResource(self)
234+
235+
@cached_property
236+
def channels(self) -> ChannelsResource:
237+
from .resources.channels import ChannelsResource
238+
239+
return ChannelsResource(self)
240+
209241
@cached_property
210242
def me(self) -> MeResource:
211243
"""Who the current key is.
@@ -492,6 +524,24 @@ def conversations(self) -> AsyncConversationsResource:
492524

493525
return AsyncConversationsResource(self)
494526

527+
@cached_property
528+
def calls(self) -> AsyncCallsResource:
529+
"""Phone calls from the numbers you hold, driven by your own callback URL.
530+
531+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
532+
533+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
534+
"""
535+
from .resources.calls import AsyncCallsResource
536+
537+
return AsyncCallsResource(self)
538+
539+
@cached_property
540+
def channels(self) -> AsyncChannelsResource:
541+
from .resources.channels import AsyncChannelsResource
542+
543+
return AsyncChannelsResource(self)
544+
495545
@cached_property
496546
def me(self) -> AsyncMeResource:
497547
"""Who the current key is.
@@ -720,6 +770,24 @@ def conversations(self) -> conversations.ConversationsResourceWithRawResponse:
720770

721771
return ConversationsResourceWithRawResponse(self._client.conversations)
722772

773+
@cached_property
774+
def calls(self) -> calls.CallsResourceWithRawResponse:
775+
"""Phone calls from the numbers you hold, driven by your own callback URL.
776+
777+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
778+
779+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
780+
"""
781+
from .resources.calls import CallsResourceWithRawResponse
782+
783+
return CallsResourceWithRawResponse(self._client.calls)
784+
785+
@cached_property
786+
def channels(self) -> channels.ChannelsResourceWithRawResponse:
787+
from .resources.channels import ChannelsResourceWithRawResponse
788+
789+
return ChannelsResourceWithRawResponse(self._client.channels)
790+
723791
@cached_property
724792
def me(self) -> me.MeResourceWithRawResponse:
725793
"""Who the current key is.
@@ -829,6 +897,24 @@ def conversations(self) -> conversations.AsyncConversationsResourceWithRawRespon
829897

830898
return AsyncConversationsResourceWithRawResponse(self._client.conversations)
831899

900+
@cached_property
901+
def calls(self) -> calls.AsyncCallsResourceWithRawResponse:
902+
"""Phone calls from the numbers you hold, driven by your own callback URL.
903+
904+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
905+
906+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
907+
"""
908+
from .resources.calls import AsyncCallsResourceWithRawResponse
909+
910+
return AsyncCallsResourceWithRawResponse(self._client.calls)
911+
912+
@cached_property
913+
def channels(self) -> channels.AsyncChannelsResourceWithRawResponse:
914+
from .resources.channels import AsyncChannelsResourceWithRawResponse
915+
916+
return AsyncChannelsResourceWithRawResponse(self._client.channels)
917+
832918
@cached_property
833919
def me(self) -> me.AsyncMeResourceWithRawResponse:
834920
"""Who the current key is.
@@ -938,6 +1024,24 @@ def conversations(self) -> conversations.ConversationsResourceWithStreamingRespo
9381024

9391025
return ConversationsResourceWithStreamingResponse(self._client.conversations)
9401026

1027+
@cached_property
1028+
def calls(self) -> calls.CallsResourceWithStreamingResponse:
1029+
"""Phone calls from the numbers you hold, driven by your own callback URL.
1030+
1031+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
1032+
1033+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
1034+
"""
1035+
from .resources.calls import CallsResourceWithStreamingResponse
1036+
1037+
return CallsResourceWithStreamingResponse(self._client.calls)
1038+
1039+
@cached_property
1040+
def channels(self) -> channels.ChannelsResourceWithStreamingResponse:
1041+
from .resources.channels import ChannelsResourceWithStreamingResponse
1042+
1043+
return ChannelsResourceWithStreamingResponse(self._client.channels)
1044+
9411045
@cached_property
9421046
def me(self) -> me.MeResourceWithStreamingResponse:
9431047
"""Who the current key is.
@@ -1047,6 +1151,24 @@ def conversations(self) -> conversations.AsyncConversationsResourceWithStreaming
10471151

10481152
return AsyncConversationsResourceWithStreamingResponse(self._client.conversations)
10491153

1154+
@cached_property
1155+
def calls(self) -> calls.AsyncCallsResourceWithStreamingResponse:
1156+
"""Phone calls from the numbers you hold, driven by your own callback URL.
1157+
1158+
`POST /v3/channels/voice` enables a number for calls, with the callback URL Sent asks what to do with each call on it, and `POST /v3/channels/voice/tokens` mints a short-lived token that lets a user of your app place and receive calls as that number. When a call arrives or a caller presses a key, a signed question is POSTed to the callback URL and the answer decides the call; `POST /v3/channels/voice/{number}/test` checks the URL answers the way we need before a real call reaches it, and `POST /v3/channels/voice/{number}/rotate-secret` replaces the signing secret. The call events themselves (`call.completed` and the rest) arrive through your webhooks.
1159+
1160+
Every call is a record under `/v3/calls`: read it, list its recordings once one is ready, hang it up, start or stop recording, and add, mute or remove conference participants while it is live. A leg to a phone number runs for at most what your balance affords at the destination's rate.
1161+
"""
1162+
from .resources.calls import AsyncCallsResourceWithStreamingResponse
1163+
1164+
return AsyncCallsResourceWithStreamingResponse(self._client.calls)
1165+
1166+
@cached_property
1167+
def channels(self) -> channels.AsyncChannelsResourceWithStreamingResponse:
1168+
from .resources.channels import AsyncChannelsResourceWithStreamingResponse
1169+
1170+
return AsyncChannelsResourceWithStreamingResponse(self._client.channels)
1171+
10501172
@cached_property
10511173
def me(self) -> me.AsyncMeResourceWithStreamingResponse:
10521174
"""Who the current key is.

0 commit comments

Comments
 (0)