ETH.id Python SDK
Zero-Knowledge Document Verification SDK for Python.
Installation
pip install ethid
Quick Start
from ethid import EthIdClient, LLMProvider
# Initialize client
client = EthIdClient(
provider=LLMProvider.OPENAI,
api_key="sk-your-key"
)
# Verify a document
result = client.verify(
document_path="passport.pdf",
claim="over 18 years old"
)
print(f"Answer: {result.answer}")
print(f"Confidence: {result.confidence}%")
print(f"Reasoning: {result.reasoning}")
Features
- Zero-Knowledge Verification: Documents never leave your machine
- Privacy-First: Only minimal, claim-relevant data is processed
- Multiple LLM Providers: OpenAI, Claude, Ollama
- Cryptographic Attestations: Tamper-evident proof bundles
- Audit Trail: Complete verification history
- Type-Safe: Full type hints and dataclasses
Usage
Basic Verification
from ethid import EthIdClient
client = EthIdClient()
# Age verification
result = client.verify(
document_path="id.pdf",
claim="maior de 18 anos"
)
if result.answer:
print("Person is over 18")
With Attestation
# Generate cryptographic proof
result = client.verify(
document_path="id.pdf",
claim="over 21 years old",
attest=True
)
# Get attestation bundle
bundle = client.get_attestation(result.session_id)
# Verify integrity
if bundle.verify_integrity():
print("Attestation is valid")
Offline Mode
# Complete privacy with local LLM
client = EthIdClient(
provider=LLMProvider.OLLAMA,
offline=True
)
result = client.verify(
document_path="document.pdf",
claim="document is signed"
)
Audit Log
# List all verifications
entries = client.list_audit_log(limit=10)
for entry in entries:
print(f"{entry.timestamp}: {entry.claim} -> {entry.answer}")
# Get specific entry
entry = client.get_audit_entry(session_id="...")
Privacy Guarantees
What is NEVER Sent
For age verification:
- ❌ Birth date
- ❌ Full name
- ❌ Address
- ✅ Only: "Age calculation result: true"
For CPF verification:
- ❌ Full CPF (123.456.789-00)
- ✅ Only: Masked (123..-00)
API Reference
EthIdClient
class EthIdClient:
def __init__(
self,
cli_path: Optional[str] = None,
provider: Optional[LLMProvider] = None,
api_key: Optional[str] = None,
offline: bool = False,
debug: bool = False,
)
Methods
verify()
def verify(
self,
document_path: str,
claim: str,
provider: Optional[LLMProvider] = None,
attest: bool = False,
zk_only: bool = False,
) -> VerificationResult
get_attestation()
def get_attestation(
self,
session_id: str,
) -> AttestationBundle
list_audit_log()
def list_audit_log(
self,
limit: Optional[int] = None,
filter_claim: Optional[str] = None,
) -> List[AuditEntry]
configure()
def configure(
self,
provider: Optional[LLMProvider] = None,
api_key: Optional[str] = None,
)
Types
VerificationResult
@dataclass
class VerificationResult:
session_id: str
answer: bool
confidence: float
reasoning: str
proof_type: ProofType
claim: str
privacy_metadata: PrivacyMetadata
timestamp: datetime
AttestationBundle
@dataclass
class AttestationBundle:
session_id: str
document_hash: str
claim: str
result: VerificationResult
proof_type: ProofType
bundle_hash: str
created_at: datetime
def verify_integrity(self) -> bool
Examples
Age Verification
result = client.verify(
document_path="passport.pdf",
claim="over 18 years old"
)
print(f"Over 18: {result.answer}")
CPF Verification
result = client.verify(
document_path="brazilian_id.pdf",
claim="CPF bate com 123.456.789-00"
)
# Only masked CPF is sent: 123.***.***-00
Income Verification
result = client.verify(
document_path="income_proof.pdf",
claim="renda acima de 5000"
)
# Only amount field is sent, no name/CPF
Multiple Providers
# OpenAI
client_openai = EthIdClient(provider=LLMProvider.OPENAI)
# Claude
client_claude = EthIdClient(provider=LLMProvider.CLAUDE)
# Ollama (offline)
client_ollama = EthIdClient(
provider=LLMProvider.OLLAMA,
offline=True
)
Error Handling
from ethid import (
DocumentParsingError,
ClaimParsingError,
VerificationError,
)
try:
result = client.verify(
document_path="document.pdf",
claim="over 18 years old"
)
except DocumentParsingError as e:
print(f"Failed to parse document: {e}")
except ClaimParsingError as e:
print(f"Failed to parse claim: {e}")
except VerificationError as e:
print(f"Verification failed: {e}")
Requirements
- Python 3.8+
- ETH.id CLI installed (
cargo install --path .)
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black ethid/
# Type check
mypy ethid/
License
MIT
Links
Metadata
Release files for ethid 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ethid-0.1.0.tar.gz | 10.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ethid-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.5 kB
Release files / ethid-0.1.0.tar.gz
| Download URL | ethid-0.1.0.tar.gz |
|---|---|
| Size | 10.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
530206fb7777b2dbcc907ea15794235b576fc217dec04130abe4abf7add8570e
|
|
BLAKE2b-256 checksum How to use checksums |
d230254d6fcec27bca07886112ba78facc90582e9c35ce47b593d1f536d0f41d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / ethid-0.1.0-py3-none-any.whl
| Download URL | ethid-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a4117339a92a3912d73db90a90b77a19c50a70a76b764ded67812f49a4ad04a5
|
|
BLAKE2b-256 checksum How to use checksums |
9155af6442712e76ba85d32acf2e534c80959680bafdf4af1528dc9c455b0a22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Security for ethid 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.