docwal 1.0.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.
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ All notable changes to the DocWal Python SDK will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2024-01-10
9
+
10
+ ### Added
11
+ - Initial release of DocWal Python SDK
12
+ - Credentials resource with full CRUD operations
13
+ - Template management (create, list, update, delete)
14
+ - Team member management (invite, list, update roles, deactivate, remove)
15
+ - API key management (generate, regenerate, revoke, info)
16
+ - Batch credential issuance (JSON array and ZIP upload)
17
+ - File upload support for PDF documents
18
+ - Comprehensive error handling with custom exceptions
19
+ - Full documentation with examples
20
+ - Type hints throughout the codebase
21
+
22
+ ### Features
23
+ - Issue single credentials with optional PDF attachments
24
+ - Batch issue up to 1000 credentials at once
25
+ - Batch upload with ZIP files (CSV/JSON + PDFs)
26
+ - List and filter credentials with pagination
27
+ - Revoke credentials with audit trail
28
+ - Resend claim links with configurable expiration
29
+ - Download credential files
30
+ - Manage credential templates with schema validation
31
+ - Team collaboration with role-based permissions
32
+ - Secure API key authentication
33
+
34
+ ### Security
35
+ - API key-based authentication
36
+ - HTTPS-only communication
37
+ - Input validation for all requests
38
+ - Proper error handling without leaking sensitive data
docwal-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 DocWal
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,10 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ include requirements.txt
5
+ recursive-include docwal *.py
6
+ exclude examples/*
7
+ exclude tests/*
8
+ global-exclude __pycache__
9
+ global-exclude *.py[co]
10
+ global-exclude .DS_Store
docwal-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,388 @@
1
+ Metadata-Version: 2.4
2
+ Name: docwal
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for DocWal API - Issue and manage verifiable digital credentials
5
+ Home-page: https://github.com/docwal/docwal-python
6
+ Author: DocWal
7
+ Author-email: support@docwal.com
8
+ Project-URL: Bug Tracker, https://github.com/docwal/docwal-python/issues
9
+ Project-URL: Documentation, https://docs.docwal.com
10
+ Project-URL: Source Code, https://github.com/docwal/docwal-python
11
+ Keywords: docwal credentials verifiable digital education blockchain
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Requires-Python: >=3.7
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: requests>=2.25.0
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: description-content-type
32
+ Dynamic: home-page
33
+ Dynamic: keywords
34
+ Dynamic: license-file
35
+ Dynamic: project-url
36
+ Dynamic: requires-dist
37
+ Dynamic: requires-python
38
+ Dynamic: summary
39
+
40
+ # DocWal Python SDK
41
+
42
+ Official Python SDK for DocWal API - Issue and manage verifiable digital credentials.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install docwal
48
+ ```
49
+
50
+ ## Quick Start
51
+
52
+ ```python
53
+ from docwal import DocWalClient
54
+
55
+ # Initialize client with your API key
56
+ client = DocWalClient(api_key="docwal_live_xxxxx")
57
+
58
+ # Issue a credential
59
+ result = client.credentials.issue(
60
+ template_id="template-123",
61
+ individual_email="student@example.com",
62
+ credential_data={
63
+ "student_name": "John Doe",
64
+ "degree": "Bachelor of Science",
65
+ "major": "Computer Science",
66
+ "graduation_date": "2024-05-15",
67
+ "gpa": "3.8"
68
+ }
69
+ )
70
+
71
+ print(f"Credential issued! Doc ID: {result['doc_id']}")
72
+ print(f"Claim token: {result['claim_token']}")
73
+ ```
74
+
75
+ ## Authentication
76
+
77
+ Get your API key from your DocWal dashboard:
78
+ 1. Login to https://docwal.com
79
+ 2. Navigate to Settings → API Keys
80
+ 3. Click "Generate API Key"
81
+ 4. Copy and store securely
82
+
83
+ **Requirements:**
84
+ - Pilot tier or above
85
+ - Owner or Admin role
86
+
87
+ ## Environment Configuration
88
+
89
+ ```python
90
+ # Production (default)
91
+ client = DocWalClient(api_key="docwal_live_xxxxx")
92
+
93
+ # Staging
94
+ client = DocWalClient(
95
+ api_key="docwal_test_xxxxx",
96
+ base_url="https://sandbox.docwal.com/api"
97
+ )
98
+
99
+ # Custom timeout
100
+ client = DocWalClient(
101
+ api_key="docwal_live_xxxxx",
102
+ timeout=60 # seconds
103
+ )
104
+ ```
105
+
106
+ ## Usage Examples
107
+
108
+ ### Issue Single Credential
109
+
110
+ ```python
111
+ # Basic credential
112
+ result = client.credentials.issue(
113
+ template_id="template-123",
114
+ individual_email="student@example.com",
115
+ credential_data={
116
+ "student_name": "John Doe",
117
+ "degree": "Bachelor of Science",
118
+ "graduation_date": "2024-05-15"
119
+ }
120
+ )
121
+
122
+ # With PDF attachment
123
+ with open("certificate.pdf", "rb") as f:
124
+ result = client.credentials.issue(
125
+ template_id="template-123",
126
+ individual_email="student@example.com",
127
+ credential_data={"student_name": "John Doe"},
128
+ document_file=f,
129
+ claim_token_expires_hours=168 # 7 days
130
+ )
131
+ ```
132
+
133
+ ### Batch Issue Credentials
134
+
135
+ ```python
136
+ credentials_list = [
137
+ {
138
+ "individual_email": "student1@example.com",
139
+ "credential_data": {
140
+ "student_name": "Alice Smith",
141
+ "degree": "Bachelor of Arts",
142
+ "graduation_date": "2024-05-15"
143
+ }
144
+ },
145
+ {
146
+ "individual_email": "student2@example.com",
147
+ "credential_data": {
148
+ "student_name": "Bob Johnson",
149
+ "degree": "Bachelor of Science",
150
+ "graduation_date": "2024-05-15"
151
+ }
152
+ }
153
+ ]
154
+
155
+ result = client.credentials.batch_issue(
156
+ template_id="template-123",
157
+ credentials=credentials_list,
158
+ send_notifications=True
159
+ )
160
+
161
+ print(f"Success: {result['success_count']}/{result['total_rows']}")
162
+ ```
163
+
164
+ ### Batch Upload with ZIP
165
+
166
+ ```python
167
+ # ZIP structure:
168
+ # batch_credentials.zip
169
+ # ├── credentials.csv
170
+ # └── documents/
171
+ # ├── student001.pdf
172
+ # ├── student002.pdf
173
+ # └── student003.pdf
174
+
175
+ with open("batch_credentials.zip", "rb") as f:
176
+ result = client.credentials.batch_upload(
177
+ template_id="template-123",
178
+ file=f,
179
+ send_notifications=True
180
+ )
181
+
182
+ print(f"Processed: {result['total_rows']}")
183
+ print(f"Success: {result['success_count']}")
184
+ print(f"Failed: {result['failure_count']}")
185
+
186
+ for item in result['results']:
187
+ if item['status'] == 'success':
188
+ print(f"Row {item['row']}: {item['doc_id']}")
189
+ else:
190
+ print(f"Row {item['row']}: {item['error']}")
191
+ ```
192
+
193
+ ### List and Get Credentials
194
+
195
+ ```python
196
+ # List all credentials
197
+ credentials = client.credentials.list(limit=50, offset=0)
198
+
199
+ for cred in credentials:
200
+ print(f"{cred['doc_id']}: {cred['template_name']}")
201
+
202
+ # Get specific credential
203
+ credential = client.credentials.get("DOC123456")
204
+ print(f"Issued to: {credential['ownership']['individual_email']}")
205
+ print(f"Status: {'Claimed' if credential['ownership']['is_claimed'] else 'Pending'}")
206
+ ```
207
+
208
+ ### Revoke Credential
209
+
210
+ ```python
211
+ result = client.credentials.revoke(
212
+ doc_id="DOC123456",
213
+ reason="Student expelled for academic misconduct"
214
+ )
215
+ print(result['message'])
216
+ ```
217
+
218
+ ### Resend Claim Link
219
+
220
+ ```python
221
+ result = client.credentials.resend_claim_link(
222
+ doc_id="DOC123456",
223
+ claim_token_expires_hours=168 # 7 days
224
+ )
225
+
226
+ print(f"Sent to: {result['recipient_email']}")
227
+ print(f"Expires: {result['claim_token_expires']}")
228
+ ```
229
+
230
+ ### Download Credential File
231
+
232
+ ```python
233
+ # Download PDF file
234
+ pdf_content = client.credentials.download("DOC123456")
235
+
236
+ with open("credential.pdf", "wb") as f:
237
+ f.write(pdf_content)
238
+ ```
239
+
240
+ ## Template Management
241
+
242
+ ```python
243
+ # List templates
244
+ templates = client.templates.list()
245
+
246
+ # Get template
247
+ template = client.templates.get("template-123")
248
+
249
+ # Create template
250
+ template = client.templates.create(
251
+ name="Bachelor Degree Certificate",
252
+ description="Template for bachelor degree graduation certificates",
253
+ credential_type="certificate",
254
+ schema={
255
+ "student_name": {
256
+ "type": "string",
257
+ "required": True,
258
+ "label": "Student Name"
259
+ },
260
+ "degree": {
261
+ "type": "string",
262
+ "required": True,
263
+ "label": "Degree Program"
264
+ },
265
+ "graduation_date": {
266
+ "type": "date",
267
+ "required": True,
268
+ "label": "Graduation Date"
269
+ }
270
+ },
271
+ version="1.0"
272
+ )
273
+
274
+ # Update template
275
+ client.templates.update(
276
+ "template-123",
277
+ description="Updated description"
278
+ )
279
+
280
+ # Delete template (soft delete)
281
+ client.templates.delete("template-123")
282
+ ```
283
+
284
+ ## API Key Management
285
+
286
+ ```python
287
+ # Generate new API key (Owner/Admin only)
288
+ result = client.api_keys.generate()
289
+ print(f"New API key: {result['api_key']}")
290
+ print("⚠️ Store securely - shown only once!")
291
+
292
+ # Get API key info
293
+ info = client.api_keys.info()
294
+ print(f"Masked key: {info['api_key_masked']}")
295
+ print(f"Created: {info['created_at']}")
296
+ print(f"Last used: {info['last_used_at']}")
297
+
298
+ # Regenerate API key
299
+ result = client.api_keys.regenerate()
300
+ print(f"New API key: {result['api_key']}")
301
+
302
+ # Revoke API key
303
+ client.api_keys.revoke()
304
+ ```
305
+
306
+ ## Team Management
307
+
308
+ ```python
309
+ # List team members
310
+ team = client.team.list()
311
+ print(f"Active members: {team['stats']['active_members']}")
312
+ print(f"Pending invitations: {team['stats']['pending_invitations']}")
313
+
314
+ # Check email before inviting
315
+ check = client.team.check_email("newmember@university.edu")
316
+ if check['recommendation'] == 'add_directly':
317
+ print("User exists - can add directly")
318
+ elif check['recommendation'] == 'send_invitation':
319
+ print("User doesn't exist - must send invitation")
320
+
321
+ # Invite team member
322
+ result = client.team.invite(
323
+ email="newmember@university.edu",
324
+ role="issuer",
325
+ send_email=True
326
+ )
327
+
328
+ # Update member role
329
+ client.team.update_role(
330
+ member_id="member-123",
331
+ role="admin"
332
+ )
333
+
334
+ # Deactivate member
335
+ client.team.deactivate(
336
+ member_id="member-123",
337
+ reason="Employee on leave"
338
+ )
339
+
340
+ # Reactivate member
341
+ client.team.reactivate("member-123")
342
+
343
+ # Remove member permanently
344
+ client.team.remove("member-123")
345
+ ```
346
+
347
+ ## Error Handling
348
+
349
+ ```python
350
+ from docwal import DocWalClient, DocWalError, AuthenticationError, ValidationError
351
+
352
+ client = DocWalClient(api_key="docwal_live_xxxxx")
353
+
354
+ try:
355
+ result = client.credentials.issue(
356
+ template_id="invalid-template",
357
+ individual_email="student@example.com",
358
+ credential_data={}
359
+ )
360
+ except AuthenticationError as e:
361
+ print(f"Authentication failed: {e}")
362
+ print("Check your API key")
363
+ except ValidationError as e:
364
+ print(f"Validation error: {e}")
365
+ print("Check required fields")
366
+ except DocWalError as e:
367
+ print(f"API error: {e}")
368
+ print(f"Status code: {e.status_code}")
369
+ ```
370
+
371
+ ## Rate Limits
372
+
373
+ - **Pilot**: 500 requests/hour
374
+ - **Standard**: 1,000 requests/hour
375
+ - **Enterprise**: Unlimited
376
+
377
+ When rate limit is exceeded, `RateLimitError` is raised.
378
+
379
+ ## Support
380
+
381
+ - **Email**: support@docwal.com
382
+ - **Documentation**: https://docs.docwal.com
383
+ - **API Reference**: https://docwal.com/api/docs
384
+ - **GitHub**: https://github.com/docwal/docwal-python
385
+
386
+ ## License
387
+
388
+ MIT License - see LICENSE file for details.