kirimel-python 0.1.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.
- kirimel_python-0.1.0/LICENSE +21 -0
- kirimel_python-0.1.0/PKG-INFO +504 -0
- kirimel_python-0.1.0/README.md +474 -0
- kirimel_python-0.1.0/kirimel/__init__.py +21 -0
- kirimel_python-0.1.0/kirimel/client.py +122 -0
- kirimel_python-0.1.0/kirimel/exceptions.py +38 -0
- kirimel_python-0.1.0/kirimel/http_client.py +128 -0
- kirimel_python-0.1.0/kirimel/resources/__init__.py +437 -0
- kirimel_python-0.1.0/kirimel_python.egg-info/PKG-INFO +504 -0
- kirimel_python-0.1.0/kirimel_python.egg-info/SOURCES.txt +14 -0
- kirimel_python-0.1.0/kirimel_python.egg-info/dependency_links.txt +1 -0
- kirimel_python-0.1.0/kirimel_python.egg-info/requires.txt +7 -0
- kirimel_python-0.1.0/kirimel_python.egg-info/top_level.txt +1 -0
- kirimel_python-0.1.0/pyproject.toml +55 -0
- kirimel_python-0.1.0/setup.cfg +4 -0
- kirimel_python-0.1.0/tests/test_client.py +27 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 KiriMel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kirimel-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official KiriMel Python SDK
|
|
5
|
+
Author-email: KiriMel <support@kirimel.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kirimel/kirimel-python-sdk
|
|
8
|
+
Project-URL: Documentation, https://docs.kirimel.com
|
|
9
|
+
Project-URL: Repository, https://github.com/kirimel/kirimel-python-sdk
|
|
10
|
+
Project-URL: Issues, https://github.com/kirimel/kirimel-python-sdk/issues
|
|
11
|
+
Keywords: kirimel,email,marketing,sdk,api
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: requests>=2.28.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
27
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# KiriMel Python SDK
|
|
32
|
+
|
|
33
|
+
Official Python SDK for KiriMel Email Marketing API.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install kirimel-python
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import kirimel
|
|
45
|
+
|
|
46
|
+
# Initialize the client
|
|
47
|
+
client = kirimel.KiriMel(
|
|
48
|
+
api_key='sk_test_xxx', # Or set KIRIMEL_API_KEY env variable
|
|
49
|
+
base_url='https://api.kirimel.com/v2',
|
|
50
|
+
timeout=30,
|
|
51
|
+
retries=3
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# List campaigns
|
|
55
|
+
campaigns = client.campaigns.list(status='sent', limit=20)
|
|
56
|
+
|
|
57
|
+
# Create a campaign
|
|
58
|
+
campaign = client.campaigns.create({
|
|
59
|
+
'name': 'Welcome Email',
|
|
60
|
+
'subject': 'Welcome to KiriMel!',
|
|
61
|
+
'list_id': 123,
|
|
62
|
+
'template_id': 456
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
# Get campaign statistics
|
|
66
|
+
stats = client.campaigns.stats(campaign['id'])
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Authentication
|
|
70
|
+
|
|
71
|
+
The SDK supports two authentication methods:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Method 1: API Key (recommended)
|
|
75
|
+
client = kirimel.KiriMel(api_key='sk_test_xxx')
|
|
76
|
+
|
|
77
|
+
# Method 2: Environment variable
|
|
78
|
+
# Set KIRIMEL_API_KEY=sk_test_xxx in your environment
|
|
79
|
+
client = kirimel.KiriMel()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Resources
|
|
83
|
+
|
|
84
|
+
### Campaigns
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# List campaigns
|
|
88
|
+
campaigns = client.campaigns.list(limit=20, status='sent')
|
|
89
|
+
|
|
90
|
+
# Get recent campaigns
|
|
91
|
+
recent = client.campaigns.recent()
|
|
92
|
+
|
|
93
|
+
# Get single campaign
|
|
94
|
+
campaign = client.campaigns.get(id)
|
|
95
|
+
|
|
96
|
+
# Create campaign
|
|
97
|
+
campaign = client.campaigns.create({
|
|
98
|
+
'name': 'Summer Sale',
|
|
99
|
+
'subject': '50% Off Everything!',
|
|
100
|
+
'list_id': 123,
|
|
101
|
+
'template_id': 456
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
# Update campaign
|
|
105
|
+
client.campaigns.update(id, {'subject': 'New Subject'})
|
|
106
|
+
|
|
107
|
+
# Delete campaign
|
|
108
|
+
client.campaigns.delete(id)
|
|
109
|
+
|
|
110
|
+
# Duplicate campaign
|
|
111
|
+
duplicate = client.campaigns.duplicate(id)
|
|
112
|
+
|
|
113
|
+
# Schedule campaign
|
|
114
|
+
client.campaigns.schedule(id, '2024-06-01 10:00:00')
|
|
115
|
+
|
|
116
|
+
# Pause campaign
|
|
117
|
+
client.campaigns.pause(id)
|
|
118
|
+
|
|
119
|
+
# Resume campaign
|
|
120
|
+
client.campaigns.resume(id)
|
|
121
|
+
|
|
122
|
+
# Get campaign statistics
|
|
123
|
+
stats = client.campaigns.stats(id)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Subscribers
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# List subscribers for a list
|
|
130
|
+
subscribers = client.subscribers.list(list_id, limit=50)
|
|
131
|
+
|
|
132
|
+
# Get single subscriber
|
|
133
|
+
subscriber = client.subscribers.get(id)
|
|
134
|
+
|
|
135
|
+
# Add subscriber to a list
|
|
136
|
+
subscriber = client.subscribers.create(list_id, {
|
|
137
|
+
'email': 'user@example.com',
|
|
138
|
+
'first_name': 'John',
|
|
139
|
+
'last_name': 'Doe'
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
# Update subscriber
|
|
143
|
+
client.subscribers.update(id, {'first_name': 'Jane'})
|
|
144
|
+
|
|
145
|
+
# Delete subscriber
|
|
146
|
+
client.subscribers.delete(id)
|
|
147
|
+
|
|
148
|
+
# Unsubscribe subscriber
|
|
149
|
+
client.subscribers.unsubscribe(id)
|
|
150
|
+
|
|
151
|
+
# Bulk unsubscribe
|
|
152
|
+
client.subscribers.bulk_unsubscribe([id1, id2, id3])
|
|
153
|
+
|
|
154
|
+
# Bulk delete
|
|
155
|
+
client.subscribers.bulk_delete([id1, id2, id3])
|
|
156
|
+
|
|
157
|
+
# Get subscriber activity
|
|
158
|
+
activity = client.subscribers.activity(id)
|
|
159
|
+
|
|
160
|
+
# Get subscriber statistics
|
|
161
|
+
stats = client.subscribers.stats(id)
|
|
162
|
+
|
|
163
|
+
# Toggle VIP status
|
|
164
|
+
client.subscribers.toggle_vip(id)
|
|
165
|
+
|
|
166
|
+
# Search subscribers
|
|
167
|
+
results = client.subscribers.search('john@example.com')
|
|
168
|
+
|
|
169
|
+
# Add tag
|
|
170
|
+
client.subscribers.add_tag(id, 'premium-customer')
|
|
171
|
+
|
|
172
|
+
# Remove tag
|
|
173
|
+
client.subscribers.remove_tag(id, 'premium-customer')
|
|
174
|
+
|
|
175
|
+
# Import subscribers
|
|
176
|
+
result = client.subscribers.import_subscribers(list_id, {
|
|
177
|
+
'subscribers': [
|
|
178
|
+
{'email': 'user1@example.com', 'first_name': 'User 1'},
|
|
179
|
+
{'email': 'user2@example.com', 'first_name': 'User 2'}
|
|
180
|
+
]
|
|
181
|
+
})
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Lists
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
# List all lists
|
|
188
|
+
lists = client.lists.list()
|
|
189
|
+
|
|
190
|
+
# Get single list
|
|
191
|
+
lst = client.lists.get(id)
|
|
192
|
+
|
|
193
|
+
# Create list
|
|
194
|
+
lst = client.lists.create({
|
|
195
|
+
'name': 'Newsletter Subscribers',
|
|
196
|
+
'description': 'Monthly newsletter'
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
# Update list
|
|
200
|
+
client.lists.update(id, {'name': 'Updated Name'})
|
|
201
|
+
|
|
202
|
+
# Delete list
|
|
203
|
+
client.lists.delete(id)
|
|
204
|
+
|
|
205
|
+
# Get list statistics
|
|
206
|
+
stats = client.lists.stats(id)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Segments
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
# List segments for a list
|
|
213
|
+
segments = client.segments.list(list_id)
|
|
214
|
+
|
|
215
|
+
# Get single segment
|
|
216
|
+
segment = client.segments.get(id)
|
|
217
|
+
|
|
218
|
+
# Create segment
|
|
219
|
+
segment = client.segments.create(list_id, {
|
|
220
|
+
'name': 'Active Subscribers',
|
|
221
|
+
'conditions': [
|
|
222
|
+
{'field': 'status', 'operator': 'equals', 'value': 'active'}
|
|
223
|
+
]
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
# Update segment
|
|
227
|
+
client.segments.update(id, {'name': 'Updated Name'})
|
|
228
|
+
|
|
229
|
+
# Delete segment
|
|
230
|
+
client.segments.delete(id)
|
|
231
|
+
|
|
232
|
+
# Preview segment (without saving)
|
|
233
|
+
preview = client.segments.preview(list_id, [
|
|
234
|
+
{'field': 'status', 'operator': 'equals', 'value': 'active'}
|
|
235
|
+
])
|
|
236
|
+
|
|
237
|
+
# Get segment subscribers
|
|
238
|
+
subscribers = client.segments.subscribers(id)
|
|
239
|
+
|
|
240
|
+
# Refresh segment count
|
|
241
|
+
client.segments.refresh(id)
|
|
242
|
+
|
|
243
|
+
# Get segment build logs
|
|
244
|
+
logs = client.segments.logs(id)
|
|
245
|
+
|
|
246
|
+
# Get segment templates
|
|
247
|
+
templates = client.segments.templates()
|
|
248
|
+
|
|
249
|
+
# Get available fields
|
|
250
|
+
fields = client.segments.fields()
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Templates
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
# List all templates
|
|
257
|
+
templates = client.templates.list(limit=20)
|
|
258
|
+
|
|
259
|
+
# Get single template
|
|
260
|
+
template = client.templates.get(id)
|
|
261
|
+
|
|
262
|
+
# Create template
|
|
263
|
+
template = client.templates.create({
|
|
264
|
+
'name': 'Welcome Email',
|
|
265
|
+
'subject': 'Welcome!',
|
|
266
|
+
'html_content': '<h1>Hello {{name}}</h1>',
|
|
267
|
+
'category': 'transactional'
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
# Update template
|
|
271
|
+
client.templates.update(id, {'name': 'Updated Name'})
|
|
272
|
+
|
|
273
|
+
# Delete template
|
|
274
|
+
client.templates.delete(id)
|
|
275
|
+
|
|
276
|
+
# Duplicate template
|
|
277
|
+
duplicate = client.templates.duplicate(id)
|
|
278
|
+
|
|
279
|
+
# Get templates by category
|
|
280
|
+
templates = client.templates.by_category('newsletter')
|
|
281
|
+
|
|
282
|
+
# Search templates
|
|
283
|
+
results = client.templates.search('welcome')
|
|
284
|
+
|
|
285
|
+
# Get categories
|
|
286
|
+
categories = client.templates.categories()
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Forms
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
# List all forms
|
|
293
|
+
forms = client.forms.list()
|
|
294
|
+
|
|
295
|
+
# Get single form
|
|
296
|
+
form = client.forms.get(id)
|
|
297
|
+
|
|
298
|
+
# Create form
|
|
299
|
+
form = client.forms.create({
|
|
300
|
+
'name': 'Newsletter Signup',
|
|
301
|
+
'list_id': 123,
|
|
302
|
+
'fields': [
|
|
303
|
+
{'name': 'email', 'type': 'email', 'required': True},
|
|
304
|
+
{'name': 'first_name', 'type': 'text', 'required': False}
|
|
305
|
+
]
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
# Update form
|
|
309
|
+
client.forms.update(id, {'name': 'Updated Name'})
|
|
310
|
+
|
|
311
|
+
# Delete form
|
|
312
|
+
client.forms.delete(id)
|
|
313
|
+
|
|
314
|
+
# Duplicate form
|
|
315
|
+
duplicate = client.forms.duplicate(id)
|
|
316
|
+
|
|
317
|
+
# Get form analytics
|
|
318
|
+
analytics = client.forms.analytics(id)
|
|
319
|
+
|
|
320
|
+
# Get form submissions
|
|
321
|
+
submissions = client.forms.submissions(id)
|
|
322
|
+
|
|
323
|
+
# Get embed code
|
|
324
|
+
embed = client.forms.embed(id)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Conversions
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
# List all conversion goals
|
|
331
|
+
conversions = client.conversions.list()
|
|
332
|
+
|
|
333
|
+
# Get single conversion goal
|
|
334
|
+
goal = client.conversions.get(id)
|
|
335
|
+
|
|
336
|
+
# Create conversion goal
|
|
337
|
+
goal = client.conversions.create({
|
|
338
|
+
'name': 'Purchase',
|
|
339
|
+
'event_type': 'purchase',
|
|
340
|
+
'value': 100
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
# Update conversion goal
|
|
344
|
+
client.conversions.update(id, {'name': 'Updated Name'})
|
|
345
|
+
|
|
346
|
+
# Delete conversion goal
|
|
347
|
+
client.conversions.delete(id)
|
|
348
|
+
|
|
349
|
+
# Track a conversion
|
|
350
|
+
client.conversions.track({
|
|
351
|
+
'goal_id': id,
|
|
352
|
+
'subscriber_id': 123,
|
|
353
|
+
'value': 50
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
# Get conversions for a goal
|
|
357
|
+
conversions = client.conversions.conversions(id)
|
|
358
|
+
|
|
359
|
+
# Get ROI report
|
|
360
|
+
roi = client.conversions.roi()
|
|
361
|
+
|
|
362
|
+
# Get funnel analysis
|
|
363
|
+
funnel = client.conversions.funnel(id)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Landing Pages
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
# List all landing pages
|
|
370
|
+
pages = client.landing_pages.list()
|
|
371
|
+
|
|
372
|
+
# Get single landing page
|
|
373
|
+
page = client.landing_pages.get(id)
|
|
374
|
+
|
|
375
|
+
# Create landing page
|
|
376
|
+
page = client.landing_pages.create({
|
|
377
|
+
'name': 'Thank You Page',
|
|
378
|
+
'slug': 'thank-you',
|
|
379
|
+
'html_content': '<h1>Thank you!</h1>'
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
# Update landing page
|
|
383
|
+
client.landing_pages.update(id, {'name': 'Updated Name'})
|
|
384
|
+
|
|
385
|
+
# Delete landing page
|
|
386
|
+
client.landing_pages.delete(id)
|
|
387
|
+
|
|
388
|
+
# Duplicate landing page
|
|
389
|
+
duplicate = client.landing_pages.duplicate(id)
|
|
390
|
+
|
|
391
|
+
# Publish landing page
|
|
392
|
+
client.landing_pages.publish(id)
|
|
393
|
+
|
|
394
|
+
# Unpublish landing page
|
|
395
|
+
client.landing_pages.unpublish(id)
|
|
396
|
+
|
|
397
|
+
# Get landing page analytics
|
|
398
|
+
analytics = client.landing_pages.analytics(id)
|
|
399
|
+
|
|
400
|
+
# Get templates
|
|
401
|
+
templates = client.landing_pages.templates()
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Workflows
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
# List all workflows
|
|
408
|
+
workflows = client.workflows.list()
|
|
409
|
+
|
|
410
|
+
# Get single workflow
|
|
411
|
+
workflow = client.workflows.get(id)
|
|
412
|
+
|
|
413
|
+
# Create workflow
|
|
414
|
+
workflow = client.workflows.create({
|
|
415
|
+
'name': 'Welcome Series',
|
|
416
|
+
'nodes': [...],
|
|
417
|
+
'edges': [...]
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
# Update workflow
|
|
421
|
+
client.workflows.update(id, {'name': 'Updated Name'})
|
|
422
|
+
|
|
423
|
+
# Delete workflow
|
|
424
|
+
client.workflows.delete(id)
|
|
425
|
+
|
|
426
|
+
# Duplicate workflow
|
|
427
|
+
duplicate = client.workflows.duplicate(id)
|
|
428
|
+
|
|
429
|
+
# Activate workflow
|
|
430
|
+
client.workflows.activate(id)
|
|
431
|
+
|
|
432
|
+
# Pause workflow
|
|
433
|
+
client.workflows.pause(id)
|
|
434
|
+
|
|
435
|
+
# Validate workflow
|
|
436
|
+
validation = client.workflows.validate(id)
|
|
437
|
+
|
|
438
|
+
# Get workflow executions
|
|
439
|
+
executions = client.workflows.executions(id)
|
|
440
|
+
|
|
441
|
+
# Get workflow templates
|
|
442
|
+
templates = client.workflows.templates()
|
|
443
|
+
|
|
444
|
+
# Create workflow from template
|
|
445
|
+
workflow = client.workflows.from_template(template_id)
|
|
446
|
+
|
|
447
|
+
# Get available node types
|
|
448
|
+
node_types = client.workflows.node_types()
|
|
449
|
+
|
|
450
|
+
# Get workflow data
|
|
451
|
+
data = client.workflows.get_data(id)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Error Handling
|
|
455
|
+
|
|
456
|
+
```python
|
|
457
|
+
from kirimel import (
|
|
458
|
+
ApiException,
|
|
459
|
+
AuthenticationException,
|
|
460
|
+
RateLimitException,
|
|
461
|
+
ValidationException
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
try:
|
|
465
|
+
campaign = client.campaigns.create(data)
|
|
466
|
+
except AuthenticationException as e:
|
|
467
|
+
# Invalid API key
|
|
468
|
+
print(f"Authentication failed: {e.message}")
|
|
469
|
+
except RateLimitException as e:
|
|
470
|
+
# Too many requests
|
|
471
|
+
print(f"Rate limited. Retry after: {e.retry_after} seconds")
|
|
472
|
+
except ValidationException as e:
|
|
473
|
+
# Invalid data
|
|
474
|
+
print(f"Validation errors: {e.errors}")
|
|
475
|
+
except ApiException as e:
|
|
476
|
+
# General API error
|
|
477
|
+
print(f"API error ({e.status_code}): {e.message}")
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Logging
|
|
481
|
+
|
|
482
|
+
```python
|
|
483
|
+
import logging
|
|
484
|
+
|
|
485
|
+
# Set up logging
|
|
486
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
487
|
+
|
|
488
|
+
# The SDK will use the root logger by default
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## Requirements
|
|
492
|
+
|
|
493
|
+
- Python 3.8 or higher
|
|
494
|
+
- requests >= 2.28.0
|
|
495
|
+
|
|
496
|
+
## License
|
|
497
|
+
|
|
498
|
+
MIT License
|
|
499
|
+
|
|
500
|
+
## Support
|
|
501
|
+
|
|
502
|
+
- Documentation: https://docs.kirimel.com
|
|
503
|
+
- GitHub: https://github.com/hualiglobal/kirimel-python-sdk
|
|
504
|
+
- Issues: https://github.com/hualiglobal/kirimel-python-sdk/issues
|