Skip to content
Open
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
# Change Log
## [4.61.0](https://github.com/plivo/plivo-python/tree/v4.61.0) (2026-05-23)
**Feature - whatsapp_templates, verify_apps, rcs_capability, rcs_assistant_events, verify_session, messages API updates**
- Added `waba_id`, `name`, `category`, `language`, `components`, `allow_category_change` parameters to whatsapp_templates.create (POST /v1/Account/{auth_id}/WhatsApp/Template/{waba_id}/)
- Added `waba_id`, `template_id`, `name`, `category`, `language`, `components`, `allow_category_change` parameters to whatsapp_templates.update (POST /v1/Account/{auth_id}/WhatsApp/Template/{waba_id}/{template_id}/)
- Added `waba_id`, `template_id` parameters to whatsapp_templates.get (GET /v1/Account/{auth_id}/WhatsApp/Template/{waba_id}/{template_id}/)
- Added `waba_id`, `template_name`, `limit`, `offset` parameters to whatsapp_templates.list (GET /v1/Account/{auth_id}/WhatsApp/Template/{waba_id}/)
- Added `waba_id`, `template_id`, `name` parameters to whatsapp_templates.delete (DELETE /v1/Account/{auth_id}/WhatsApp/Template/{waba_id}/{template_id}/)
- Added `name`, `brand_name`, `otp_type`, `otp_length`, `otp_expiry`, `otp_attempts`, `max_validation_attempts`, `sms_channel`, `voice_channel`, `wa_channel`, `waba_id`, `waba_phone_number`, `waba_template_id`, `template_uuid`, `is_default`, `message_redaction`, `enable_fraudshield`, `fs_protection_level`, `customer_app_hash`, `number_pool` parameters to verify_apps.create (POST /v1/Account/{auth_id}/Verify/App/)
- Added `name`, `subaccount`, `limit`, `offset`, `created_at`, `created_at__lt`, `created_at__lte`, `created_at__gt`, `created_at__gte` parameters to verify_apps.list (GET /v1/Account/{auth_id}/Verify/App/)
- GET /v1/Account/{auth_id}/Verify/App/templates/ — verify_apps.list_templates. List default Verify templates available to the account.
- Added `app_uuid` required parameter to verify_apps.get (GET /v1/Account/{auth_id}/Verify/App/{app_uuid}/)
- Added `app_uuid`, `name`, `brand_name`, `otp_type`, `otp_length`, `otp_expiry`, `otp_attempts`, `max_validation_attempts`, `sms_channel`, `voice_channel`, `wa_channel`, `waba_id`, `waba_phone_number`, `waba_template_id`, `template_uuid`, `is_default`, `message_redaction`, `enable_fraudshield`, `fs_protection_level`, `customer_app_hash`, `client` parameters to verify_apps.update (POST /v1/Account/{auth_id}/Verify/App/{app_uuid}/)
- Added `app_uuid` required parameter to verify_apps.delete (DELETE /v1/Account/{auth_id}/Verify/App/{app_uuid}/)
- Added `phone_number`, `agent_uuid` parameters to rcs_capability.check (GET /v1/Account/{auth_id}/RCS/Capability/)
- POST /v1/Account/{auth_id}/RCS/AssistantEvents/ — rcs_assistant_events.create. Send RCS assistant events.
- Added `app_hash`, `brand_name`, `code_length`, `dlt_entity_id`, `dlt_sender_id`, `dlt_template_category`, `dlt_template_id`, `dlt_text`, `dtmf`, `fraud_check`, `text` parameters to verify_session.create (POST /v1/Account/{auth_id}/Verify/Session/)
- Added `content_message` optional parameter to messages.create (POST /v1/Account/{auth_id}/Message/)
- GET /v1/Account/{auth_id}/Message/ — messages.list. Add error_message, message_sent_time, and message_updated_time fields to the list messages response.
- GET /v1/Account/{auth_id}/Message/{record_id}/ — messages.get. Add error_message, message_sent_time, and message_updated_time fields to the get message response.
- Added `number_pool` optional parameter to verify_apps.create (POST /v1/Account/{auth_id}/Verify/App/)

_Source: plivo/api-messaging#630_

## [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
Expand Down
8 changes: 8 additions & 0 deletions examples/rcs_assistant_events_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.rcs_assistant_events.create()

print(response)
18 changes: 18 additions & 0 deletions examples/rcs_capability_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

# Check if a phone number is RCS-enabled
response = client.rcs_capability.check(
phone_number='+14151234567',
agent_uuid='your-agent-uuid', # optional
)

print('API ID:', response.api_id)
print('Phone Number:', response.phone_number)
print('Is RCS Capable:', response.is_capable)
print('Features:', response.features)
print('Message:', response.message)
if response.error:
print('Error:', response.error)
22 changes: 22 additions & 0 deletions examples/verify_apps_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.create(
name='MyVerifyApp',
brand_name='MyBrand',
otp_type='numeric',
otp_length=6,
otp_expiry=300,
otp_attempts=3,
max_validation_attempts=5,
sms_channel=True,
voice_channel=False,
wa_channel=False,
is_default=False,
message_redaction=False,
enable_fraudshield=False,
number_pool='my-number-pool',
)

print(response)
7 changes: 7 additions & 0 deletions examples/verify_apps_delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.delete(app_uuid='your-app-uuid')

print(response)
7 changes: 7 additions & 0 deletions examples/verify_apps_get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.get(app_uuid='your-app-uuid')

print(response)
10 changes: 10 additions & 0 deletions examples/verify_apps_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.list(
limit=20,
offset=0,
)

print(response)
7 changes: 7 additions & 0 deletions examples/verify_apps_list_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.list_templates()

print(response)
12 changes: 12 additions & 0 deletions examples/verify_apps_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.verify_apps.update(
app_uuid='your-app-uuid',
name='UpdatedAppName',
otp_length=4,
sms_channel=True,
)

print(response)
27 changes: 27 additions & 0 deletions examples/verify_session_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
"""
Example: Create a Verify Session (generate OTP)
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

# Minimal creation — no optional params required
response = client.verify_session.create()
print(response)

# Full creation with all optional params
response = client.verify_session.create(
app_hash='android_app_hash_value',
brand_name='MyBrand',
code_length=6,
dlt_entity_id='dlt_entity_id_value',
dlt_sender_id='dlt_sender_id_value',
dlt_template_category='transactional',
dlt_template_id='dlt_template_id_value',
dlt_text='Your OTP is {otp}',
dtmf=1,
fraud_check='medium',
text='Your OTP is {otp}. It is valid for 10 minutes.',
)
print(response)
23 changes: 23 additions & 0 deletions examples/whatsapp_templates_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
"""
Example: Create a WhatsApp message template.
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.whatsapp_templates.create(
waba_id='<waba_id>',
name='my_template',
category='MARKETING',
language='en_US',
components=[
{
'type': 'BODY',
'text': 'Hello, this is a test template.',
}
],
allow_category_change=True,
)

print(response)
15 changes: 15 additions & 0 deletions examples/whatsapp_templates_delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
"""
Example: Delete a WhatsApp template by ID and name.
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.whatsapp_templates.delete(
waba_id='<waba_id>',
template_id='<template_id>',
name='my_template',
)

print(response)
14 changes: 14 additions & 0 deletions examples/whatsapp_templates_get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
"""
Example: Retrieve a WhatsApp template by its ID.
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.whatsapp_templates.get(
waba_id='<waba_id>',
template_id='<template_id>',
)

print(response)
16 changes: 16 additions & 0 deletions examples/whatsapp_templates_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
"""
Example: List WhatsApp templates for a given WABA.
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.whatsapp_templates.list(
waba_id='<waba_id>',
template_name='my_template',
limit=20,
offset=0,
)

print(response)
21 changes: 21 additions & 0 deletions examples/whatsapp_templates_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
"""
Example: Update an existing WhatsApp message template.
"""
import plivo

client = plivo.RestClient(auth_id='YOUR_AUTH_ID', auth_token='YOUR_AUTH_TOKEN')

response = client.whatsapp_templates.update(
waba_id='<waba_id>',
template_id='<template_id>',
category='UTILITY',
components=[
{
'type': 'BODY',
'text': 'Updated template body.',
}
],
)

print(response)
14 changes: 8 additions & 6 deletions plivo/resources/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Messages(PlivoResourceInterface):
dst=[is_iterable(of_type(six.text_type), '<')],
text=[optional(of_type(six.text_type))],
type_=[
optional(all_of(of_type(six.text_type), is_in(('sms', 'mms', 'whatsapp'))))],
optional(all_of(of_type(six.text_type), is_in(('sms', 'mms', 'whatsapp', 'rcs'))))],
url=[optional(is_url())],
method=[optional(of_type(six.text_type))],
log=[optional(of_type_exact(str))],
Expand All @@ -46,7 +46,8 @@ class Messages(PlivoResourceInterface):
location=[optional(is_location())],
dlt_entity_id=[optional(of_type(six.text_type))],
dlt_template_id=[optional(of_type(six.text_type))],
dlt_template_category=[optional(of_type(six.text_type))]
dlt_template_category=[optional(of_type(six.text_type))],
content_message=[optional(of_type_exact(dict))],
)
def create(self,
dst,
Expand All @@ -60,13 +61,14 @@ def create(self,
powerpack_uuid=None,
media_urls=None,
media_ids=None,
message_expiry=None,
message_expiry=None,
template=None,
interactive=None,
location=None,
dlt_entity_id=None,
dlt_template_id=None,
dlt_template_category=None):
dlt_template_category=None,
content_message=None):
if src in dst.split('<'):
raise ValidationError(
'destination number cannot be same as source number')
Expand All @@ -87,7 +89,7 @@ def create(self,
'src parameter not present'
)
if template is not None:
template = template.__dict__
template = template.__dict__
if interactive is not None:
interactive = interactive.__dict__
if location is not None:
Expand Down Expand Up @@ -161,4 +163,4 @@ def list(self,
'GET', ('Message', ),
to_param_dict(self.list, locals()),
response_type=ListMessagesResponseObject,
objects_type=Message)
objects_type=Message)
31 changes: 31 additions & 0 deletions plivo/resources/rcs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from plivo.utils.validators import *

from ..base import PlivoResource, PlivoResourceInterface, ResponseObject
from ..exceptions import *
from ..utils import *


class RcsCapabilityResponse(ResponseObject):
def __init__(self, client, dct):
super(RcsCapabilityResponse, self).__init__(dct)
self.api_id = dct.get('api_id', None)
self.phone_number = dct.get('phone_number', None)
self.is_capable = dct.get('is_capable', None)
self.features = dct.get('features', None)
self.message = dct.get('message', None)
self.error = dct.get('error', None)


class RcsCapability(PlivoResourceInterface):
@validate_args(
phone_number=[of_type(six.text_type)],
agent_uuid=[optional(of_type(six.text_type))],
)
def check(self, phone_number, agent_uuid=None):
return self.client.request(
'GET',
('RCS', 'Capability'),
to_param_dict(self.check, locals()),
response_type=RcsCapabilityResponse,
)
27 changes: 27 additions & 0 deletions plivo/resources/rcs_assistant_events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from plivo.utils.validators import *

from ..base import PlivoResource, PlivoResourceInterface
from ..exceptions import *
from ..utils import *


class RcsAssistantEvent(PlivoResource):
_name = 'RcsAssistantEvent'
_identifier_string = 'api_id'

def delete(self):
raise InvalidRequestError('Cannot delete an RcsAssistantEvent resource')

def update(self):
raise InvalidRequestError('Cannot update an RcsAssistantEvent resource')


class RcsAssistantEvents(PlivoResourceInterface):
_resource_type = RcsAssistantEvent

def create(self, **kwargs):
return self.client.request(
'POST', ('RCS', 'AssistantEvents'),
to_param_dict(self.create, locals()),
)
Loading
Loading