Skip to main content

Official Python SDK for DocWal API - Issue and manage verifiable digital credentials

Project description

DocWal Python SDK

Official Python SDK for DocWal API - Issue and manage verifiable digital credentials.

Installation

pip install docwal

Quick Start

from docwal import DocWalClient

# Initialize client with your API key
client = DocWalClient(api_key="docwal_live_xxxxx")

# Issue a credential
result = client.credentials.issue(
    template_id="template-123",
    individual_email="student@example.com",
    credential_data={
        "student_name": "John Doe",
        "degree": "Bachelor of Science",
        "major": "Computer Science",
        "graduation_date": "2024-05-15",
        "gpa": "3.8"
    }
)

print(f"Credential issued! Doc ID: {result['doc_id']}")
print(f"Claim token: {result['claim_token']}")

Authentication

Get your API key from your DocWal dashboard:

  1. Login to https://docwal.com
  2. Navigate to Settings → API Keys
  3. Click "Generate API Key"
  4. Copy and store securely

Requirements:

  • Pilot tier or above
  • Owner or Admin role

Environment Configuration

# Production (default)
client = DocWalClient(api_key="docwal_live_xxxxx")

# Staging
client = DocWalClient(
    api_key="docwal_test_xxxxx",
    base_url="https://sandbox.docwal.com/api"
)

# Custom timeout
client = DocWalClient(
    api_key="docwal_live_xxxxx",
    timeout=60  # seconds
)

Usage Examples

Issue Single Credential

# Basic credential
result = client.credentials.issue(
    template_id="template-123",
    individual_email="student@example.com",
    credential_data={
        "student_name": "John Doe",
        "degree": "Bachelor of Science",
        "graduation_date": "2024-05-15"
    }
)

# With PDF attachment
with open("certificate.pdf", "rb") as f:
    result = client.credentials.issue(
        template_id="template-123",
        individual_email="student@example.com",
        credential_data={"student_name": "John Doe"},
        document_file=f,
        claim_token_expires_hours=168  # 7 days
    )

Batch Issue Credentials

credentials_list = [
    {
        "individual_email": "student1@example.com",
        "credential_data": {
            "student_name": "Alice Smith",
            "degree": "Bachelor of Arts",
            "graduation_date": "2024-05-15"
        }
    },
    {
        "individual_email": "student2@example.com",
        "credential_data": {
            "student_name": "Bob Johnson",
            "degree": "Bachelor of Science",
            "graduation_date": "2024-05-15"
        }
    }
]

result = client.credentials.batch_issue(
    template_id="template-123",
    credentials=credentials_list,
    send_notifications=True
)

print(f"Success: {result['success_count']}/{result['total_rows']}")

Batch Upload with ZIP

# ZIP structure:
# batch_credentials.zip
# ├── credentials.csv
# └── documents/
#     ├── student001.pdf
#     ├── student002.pdf
#     └── student003.pdf

with open("batch_credentials.zip", "rb") as f:
    result = client.credentials.batch_upload(
        template_id="template-123",
        file=f,
        send_notifications=True
    )

print(f"Processed: {result['total_rows']}")
print(f"Success: {result['success_count']}")
print(f"Failed: {result['failure_count']}")

for item in result['results']:
    if item['status'] == 'success':
        print(f"Row {item['row']}: {item['doc_id']}")
    else:
        print(f"Row {item['row']}: {item['error']}")

List and Get Credentials

# List all credentials
credentials = client.credentials.list(limit=50, offset=0)

for cred in credentials:
    print(f"{cred['doc_id']}: {cred['template_name']}")

# Get specific credential
credential = client.credentials.get("DOC123456")
print(f"Issued to: {credential['ownership']['individual_email']}")
print(f"Status: {'Claimed' if credential['ownership']['is_claimed'] else 'Pending'}")

Revoke Credential

result = client.credentials.revoke(
    doc_id="DOC123456",
    reason="Student expelled for academic misconduct"
)
print(result['message'])

Resend Claim Link

result = client.credentials.resend_claim_link(
    doc_id="DOC123456",
    claim_token_expires_hours=168  # 7 days
)

print(f"Sent to: {result['recipient_email']}")
print(f"Expires: {result['claim_token_expires']}")

Download Credential File

# Download PDF file
pdf_content = client.credentials.download("DOC123456")

with open("credential.pdf", "wb") as f:
    f.write(pdf_content)

Template Management

# List templates
templates = client.templates.list()

# Get template
template = client.templates.get("template-123")

# Create template
template = client.templates.create(
    name="Bachelor Degree Certificate",
    description="Template for bachelor degree graduation certificates",
    credential_type="certificate",
    schema={
        "student_name": {
            "type": "string",
            "required": True,
            "label": "Student Name"
        },
        "degree": {
            "type": "string",
            "required": True,
            "label": "Degree Program"
        },
        "graduation_date": {
            "type": "date",
            "required": True,
            "label": "Graduation Date"
        }
    },
    version="1.0"
)

# Update template
client.templates.update(
    "template-123",
    description="Updated description"
)

# Delete template (soft delete)
client.templates.delete("template-123")

API Key Management

# Generate new API key (Owner/Admin only)
result = client.api_keys.generate()
print(f"New API key: {result['api_key']}")
print("⚠️  Store securely - shown only once!")

# Get API key info
info = client.api_keys.info()
print(f"Masked key: {info['api_key_masked']}")
print(f"Created: {info['created_at']}")
print(f"Last used: {info['last_used_at']}")

# Regenerate API key
result = client.api_keys.regenerate()
print(f"New API key: {result['api_key']}")

# Revoke API key
client.api_keys.revoke()

Team Management

# List team members
team = client.team.list()
print(f"Active members: {team['stats']['active_members']}")
print(f"Pending invitations: {team['stats']['pending_invitations']}")

# Check email before inviting
check = client.team.check_email("newmember@university.edu")
if check['recommendation'] == 'add_directly':
    print("User exists - can add directly")
elif check['recommendation'] == 'send_invitation':
    print("User doesn't exist - must send invitation")

# Invite team member
result = client.team.invite(
    email="newmember@university.edu",
    role="issuer",
    send_email=True
)

# Update member role
client.team.update_role(
    member_id="member-123",
    role="admin"
)

# Deactivate member
client.team.deactivate(
    member_id="member-123",
    reason="Employee on leave"
)

# Reactivate member
client.team.reactivate("member-123")

# Remove member permanently
client.team.remove("member-123")

Error Handling

from docwal import DocWalClient, DocWalError, AuthenticationError, ValidationError

client = DocWalClient(api_key="docwal_live_xxxxx")

try:
    result = client.credentials.issue(
        template_id="invalid-template",
        individual_email="student@example.com",
        credential_data={}
    )
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
    print("Check your API key")
except ValidationError as e:
    print(f"Validation error: {e}")
    print("Check required fields")
except DocWalError as e:
    print(f"API error: {e}")
    print(f"Status code: {e.status_code}")

Rate Limits

  • Pilot: 500 requests/hour
  • Standard: 1,000 requests/hour
  • Enterprise: Unlimited

When rate limit is exceeded, RateLimitError is raised.

Support

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docwal-1.0.1.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docwal-1.0.1-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file docwal-1.0.1.tar.gz.

File metadata

  • Download URL: docwal-1.0.1.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for docwal-1.0.1.tar.gz
Algorithm Hash digest
SHA256 8645a604c6dcc92037f6bbbfa0e8da0aca68893ec71138fa3e4ca596d5e51e49
MD5 69dae815dada6d2f6c1a7f9c9ff8e26b
BLAKE2b-256 44238e5479ca3271176317fb92bd6c75533795c9633bda31fc4828ef6e00695e

See more details on using hashes here.

File details

Details for the file docwal-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: docwal-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for docwal-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 28724e7d1ff264cbb3521b1c8c1380b20b0c8384acf44b1517e31d0c99e6e524
MD5 67a969cfa2dd99897af2b838f22fce61
BLAKE2b-256 d1788b35c03e1b50ab17c7362c2d40549c33c3b6ef6905ed875c333ae417cba8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page