ccai-python 1.0.1__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccai_python-1.2.0/PKG-INFO +530 -0
- ccai_python-1.2.0/README.md +509 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/pyproject.toml +1 -1
- {ccai_python-1.0.1 → ccai_python-1.2.0}/setup.py +2 -2
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/__init__.py +24 -5
- ccai_python-1.2.0/src/ccai_python/brand_service.py +91 -0
- ccai_python-1.2.0/src/ccai_python/campaign_service.py +125 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/ccai.py +92 -25
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/contact_test.py +2 -2
- ccai_python-1.2.0/src/ccai_python/contact_validator_service.py +76 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/email_send.py +5 -5
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/email_service.py +127 -41
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/mms_send.py +7 -6
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/sms/mms.py +28 -12
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/sms/sms.py +81 -22
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/sms_send.py +7 -6
- ccai_python-1.2.0/src/ccai_python/webhook.py +171 -0
- ccai_python-1.2.0/src/ccai_python/webhook_handler_example.py +91 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/webhook_test.py +7 -6
- ccai_python-1.2.0/src/ccai_python.egg-info/PKG-INFO +530 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python.egg-info/SOURCES.txt +6 -3
- {ccai_python-1.0.1 → ccai_python-1.2.0}/tests/test_ccai.py +33 -10
- ccai_python-1.2.0/tests/test_email.py +135 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/tests/test_mms.py +25 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/tests/test_sms.py +100 -3
- ccai_python-1.2.0/tests/test_webhook.py +178 -0
- ccai_python-1.0.1/PKG-INFO +0 -312
- ccai_python-1.0.1/README.md +0 -291
- ccai_python-1.0.1/src/ccai_python/examples/async_example.py +0 -248
- ccai_python-1.0.1/src/ccai_python/examples/basic_example.py +0 -79
- ccai_python-1.0.1/src/ccai_python/webhook.py +0 -110
- ccai_python-1.0.1/src/ccai_python/webhook_handler_example.py +0 -46
- ccai_python-1.0.1/src/ccai_python.egg-info/PKG-INFO +0 -312
- {ccai_python-1.0.1 → ccai_python-1.2.0}/setup.cfg +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/contact_service.py +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python/sms/__init__.py +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python.egg-info/dependency_links.txt +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python.egg-info/requires.txt +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/src/ccai_python.egg-info/top_level.txt +0 -0
- {ccai_python-1.0.1 → ccai_python-1.2.0}/tests/test_contact.py +0 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ccai-python
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: Python client for CloudContactAI API
|
|
5
|
+
Author: CloudContactAI LLC
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudcontactai/ccai-python
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/cloudcontactai/ccai-python/issues
|
|
9
|
+
Keywords: sms,api,client,cloud,contact,ai,cloudcontactai
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.31.0
|
|
19
|
+
Requires-Dist: pydantic>=2.5.0
|
|
20
|
+
Dynamic: requires-python
|
|
21
|
+
|
|
22
|
+
# CCAI Python Client
|
|
23
|
+
|
|
24
|
+
Version: 1.2.0
|
|
25
|
+
|
|
26
|
+
A Python client for interacting with the CloudContactAI API.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install ccai-python
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### SMS
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from ccai_python import CCAI
|
|
40
|
+
|
|
41
|
+
# Initialize the client
|
|
42
|
+
ccai = CCAI(
|
|
43
|
+
client_id="YOUR-CLIENT-ID",
|
|
44
|
+
api_key="YOUR-API-KEY"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Send a single SMS
|
|
48
|
+
response = ccai.sms.send_single(
|
|
49
|
+
first_name="John",
|
|
50
|
+
last_name="Doe",
|
|
51
|
+
phone="+15551234567",
|
|
52
|
+
message="Hello ${first_name}, this is a test message!",
|
|
53
|
+
title="Test Campaign"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
print(f"Message sent with ID: {response.id}")
|
|
57
|
+
|
|
58
|
+
# Send to multiple recipients
|
|
59
|
+
accounts = [
|
|
60
|
+
{"first_name": "John", "last_name": "Doe", "phone": "+15551234567"},
|
|
61
|
+
{"first_name": "Jane", "last_name": "Smith", "phone": "+15559876543"}
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
campaign_response = ccai.sms.send(
|
|
65
|
+
accounts=accounts,
|
|
66
|
+
message="Hello ${first_name} ${last_name}, this is a test message!",
|
|
67
|
+
title="Bulk Test Campaign"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
print(f"Campaign sent with ID: {campaign_response.campaign_id}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### SMS — Template-Controlled Accounts
|
|
74
|
+
|
|
75
|
+
If an account has been configured to enforce template-only messaging, all campaigns must reference a pre-approved template ID. Sending a free-text message to such an account will result in a `422` error.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Send to multiple recipients using a template
|
|
79
|
+
response = ccai.sms.send_with_template(
|
|
80
|
+
accounts=accounts,
|
|
81
|
+
template_id=12345, # the ID of the approved template
|
|
82
|
+
title="My Campaign"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Send to a single recipient using a template
|
|
86
|
+
response = ccai.sms.send_single_with_template(
|
|
87
|
+
first_name="John",
|
|
88
|
+
last_name="Doe",
|
|
89
|
+
phone="+15551234567",
|
|
90
|
+
template_id=12345,
|
|
91
|
+
title="My Campaign"
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The message body is resolved server-side from the template. Variable substitution (e.g. `${firstName}`) is applied automatically using the recipient's account data.
|
|
96
|
+
|
|
97
|
+
### MMS
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from ccai_python import CCAI, Account, SMSOptions
|
|
101
|
+
|
|
102
|
+
# Initialize the client
|
|
103
|
+
ccai = CCAI(
|
|
104
|
+
client_id="YOUR-CLIENT-ID",
|
|
105
|
+
api_key="YOUR-API-KEY"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Define a progress callback
|
|
109
|
+
def track_progress(status):
|
|
110
|
+
print(f"Progress: {status}")
|
|
111
|
+
|
|
112
|
+
# Create options with progress tracking
|
|
113
|
+
options = SMSOptions(
|
|
114
|
+
timeout=60,
|
|
115
|
+
on_progress=track_progress
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Complete MMS workflow (get URL, upload image, send MMS)
|
|
119
|
+
image_path = "path/to/your/image.jpg"
|
|
120
|
+
content_type = "image/jpeg"
|
|
121
|
+
|
|
122
|
+
# Define recipient
|
|
123
|
+
account = Account(
|
|
124
|
+
first_name="John",
|
|
125
|
+
last_name="Doe",
|
|
126
|
+
phone="+15551234567" # Use E.164 format
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Send MMS with image in one step
|
|
130
|
+
response = ccai.mms.send_with_image(
|
|
131
|
+
image_path=image_path,
|
|
132
|
+
content_type=content_type,
|
|
133
|
+
accounts=[account],
|
|
134
|
+
message="Hello ${first_name}, check out this image!",
|
|
135
|
+
title="MMS Campaign Example",
|
|
136
|
+
options=options
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
print(f"MMS sent! Campaign ID: {response.campaign_id}")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Email
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from ccai_python import CCAI, EmailAccount, EmailCampaign
|
|
146
|
+
from datetime import datetime, timedelta
|
|
147
|
+
|
|
148
|
+
# Initialize the client
|
|
149
|
+
ccai = CCAI(
|
|
150
|
+
client_id="YOUR-CLIENT-ID",
|
|
151
|
+
api_key="YOUR-API-KEY"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Send a single email
|
|
155
|
+
response = ccai.email.send_single(
|
|
156
|
+
first_name="John",
|
|
157
|
+
last_name="Doe",
|
|
158
|
+
email="john@example.com",
|
|
159
|
+
subject="Welcome to Our Service",
|
|
160
|
+
message="<p>Hello John,</p><p>Thank you for signing up!</p>",
|
|
161
|
+
sender_email="noreply@yourcompany.com",
|
|
162
|
+
reply_email="support@yourcompany.com",
|
|
163
|
+
sender_name="Your Company",
|
|
164
|
+
title="Welcome Email"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
print(f"Email sent with ID: {response.id}")
|
|
168
|
+
|
|
169
|
+
# Send email campaign to multiple recipients
|
|
170
|
+
accounts = [
|
|
171
|
+
EmailAccount(
|
|
172
|
+
first_name="John",
|
|
173
|
+
last_name="Doe",
|
|
174
|
+
email="john@example.com",
|
|
175
|
+
phone=""
|
|
176
|
+
),
|
|
177
|
+
EmailAccount(
|
|
178
|
+
first_name="Jane",
|
|
179
|
+
last_name="Smith",
|
|
180
|
+
email="jane@example.com",
|
|
181
|
+
phone=""
|
|
182
|
+
)
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
campaign = EmailCampaign(
|
|
186
|
+
subject="Monthly Newsletter",
|
|
187
|
+
title="July 2025 Newsletter",
|
|
188
|
+
message="<h1>Hello ${firstName}!</h1><p>Here's our monthly update...</p>",
|
|
189
|
+
sender_email="newsletter@yourcompany.com",
|
|
190
|
+
reply_email="support@yourcompany.com",
|
|
191
|
+
sender_name="Your Company Newsletter",
|
|
192
|
+
accounts=accounts
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
response = ccai.email.send_campaign(campaign)
|
|
196
|
+
print(f"Email campaign sent: {response}")
|
|
197
|
+
|
|
198
|
+
# Schedule an email for future delivery
|
|
199
|
+
tomorrow = datetime.now() + timedelta(days=1)
|
|
200
|
+
tomorrow = tomorrow.replace(hour=10, minute=0, second=0, microsecond=0)
|
|
201
|
+
|
|
202
|
+
scheduled_campaign = EmailCampaign(
|
|
203
|
+
subject="Scheduled Email",
|
|
204
|
+
title="Future Email",
|
|
205
|
+
message="<p>This email was scheduled in advance!</p>",
|
|
206
|
+
sender_email="scheduled@yourcompany.com",
|
|
207
|
+
reply_email="support@yourcompany.com",
|
|
208
|
+
sender_name="Your Company",
|
|
209
|
+
accounts=[accounts[0]],
|
|
210
|
+
scheduled_timestamp=tomorrow.isoformat(),
|
|
211
|
+
scheduled_timezone="America/New_York"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
response = ccai.email.send_campaign(scheduled_campaign)
|
|
215
|
+
print(f"Email scheduled: {response}")
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Contacts
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from ccai_python import CCAI
|
|
222
|
+
|
|
223
|
+
# Initialize the client
|
|
224
|
+
ccai = CCAI(
|
|
225
|
+
client_id="YOUR-CLIENT-ID",
|
|
226
|
+
api_key="YOUR-API-KEY"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Set do not text status using contact ID
|
|
230
|
+
response = ccai.contact.set_do_not_text(
|
|
231
|
+
do_not_text=True,
|
|
232
|
+
contact_id="your-contact-id"
|
|
233
|
+
)
|
|
234
|
+
print(f"Contact {response.contact_id} do not text set to {response.do_not_text}")
|
|
235
|
+
|
|
236
|
+
# Set do not text status using phone number
|
|
237
|
+
response = ccai.contact.set_do_not_text(
|
|
238
|
+
do_not_text=True,
|
|
239
|
+
phone="+15551234567"
|
|
240
|
+
)
|
|
241
|
+
print(f"Contact {response.contact_id} ({response.phone}) do not text set to {response.do_not_text}")
|
|
242
|
+
|
|
243
|
+
# Remove do not text status from a contact
|
|
244
|
+
response = ccai.contact.set_do_not_text(
|
|
245
|
+
do_not_text=False,
|
|
246
|
+
contact_id="your-contact-id"
|
|
247
|
+
)
|
|
248
|
+
print(f"Contact {response.contact_id} do not text removed: {response.do_not_text}")
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Contact Validator
|
|
252
|
+
|
|
253
|
+
Validate email addresses and phone numbers.
|
|
254
|
+
|
|
255
|
+
> Bulk endpoints accept up to 50 contacts per request and are processed server-side in chunks.
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
from ccai_python import CCAI
|
|
259
|
+
|
|
260
|
+
ccai = CCAI(
|
|
261
|
+
client_id="YOUR-CLIENT-ID",
|
|
262
|
+
api_key="YOUR-API-KEY"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Validate a single email
|
|
266
|
+
email_result = ccai.contact_validator.validate_email("user@example.com")
|
|
267
|
+
print(email_result.status) # "valid" | "invalid" | "risky"
|
|
268
|
+
print(email_result.metadata.get("safe_to_send")) # True | False
|
|
269
|
+
|
|
270
|
+
# Validate multiple emails (up to 50, processed server-side in chunks)
|
|
271
|
+
bulk_emails = ccai.contact_validator.validate_emails(["user@example.com", "bad@invalid.xyz"])
|
|
272
|
+
print(bulk_emails.summary.model_dump()) # {"total": 2, "valid": 1, "invalid": 1, "risky": 0, "landline": 0}
|
|
273
|
+
|
|
274
|
+
# Validate a single phone number
|
|
275
|
+
phone_result = ccai.contact_validator.validate_phone("+15551234567", country_code="US")
|
|
276
|
+
print(phone_result.status) # "valid" | "invalid" | "landline"
|
|
277
|
+
print(phone_result.metadata.get("carrier_type")) # "mobile" | "landline" | "voip"
|
|
278
|
+
|
|
279
|
+
# Validate multiple phone numbers (up to 50, processed server-side in chunks)
|
|
280
|
+
bulk_phones = ccai.contact_validator.validate_phones([
|
|
281
|
+
{"phone": "+15551234567"},
|
|
282
|
+
{"phone": "+15559876543", "countryCode": "US"}
|
|
283
|
+
])
|
|
284
|
+
print(bulk_phones.summary.model_dump()) # {"total": 2, "valid": 1, "invalid": 0, "risky": 0, "landline": 1}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Webhooks
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
from ccai_python import CCAI, WebhookConfig, WebhookEventType
|
|
291
|
+
|
|
292
|
+
# Initialize the client
|
|
293
|
+
ccai = CCAI(
|
|
294
|
+
client_id="YOUR-CLIENT-ID",
|
|
295
|
+
api_key="YOUR-API-KEY"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Example 1: Register a webhook with auto-generated secret
|
|
299
|
+
# If secret is not provided, the server will auto-generate one
|
|
300
|
+
config = WebhookConfig(
|
|
301
|
+
url="https://your-domain.com/api/ccai-webhook",
|
|
302
|
+
events=[WebhookEventType.MESSAGE_SENT, WebhookEventType.MESSAGE_RECEIVED]
|
|
303
|
+
# secret not provided - server will auto-generate and return it
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
webhook = ccai.webhook.register(config)
|
|
307
|
+
print(f"Webhook registered with ID: {webhook.id}")
|
|
308
|
+
print(f"Auto-generated Secret: {webhook.secretKey}")
|
|
309
|
+
|
|
310
|
+
# Example 2: Register a webhook with a custom secret
|
|
311
|
+
config_custom = WebhookConfig(
|
|
312
|
+
url="https://your-domain.com/api/ccai-webhook-v2",
|
|
313
|
+
events=[WebhookEventType.MESSAGE_SENT, WebhookEventType.MESSAGE_RECEIVED],
|
|
314
|
+
secret="your-custom-secret-key"
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
webhook_custom = ccai.webhook.register(config_custom)
|
|
318
|
+
print(f"Webhook with custom secret registered: {webhook_custom.id}")
|
|
319
|
+
|
|
320
|
+
# List all webhooks
|
|
321
|
+
webhooks = ccai.webhook.list()
|
|
322
|
+
print(f"Found {len(webhooks)} webhooks")
|
|
323
|
+
|
|
324
|
+
# Update a webhook
|
|
325
|
+
updated_webhook = ccai.webhook.update(webhook.id, {
|
|
326
|
+
"url": "https://your-domain.com/api/ccai-webhook-v3"
|
|
327
|
+
})
|
|
328
|
+
print(f"Webhook updated: {updated_webhook.url}")
|
|
329
|
+
|
|
330
|
+
# Delete a webhook
|
|
331
|
+
result = ccai.webhook.delete(webhook.id)
|
|
332
|
+
print(f"Webhook deleted: {result}")
|
|
333
|
+
|
|
334
|
+
# Verify webhook signature in your handler
|
|
335
|
+
def verify_and_handle_webhook(signature, client_id, event_hash, secret):
|
|
336
|
+
if ccai.webhook.verify_signature(signature, client_id, event_hash, secret):
|
|
337
|
+
print(f"Valid webhook signature verified")
|
|
338
|
+
else:
|
|
339
|
+
print("Invalid signature")
|
|
340
|
+
|
|
341
|
+
# Create a webhook handler for web frameworks
|
|
342
|
+
def handle_event(event):
|
|
343
|
+
if event.event_type == WebhookEventType.MESSAGE_SENT:
|
|
344
|
+
print(f"Message sent: {event.data.get('Message')} to {event.data.get('To')}")
|
|
345
|
+
elif event.event_type == WebhookEventType.MESSAGE_RECEIVED:
|
|
346
|
+
print(f"Message received: {event.data.get('Message')} from {event.data.get('From')}")
|
|
347
|
+
|
|
348
|
+
webhook_handler = ccai.webhook.create_handler({'on_event': handle_event})
|
|
349
|
+
|
|
350
|
+
# Use with Flask
|
|
351
|
+
import os
|
|
352
|
+
import json
|
|
353
|
+
from flask import Flask, request, jsonify
|
|
354
|
+
|
|
355
|
+
app = Flask(__name__)
|
|
356
|
+
|
|
357
|
+
@app.route('/api/ccai-webhook', methods=['POST'])
|
|
358
|
+
def handle_webhook():
|
|
359
|
+
signature = request.headers.get('X-CCAI-Signature', '')
|
|
360
|
+
body = request.get_data(as_text=True)
|
|
361
|
+
secret = 'your-webhook-secret-key' # Use the secret from webhook registration
|
|
362
|
+
|
|
363
|
+
# Parse payload to get client_id and event_hash
|
|
364
|
+
payload = json.loads(body)
|
|
365
|
+
client_id = os.getenv('CCAI_CLIENT_ID')
|
|
366
|
+
event_hash = payload.get('eventHash', '')
|
|
367
|
+
|
|
368
|
+
# Verify signature
|
|
369
|
+
if not ccai.webhook.verify_signature(signature, client_id, event_hash, secret):
|
|
370
|
+
return jsonify({"error": "Invalid signature"}), 401
|
|
371
|
+
|
|
372
|
+
# Process webhook
|
|
373
|
+
result = webhook_handler(payload)
|
|
374
|
+
return jsonify(result)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Brands
|
|
378
|
+
|
|
379
|
+
Register and manage brands for TCR (The Campaign Registry) business verification.
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
from ccai_python import CCAI
|
|
383
|
+
|
|
384
|
+
ccai = CCAI(
|
|
385
|
+
client_id="YOUR-CLIENT-ID",
|
|
386
|
+
api_key="YOUR-API-KEY"
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# Create a brand
|
|
390
|
+
brand = ccai.brands.create({
|
|
391
|
+
"legalCompanyName": "Collect.org Inc.",
|
|
392
|
+
"dba": "Collect",
|
|
393
|
+
"entityType": "NON_PROFIT",
|
|
394
|
+
"taxId": "123456789",
|
|
395
|
+
"taxIdCountry": "US",
|
|
396
|
+
"country": "US",
|
|
397
|
+
"verticalType": "NON_PROFIT",
|
|
398
|
+
"websiteUrl": "https://www.collect.org",
|
|
399
|
+
"street": "123 Main Street",
|
|
400
|
+
"city": "San Francisco",
|
|
401
|
+
"state": "CA",
|
|
402
|
+
"postalCode": "94105",
|
|
403
|
+
"contactFirstName": "Jane",
|
|
404
|
+
"contactLastName": "Doe",
|
|
405
|
+
"contactEmail": "jane@collect.org",
|
|
406
|
+
"contactPhone": "+14155551234",
|
|
407
|
+
})
|
|
408
|
+
print(f"Brand created with ID: {brand['id']}")
|
|
409
|
+
|
|
410
|
+
# Get a brand by ID
|
|
411
|
+
fetched = ccai.brands.get(brand["id"])
|
|
412
|
+
print(f"Website match score: {fetched.get('websiteMatchScore')}")
|
|
413
|
+
|
|
414
|
+
# List all brands for the account
|
|
415
|
+
brands = ccai.brands.list()
|
|
416
|
+
print(f"Found {len(brands)} brand(s)")
|
|
417
|
+
|
|
418
|
+
# Update a brand (partial update)
|
|
419
|
+
updated = ccai.brands.update(brand["id"], {
|
|
420
|
+
"street": "456 Oak Avenue",
|
|
421
|
+
"city": "Los Angeles",
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
# Delete a brand
|
|
425
|
+
ccai.brands.delete(brand["id"])
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
#### Entity Types
|
|
429
|
+
|
|
430
|
+
`PRIVATE_PROFIT`, `PUBLIC_PROFIT`, `NON_PROFIT`, `GOVERNMENT`, `SOLE_PROPRIETOR`
|
|
431
|
+
|
|
432
|
+
> Note: `PUBLIC_PROFIT` entities require `stockSymbol` and `stockExchange` fields.
|
|
433
|
+
|
|
434
|
+
#### Vertical Types
|
|
435
|
+
|
|
436
|
+
`AUTOMOTIVE`, `AGRICULTURE`, `BANKING`, `COMMUNICATION`, `CONSTRUCTION`, `EDUCATION`, `ENERGY`, `ENTERTAINMENT`, `GOVERNMENT`, `HEALTHCARE`, `HOSPITALITY`, `INSURANCE`, `LEGAL`, `MANUFACTURING`, `NON_PROFIT`, `PROFESSIONAL`, `REAL_ESTATE`, `RETAIL`, `TECHNOLOGY`, `TRANSPORTATION`
|
|
437
|
+
|
|
438
|
+
### Campaigns
|
|
439
|
+
|
|
440
|
+
Register and manage campaigns for TCR (The Campaign Registry) carrier vetting. Each campaign must be linked to a verified brand.
|
|
441
|
+
|
|
442
|
+
```python
|
|
443
|
+
from ccai_python import CCAI
|
|
444
|
+
|
|
445
|
+
ccai = CCAI(
|
|
446
|
+
client_id="YOUR-CLIENT-ID",
|
|
447
|
+
api_key="YOUR-API-KEY"
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
# Create a campaign
|
|
451
|
+
campaign = ccai.campaigns.create({
|
|
452
|
+
"brandId": 1,
|
|
453
|
+
"useCase": "MIXED",
|
|
454
|
+
"subUseCases": ["CUSTOMER_CARE", "TWO_FACTOR_AUTHENTICATION", "ACCOUNT_NOTIFICATION"],
|
|
455
|
+
"description": "Security codes and support messaging.",
|
|
456
|
+
"messageFlow": "Users opt-in via signup form at https://example.com/signup",
|
|
457
|
+
"termsLink": "https://example.com/terms",
|
|
458
|
+
"privacyLink": "https://example.com/privacy",
|
|
459
|
+
"hasEmbeddedLinks": True,
|
|
460
|
+
"hasEmbeddedPhone": False,
|
|
461
|
+
"isAgeGated": False,
|
|
462
|
+
"isDirectLending": False,
|
|
463
|
+
"optInKeywords": ["START"],
|
|
464
|
+
"optInMessage": "Welcome! Reply STOP to cancel.",
|
|
465
|
+
"optInProofUrl": "https://example.com/opt-in-proof.png",
|
|
466
|
+
"helpKeywords": ["HELP"],
|
|
467
|
+
"helpMessage": "For HELP email support@example.com.",
|
|
468
|
+
"optOutKeywords": ["STOP"],
|
|
469
|
+
"optOutMessage": "STOP received. You are unsubscribed.",
|
|
470
|
+
"sampleMessages": [
|
|
471
|
+
"Your code is 554321. Reply STOP to cancel.",
|
|
472
|
+
"Your ticket has been updated. Reply HELP for info."
|
|
473
|
+
]
|
|
474
|
+
})
|
|
475
|
+
print(f"Campaign created with ID: {campaign['id']}")
|
|
476
|
+
|
|
477
|
+
# Get a campaign by ID
|
|
478
|
+
fetched = ccai.campaigns.get(campaign["id"])
|
|
479
|
+
|
|
480
|
+
# List all campaigns for the account
|
|
481
|
+
campaigns = ccai.campaigns.list()
|
|
482
|
+
print(f"Found {len(campaigns)} campaign(s)")
|
|
483
|
+
|
|
484
|
+
# Update a campaign (partial update)
|
|
485
|
+
updated = ccai.campaigns.update(campaign["id"], {
|
|
486
|
+
"description": "Updated description."
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
# Delete a campaign
|
|
490
|
+
ccai.campaigns.delete(campaign["id"])
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Use Cases
|
|
494
|
+
|
|
495
|
+
`TWO_FACTOR_AUTHENTICATION`, `ACCOUNT_NOTIFICATION`, `CUSTOMER_CARE`, `DELIVERY_NOTIFICATION`, `FRAUD_ALERT`, `HIGHER_EDUCATION`, `LOW_VOLUME_MIXED`, `MARKETING`, `MIXED`, `POLLING_VOTING`, `PUBLIC_SERVICE_ANNOUNCEMENT`, `SECURITY_ALERT`
|
|
496
|
+
|
|
497
|
+
> Note: `MIXED` and `LOW_VOLUME_MIXED` campaigns require 2–3 `subUseCases`.
|
|
498
|
+
|
|
499
|
+
> `termsLink` and `privacyLink` are optional fields on the campaign dict.
|
|
500
|
+
|
|
501
|
+
#### Sub-Use Cases
|
|
502
|
+
|
|
503
|
+
`TWO_FACTOR_AUTHENTICATION`, `ACCOUNT_NOTIFICATION`, `CUSTOMER_CARE`, `DELIVERY_NOTIFICATION`, `FRAUD_ALERT`, `MARKETING`, `POLLING_VOTING`
|
|
504
|
+
|
|
505
|
+
## Features
|
|
506
|
+
|
|
507
|
+
- Send SMS messages to single or multiple recipients
|
|
508
|
+
- Send MMS messages with images
|
|
509
|
+
- Send Email campaigns with HTML content
|
|
510
|
+
- Schedule emails for future delivery
|
|
511
|
+
- Brand registration and management for TCR verification
|
|
512
|
+
- Campaign registration and management for TCR carrier vetting
|
|
513
|
+
- Webhook management (register, update, list, delete)
|
|
514
|
+
- Webhook event handling for web frameworks
|
|
515
|
+
- Validate email addresses (valid/invalid/risky) and phone numbers (valid/invalid/landline)
|
|
516
|
+
- Upload images to S3 with signed URLs
|
|
517
|
+
- Variable substitution in messages
|
|
518
|
+
- Progress tracking callbacks
|
|
519
|
+
- Type hints for better IDE integration
|
|
520
|
+
- Comprehensive error handling
|
|
521
|
+
|
|
522
|
+
## Requirements
|
|
523
|
+
|
|
524
|
+
- Python 3.10 or higher
|
|
525
|
+
- `requests` library
|
|
526
|
+
- `pydantic` library
|
|
527
|
+
|
|
528
|
+
## License
|
|
529
|
+
|
|
530
|
+
MIT
|