Skip to content
Merged
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# Change Log
## [4.60.0](https://github.com/plivo/plivo-python/tree/v4.60.0) (2026-04-08)
**Feature - PhoneNumber Compliance API support**
- Added `phone_number_compliance_requirements` resource for discovering compliance requirements by country, number type, and user type
- Added `phone_number_compliance` resource with full CRUD support (create, get, list, update, delete) for compliance applications
- Added `phone_number_compliance_link` resource for bulk linking phone numbers to accepted compliance applications
- Create and update operations support multipart file uploads for compliance documents

## [4.59.6](https://github.com/plivo/plivo-python/tree/v4.59.6) (2026-02-18)
**Feature - Campaign API optional fields support**
- Added `sample3`, `sample4`, `sample5` optional sample message fields to Campaign `create` and `update` methods
Expand Down
1 change: 1 addition & 0 deletions plivo/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
from .multipartycall import MultiPartyCalls, MultiPartyCall, MultiPartyCallParticipant
from .verify import Sessions
from .tollfree_verification import TollfreeVerifications
from .phone_number_compliance import PhoneNumberComplianceRequirements, PhoneNumberComplianceApplications, PhoneNumberComplianceLink
119 changes: 119 additions & 0 deletions plivo/resources/phone_number_compliance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import json
import os
from plivo.base import PlivoResource, PlivoResourceInterface


class PhoneNumberComplianceRequirement(PlivoResource):
_name = 'PhoneNumberComplianceRequirement'
_identifier_string = 'requirement_id'


class PhoneNumberComplianceRequirements(PlivoResourceInterface):
_resource_type = PhoneNumberComplianceRequirement

def get(self, country_iso=None, number_type=None, user_type=None):
# GET /PhoneNumber/Compliance/Requirements
return self.client.request(
'GET',
('PhoneNumber', 'Compliance', 'Requirements'),
dict(country_iso=country_iso, number_type=number_type, user_type=user_type)
)


class PhoneNumberCompliance(PlivoResource):
_name = 'PhoneNumberCompliance'
_identifier_string = 'compliance_id'


class PhoneNumberComplianceApplications(PlivoResourceInterface):
_resource_type = PhoneNumberCompliance

def create(self, data=None, documents=None):
"""
data: dict with keys country_iso, number_type, alias, end_user, documents, callback_url, callback_method
documents: list of local file paths for document uploads
"""
payload, files = _build_compliance_multipart(data, documents)
return self.client.request(
'POST',
('PhoneNumber', 'Compliance'),
payload,
files=files
)

def list(self, limit=None, offset=None, status=None, country_iso=None,
number_type=None, user_type=None, alias=None, expand=None):
params = {}
if limit is not None:
params['limit'] = limit
if offset is not None:
params['offset'] = offset
if status:
params['status'] = status
if country_iso:
params['country_iso'] = country_iso
if number_type:
params['number_type'] = number_type
if user_type:
params['user_type'] = user_type
if alias:
params['alias'] = alias
if expand:
params['expand'] = expand
return self.client.request(
'GET',
('PhoneNumber', 'Compliance'),
params
)

def get(self, compliance_id, expand=None):
params = {}
if expand:
params['expand'] = expand
return self.client.request(
'GET',
('PhoneNumber', 'Compliance', compliance_id),
params
)

def update(self, compliance_id, data=None, documents=None):
payload, files = _build_compliance_multipart(data, documents)
return self.client.request(
'PATCH',
('PhoneNumber', 'Compliance', compliance_id),
payload,
files=files
)

def delete(self, compliance_id):
return self.client.request(
'DELETE',
('PhoneNumber', 'Compliance', compliance_id)
)


class PhoneNumberComplianceLink(PlivoResourceInterface):

def link(self, numbers=None):
"""
numbers: list of dicts, each with 'number' and 'compliance_application_id'
"""
return self.client.request(
'POST',
('PhoneNumber', 'Compliance', 'Link'),
dict(numbers=numbers)
)


def _build_compliance_multipart(data, documents):
payload = {}
files = {}
if data:
payload['data'] = json.dumps(data)
if documents:
for idx, doc_path in enumerate(documents):
field_name = 'documents[{}].file'.format(idx)
files[field_name] = (os.path.basename(doc_path), open(doc_path, 'rb'))
if not files:
files = None
return payload, files
4 changes: 4 additions & 0 deletions plivo/rest/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from plivo.resources.queued_calls import QueuedCalls
from plivo.resources.regulatory_compliance import EndUsers, ComplianceDocumentTypes, ComplianceDocuments, \
ComplianceRequirements, ComplianceApplications
from plivo.resources.phone_number_compliance import PhoneNumberComplianceRequirements, PhoneNumberComplianceApplications, PhoneNumberComplianceLink
from plivo.utils import is_valid_mainaccount, is_valid_subaccount
from plivo.version import __version__
from requests import Request, Session
Expand Down Expand Up @@ -127,6 +128,9 @@ def __init__(self, auth_id=None, auth_token=None, proxies=None, timeout=5):
self.verify_session = Sessions(self)
self.verify_callerids = VerifyCallerids(self)
self.transcriptions = Transcriptions(self)
self.phone_number_compliance_requirements = PhoneNumberComplianceRequirements(self)
self.phone_number_compliance = PhoneNumberComplianceApplications(self)
self.phone_number_compliance_link = PhoneNumberComplianceLink(self)


def __enter__(self):
Expand Down
2 changes: 1 addition & 1 deletion plivo/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
__version__ = '4.59.5'
__version__ = '4.60.0'
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name='plivo',
version='4.59.6',
version='4.60.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',
Expand Down
Loading
Loading