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.0.tar.gz (11.3 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.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: docwal-1.0.0.tar.gz
  • Upload date:
  • Size: 11.3 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.0.tar.gz
Algorithm Hash digest
SHA256 464b2b554ff3c6e618eda13a958c9bba5c7ac9fbd4a96a094ad18c0d77d63305
MD5 02342734f545c89808a772889e42fbe1
BLAKE2b-256 52e5f9f9146964617d4074568c82256d7cd4a0a1c0f0048e3497bc81b6796968

See more details on using hashes here.

File details

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

File metadata

  • Download URL: docwal-1.0.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91a86681e87b7ed1ba6eb118e59c008801a7691016c9c5a9944b4aede30bcc89
MD5 a55aa1dfa06453aef40bfddc82acaac4
BLAKE2b-256 d22d81516c7a072a8b6c9a96325646f52939806733339e65357871e9151d7b0f

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