From 1c7986d7e48b252bf0049a9d1e1772fbf0649607 Mon Sep 17 00:00:00 2001 From: Narayana Shanbhogh Date: Sat, 23 May 2026 08:30:52 +0530 Subject: [PATCH] Add bulk_messages.create POST /v1/Account/{auth_id}/Message/Bulk/ --- CHANGELOG.md | 6 +++ examples/bulk_messages_create.py | 18 +++++++ plivo/resources/bulk_messages.py | 47 ++++++++++++++++++ setup.py | 2 +- tests/resources/test_bulk_messages.py | 70 +++++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 examples/bulk_messages_create.py create mode 100644 plivo/resources/bulk_messages.py create mode 100644 tests/resources/test_bulk_messages.py diff --git a/CHANGELOG.md b/CHANGELOG.md index b3bc619d..282f2f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # Change Log +## [4.61.0](https://github.com/plivo/plivo-python/tree/v4.61.0) (2026-05-23) +**Major - bulk_messages.create** +- Added `src`, `dst`, `text`, `type`, `url`, `method`, `log`, `powerpack_uuid` parameters to bulk_messages.create (POST /v1/Account/{auth_id}/Message/Bulk/) + +_Source: plivo/api-messaging#9001_ + ## [4.60.1](https://github.com/plivo/plivo-python/tree/v4.60.1) (2026-04-17) **Bug Fix - PhoneNumber Compliance API** - Fixed Requirements.get() sending None values as query params when not provided diff --git a/examples/bulk_messages_create.py b/examples/bulk_messages_create.py new file mode 100644 index 00000000..12f90942 --- /dev/null +++ b/examples/bulk_messages_create.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +import plivo + +client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN') + +response = client.bulk_messages.create( + src='+14155551234', + dst='+14155550001<+14155550002<+14155550003', + text='Hello from Plivo Bulk Messaging!', + type_='sms', + url='https://example.com/delivery_status', + method='POST', + log=False, +) + +print('API ID:', response.api_id) +print('Message UUIDs:', response.message_uuid) +print('Status:', response.message) \ No newline at end of file diff --git a/plivo/resources/bulk_messages.py b/plivo/resources/bulk_messages.py new file mode 100644 index 00000000..d013c496 --- /dev/null +++ b/plivo/resources/bulk_messages.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +from plivo.utils.validators import * + +from ..base import PlivoResource, PlivoResourceInterface +from ..exceptions import * +from ..utils import * + + +class BulkMessage(PlivoResource): + _name = 'BulkMessage' + _identifier_string = 'message_uuid' + + def delete(self): + raise InvalidRequestError('Cannot delete a BulkMessage resource') + + def update(self): + raise InvalidRequestError('Cannot update a BulkMessage resource') + + +class BulkMessages(PlivoResourceInterface): + _resource_type = BulkMessage + + @validate_args( + src=[of_type(six.text_type)], + dst=[is_iterable(of_type(six.text_type), '<')], + text=[of_type(six.text_type)], + type_=[optional(of_type(six.text_type))], + url=[optional(is_url())], + method=[optional(of_type(six.text_type))], + log=[optional(of_type_exact(bool))], + powerpack_uuid=[optional(of_type(six.text_type))], + ) + def create(self, + src, + dst, + text, + type_=None, + url=None, + method=None, + log=None, + powerpack_uuid=None): + params = to_param_dict(self.create, locals()) + # rename type_ -> type for API + if 'type_' in params: + params['type'] = params.pop('type_') + return self.client.request('POST', ('Message', 'Bulk'), + params) \ No newline at end of file diff --git a/setup.py b/setup.py index 5aa4ad1e..18f23075 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name='plivo', - version='4.60.1', + version='4.61.0', description='A Python SDK to make voice calls & send SMS using Plivo and to generate Plivo XML', long_description=long_description, url='https://github.com/plivo/plivo-python', diff --git a/tests/resources/test_bulk_messages.py b/tests/resources/test_bulk_messages.py new file mode 100644 index 00000000..0125fd41 --- /dev/null +++ b/tests/resources/test_bulk_messages.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +from tests.base import PlivoResourceTestCase + + +class BulkMessageTest(PlivoResourceTestCase): + def test_create_bulk_message(self): + expected_response = { + 'api_id': 'api-id-123', + 'message_uuid': ['uuid-1', 'uuid-2'], + 'message': 'requests queued', + } + self.client.set_expected_response( + status_code=202, data_to_return=expected_response) + + response = self.client.bulk_messages.create( + src='+14155551234', + dst='+14155550001<+14155550002', + text='Hello World') + + self.assertUrlEqual( + self.client.current_request.url, + self.get_url('Message', 'Bulk')) + self.assertEqual(self.client.current_request.method, 'POST') + self.assertEqual(response.message_uuid, expected_response['message_uuid']) + + def test_create_bulk_message_with_optional_params(self): + expected_response = { + 'api_id': 'api-id-456', + 'message_uuid': ['uuid-3'], + 'message': 'requests queued', + } + self.client.set_expected_response( + status_code=202, data_to_return=expected_response) + + response = self.client.bulk_messages.create( + src='+14155551234', + dst='+14155550001', + text='Hello World', + type_='sms', + url='https://example.com/status', + method='POST', + log=False, + powerpack_uuid='some-powerpack-uuid') + + self.assertUrlEqual( + self.client.current_request.url, + self.get_url('Message', 'Bulk')) + self.assertEqual(self.client.current_request.method, 'POST') + self.assertEqual(response.message_uuid, expected_response['message_uuid']) + + def test_create_bulk_message_with_invalid_numbers(self): + expected_response = { + 'api_id': 'api-id-789', + 'message_uuid': ['uuid-4'], + 'message': 'requests queued', + 'invalid_number': ['+1invalid'], + } + self.client.set_expected_response( + status_code=202, data_to_return=expected_response) + + response = self.client.bulk_messages.create( + src='+14155551234', + dst='+14155550001<+1invalid', + text='Hello World') + + self.assertUrlEqual( + self.client.current_request.url, + self.get_url('Message', 'Bulk')) + self.assertEqual(self.client.current_request.method, 'POST') + self.assertEqual(response.invalid_number, expected_response['invalid_number']) \ No newline at end of file