Skip to main content

CertySign Trust Services SDK — sign, verify, and manage digital signatures

Project description

CertySign SDK — Python

PyPI version Python 3.8+

Official Python SDK for the CertySign Trust Services platform. Mirrors the @certysign/sdk Node.js package feature-for-feature.

Privacy-first: Your documents never leave your infrastructure. Only cryptographic hashes are transmitted to the API.


Installation

pip install certysign-sdk

For PAdES PDF signing with TSA timestamp support:

pip install "certysign-sdk[asn1]"

Quick start

from certysign_sdk import CertySignClient

client = CertySignClient(
    public_key="YOUR_API_KEY_ID",
    secret_key="YOUR_API_KEY_SECRET",
    environment="staging",
)

# Optional: check that the configured key can reach the API
status = client.ping()
print(status["success"])

Core workflows

1 — Hash-based signing (recommended)

The document never leaves your server.

# Hash raw document bytes locally and send only the hash
result = client.sign.hash_and_sign(
    document=open("invoice.pdf", "rb").read(),
    file_name="invoice.pdf",
    reason="Invoice approval",
)

If you already computed the hash yourself, use sign_hash() instead:

doc_hash = client.hasher.hash_file("invoice.pdf")

result = client.sign.sign_hash(
    document_hash=doc_hash["hash"],
    hash_algorithm=doc_hash["algorithm"],
    file_name="invoice.pdf",
)

2 — Local PDF signature embedding (PAdES)

with open("invoice.pdf", "rb") as f:
    pdf_bytes = f.read()

signed_pdf = client.embedder.embed_in_pdf(
    pdf_bytes,
    reason="Invoice approval",
    sign_callback=lambda h: client.sign.sign_hash(
        document_hash=h,
        hash_algorithm="sha256",
    ),
)

with open("invoice-signed.pdf", "wb") as f:
    f.write(signed_pdf)

3 — PAdES B-T (with RFC 3161 timestamp)

client = CertySignClient(
    public_key="...",
    secret_key="...",
    tsa_url="https://tsa.certysign.io",  # upgrades to PAdES B-T automatically
)

signed_pdf = client.embedder.embed_in_pdf(pdf_bytes, sign_callback=...)

4 — XML signing (XMLDSig enveloped)

with open("document.xml") as f:
    xml_content = f.read()

# Hash and sign
doc_hash = client.hasher.hash(xml_content.encode())
result = client.sign.sign_hash(
    document_hash=doc_hash["hash"],
    hash_algorithm=doc_hash["algorithm"],
)

# Embed signature
signed_xml = client.embedder.embed_in_xml(
    xml_content,
    signature=result["data"]["signature"],
    certificate=result["data"]["certificate"],
    document_hash=doc_hash["hash"],
)

5 — JSON signing

payload = {"amount": 1500, "currency": "USD", "recipient": "Alice"}
doc_hash = client.hasher.hash(json.dumps(payload).encode())
result = client.sign.sign_hash(document_hash=doc_hash["hash"])

signed_envelope = client.embedder.embed_in_json(
    payload,
    signature=result["data"]["signature"],
    certificate=result["data"]["certificate"],
)

6 — Signature envelope workflow (multi-recipient)

# Create envelope
envelope = client.envelopes.create(
    title="Service Agreement",
    signers=[
        {"email": "alice@example.com", "name": "Alice"},
        {"email": "bob@example.com", "name": "Bob"},
    ],
)

# Upload documents
client.envelopes.upload_documents(
    envelope["data"]["id"],
    [{"name": "agreement.pdf", "data": open("agreement.pdf", "rb").read()}],
)

# Send to signers
client.envelopes.send(envelope["data"]["id"])

7 — Signing sessions (OTP verification)

session = client.sessions.create(
    {
        "name": "Q1 Board Resolution",
        "documents": [
            {
                "documentId": "doc-resolution",
                "fileName": "board-resolution.pdf",
                "hash": "a3f2b8c1d4e5f6...",
                "hashAlgorithm": "sha256",
                "mimeType": "application/pdf",
            }
        ],
        "recipients": [{"email": "alice@example.com", "name": "Alice"}],
        "signingOrder": "parallel",
    }
)

recipient_id = session["data"]["session"]["recipients"][0]["recipientId"]
session_id = session["data"]["session"]["_id"]

# Trigger OTP delivery
client.sessions.sendOtp(session_id, recipient_id)

# Verify OTP and sign
result = client.sessions.verifyOtp(session_id, recipient_id, "123456")
client.sessions.recipientSign(session_id, recipient_id, result["data"]["signingToken"])

Node-style aliases are also available throughout the Python SDK, for example:

result = client.sign.hashAndSign({
    "document": open("invoice.pdf", "rb").read(),
    "fileName": "invoice.pdf",
    "signerEmail": "alice@example.com",
    "reason": "Approval",
})

API Reference

CertySignClient

Parameter Type Default Description
public_key str required X-API-Key-Id header value
secret_key str required X-API-Key-Secret header value
environment str 'production' 'production' | 'staging' | 'development' | 'test'
base_url str None Override API base URL completely
timeout int 30 HTTP timeout in seconds
retries int 3 Max retries for transient failures
debug bool False Verbose request logging
tsa_url str None TSA service URL for PAdES-T timestamps

Resources

Property Class Description
client.sign HashSigningResource Hash-based signing (recommended)
client.certificates CertificateResource Certificate lifecycle
client.pki PkiResource CRL, OCSP, chain, info
client.envelopes EnvelopeResource Signature envelopes
client.sessions SigningSessionResource OTP-verified signing sessions
client.dashboard DashboardResource Analytics
client.hasher DocumentHasher Local hashing (no network)
client.embedder SignatureEmbedder Local signature embedding (no network)
client.legacy_sign SigningResource Legacy upload-based signing

DocumentHasher

from certysign_sdk.utils import DocumentHasher

hasher = DocumentHasher()

# Hash bytes
result = hasher.hash(b"hello world")
# → {"hash": "b94d27b9...", "algorithm": "sha256", "size": 11}

# Hash a file
result = hasher.hash_file("document.pdf")
# → {"hash": "...", "algorithm": "sha256", "size": 204800, "file_name": "document.pdf"}

# Hash many documents
results = hasher.hash_many([b"doc1", b"doc2"])

# Hash multiple files
results = hasher.hash_files(["a.pdf", "b.pdf"])

Supported algorithms: sha256 (default), sha384, sha512.


SignatureEmbedder

from certysign_sdk.utils import SignatureEmbedder

embedder = SignatureEmbedder(tsa_url="https://tsa.certysign.io")

# PDF (PAdES)
signed_pdf = embedder.embed_in_pdf(pdf_bytes, sign_callback=my_sign_fn)

# XML (XMLDSig enveloped)
signed_xml = embedder.embed_in_xml(xml_str, signature="...", certificate="...")

# JSON (signed envelope)
signed_json = embedder.embed_in_json(data, signature="...", certificate="...")

Error handling

from certysign_sdk import CertySignError

try:
    result = client.sign.hash_and_sign(document_hash="...")
except CertySignError as e:
    print(f"Status: {e.status_code}, Code: {e.code}, Message: {e}")
    print(f"Details: {e.details}")

Environments

environment Base URL
production https://core.certysign.io
staging https://service.certysign.io
development http://localhost:8000
test http://localhost:8000

License

MIT © CertySign Trust Services

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

certysign_sdk-1.3.2.tar.gz (40.6 kB view details)

Uploaded Source

Built Distribution

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

certysign_sdk-1.3.2-py3-none-any.whl (39.2 kB view details)

Uploaded Python 3

File details

Details for the file certysign_sdk-1.3.2.tar.gz.

File metadata

  • Download URL: certysign_sdk-1.3.2.tar.gz
  • Upload date:
  • Size: 40.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for certysign_sdk-1.3.2.tar.gz
Algorithm Hash digest
SHA256 0b5a9b0d5b351930c4af684b43b4ffb8171b74188321f9e9362e6ba65239cd00
MD5 b711ab98b08a841c4ff50e2c488b1aa2
BLAKE2b-256 ca2c9127c32f78c5f4c3bf653c14200b7c8d99ba5851fe624981244bf66c741e

See more details on using hashes here.

File details

Details for the file certysign_sdk-1.3.2-py3-none-any.whl.

File metadata

  • Download URL: certysign_sdk-1.3.2-py3-none-any.whl
  • Upload date:
  • Size: 39.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for certysign_sdk-1.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 332696ba15e72da4d1b65a5d7fb469c7ec08e91ccb65c72cbabd5f386dd4f80f
MD5 3fc63e68a2cec63d541dd1206b866b40
BLAKE2b-256 5b82e1ec7acc0d35947de39841a9861913ce3289530be3679638eff78e38c026

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