Skip to content

Commit f35530f

Browse files
Koushik SKclaude
andcommitted
feat: add PhoneNumber Compliance API support
Add new regulatory compliance APIs under PhoneNumber/Compliance/ path: - Requirements API (GET) for discovering compliance requirements - Compliance Applications API (POST, GET, LIST, PATCH, DELETE) - Number Linking API (POST) for bulk linking numbers to applications Includes multipart form-data support for document file uploads with indexed file fields (documents[N].file) and JSON data field. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a0cd323 commit f35530f

3 files changed

Lines changed: 124 additions & 0 deletions

File tree

plivo/resources/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@
2222
from .multipartycall import MultiPartyCalls, MultiPartyCall, MultiPartyCallParticipant
2323
from .verify import Sessions
2424
from .tollfree_verification import TollfreeVerifications
25+
from .phone_number_compliance import PhoneNumberComplianceRequirements, PhoneNumberComplianceApplications, PhoneNumberComplianceLink
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import json
2+
import os
3+
from plivo.base import PlivoResource, PlivoResourceInterface
4+
5+
6+
class PhoneNumberComplianceRequirement(PlivoResource):
7+
_name = 'PhoneNumberComplianceRequirement'
8+
_identifier_string = 'requirement_id'
9+
10+
11+
class PhoneNumberComplianceRequirements(PlivoResourceInterface):
12+
_resource_type = PhoneNumberComplianceRequirement
13+
14+
def get(self, country_iso=None, number_type=None, user_type=None):
15+
# GET /PhoneNumber/Compliance/Requirements
16+
return self.client.request(
17+
'GET',
18+
('PhoneNumber', 'Compliance', 'Requirements'),
19+
dict(country_iso=country_iso, number_type=number_type, user_type=user_type)
20+
)
21+
22+
23+
class PhoneNumberCompliance(PlivoResource):
24+
_name = 'PhoneNumberCompliance'
25+
_identifier_string = 'compliance_id'
26+
27+
28+
class PhoneNumberComplianceApplications(PlivoResourceInterface):
29+
_resource_type = PhoneNumberCompliance
30+
31+
def create(self, data=None, documents=None):
32+
"""
33+
data: dict with keys country_iso, number_type, alias, end_user, documents, callback_url, callback_method
34+
documents: list of local file paths for document uploads
35+
"""
36+
payload, files = _build_compliance_multipart(data, documents)
37+
return self.client.request(
38+
'POST',
39+
('PhoneNumber', 'Compliance'),
40+
payload,
41+
files=files
42+
)
43+
44+
def list(self, limit=None, offset=None, status=None, country_iso=None,
45+
number_type=None, user_type=None, alias=None, expand=None):
46+
params = {}
47+
if limit is not None:
48+
params['limit'] = limit
49+
if offset is not None:
50+
params['offset'] = offset
51+
if status:
52+
params['status'] = status
53+
if country_iso:
54+
params['country_iso'] = country_iso
55+
if number_type:
56+
params['number_type'] = number_type
57+
if user_type:
58+
params['user_type'] = user_type
59+
if alias:
60+
params['alias'] = alias
61+
if expand:
62+
params['expand'] = expand
63+
return self.client.request(
64+
'GET',
65+
('PhoneNumber', 'Compliance'),
66+
params
67+
)
68+
69+
def get(self, compliance_id, expand=None):
70+
params = {}
71+
if expand:
72+
params['expand'] = expand
73+
return self.client.request(
74+
'GET',
75+
('PhoneNumber', 'Compliance', compliance_id),
76+
params
77+
)
78+
79+
def update(self, compliance_id, data=None, documents=None):
80+
payload, files = _build_compliance_multipart(data, documents)
81+
return self.client.request(
82+
'PATCH',
83+
('PhoneNumber', 'Compliance', compliance_id),
84+
payload,
85+
files=files
86+
)
87+
88+
def delete(self, compliance_id):
89+
return self.client.request(
90+
'DELETE',
91+
('PhoneNumber', 'Compliance', compliance_id)
92+
)
93+
94+
95+
class PhoneNumberComplianceLink(PlivoResourceInterface):
96+
97+
def link(self, numbers=None):
98+
"""
99+
numbers: list of dicts, each with 'number' and 'compliance_application_id'
100+
"""
101+
return self.client.request(
102+
'POST',
103+
('PhoneNumber', 'Compliance', 'Link'),
104+
dict(numbers=numbers)
105+
)
106+
107+
108+
def _build_compliance_multipart(data, documents):
109+
payload = {}
110+
files = {}
111+
if data:
112+
payload['data'] = json.dumps(data)
113+
if documents:
114+
for idx, doc_path in enumerate(documents):
115+
field_name = 'documents[{}].file'.format(idx)
116+
files[field_name] = (os.path.basename(doc_path), open(doc_path, 'rb'))
117+
if not files:
118+
files = None
119+
return payload, files

plivo/rest/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from plivo.resources.queued_calls import QueuedCalls
2525
from plivo.resources.regulatory_compliance import EndUsers, ComplianceDocumentTypes, ComplianceDocuments, \
2626
ComplianceRequirements, ComplianceApplications
27+
from plivo.resources.phone_number_compliance import PhoneNumberComplianceRequirements, PhoneNumberComplianceApplications, PhoneNumberComplianceLink
2728
from plivo.utils import is_valid_mainaccount, is_valid_subaccount
2829
from plivo.version import __version__
2930
from requests import Request, Session
@@ -127,6 +128,9 @@ def __init__(self, auth_id=None, auth_token=None, proxies=None, timeout=5):
127128
self.verify_session = Sessions(self)
128129
self.verify_callerids = VerifyCallerids(self)
129130
self.transcriptions = Transcriptions(self)
131+
self.phone_number_compliance_requirements = PhoneNumberComplianceRequirements(self)
132+
self.phone_number_compliance = PhoneNumberComplianceApplications(self)
133+
self.phone_number_compliance_link = PhoneNumberComplianceLink(self)
130134

131135

132136
def __enter__(self):

0 commit comments

Comments
 (0)