Skip to main content

hashsign-python

Official Python SDK for HashSign — hash documents locally, request cryptographic verification payloads, and retrieve Hedera Hashgraph audit proofs. Designed for AI agents that need programmatic, auditable signing.

API reference: hashsign.io/docs.

Requires Python 3.10+.

Install

pip install hashsign-python

From this monorepo:

cd sdks/python
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Quickstart

from hashsign import HashSignClient

client = HashSignClient(api_key="hs_live_...")

document = client.documents.upload("contract.pdf")
signed = client.documents.sign(document.id, metadata={"agentId": "invoice-bot"})
proof = client.documents.verify(document.id)

print(signed.payload.signature, signed.document.status)
print(proof.hedera_transaction_id, proof.verified)

sign() returns the full SignDocumentResponse from the API — .payload is the detached signature, .document reflects the new status.

Hybrid ML-DSA-65 envelope

Pass pqc_mode=True when the API key has requirePqcSignatures or when you want a hybrid-ecdsa-ml-dsa envelope. The post-quantum half is FIPS 204 ML-DSA-65 over the raw 32-byte SHA-256 digest (pure ML-DSA, not HashML-DSA). The signature is 3309 bytes. Hedera Consensus Service stores only the 32-byte hybrid anchor, because topic messages are capped at 1024 bytes. The landing-page example topic is 0.0.9001; live topics come from the proof's topic_id.

signed = client.documents.sign(document.id, pqc_mode=True)
proof = client.documents.verify(document.id)

Recompute the anchor locally and compare it to the HCS message field hybridAnchor:

import hashlib

payload = signed.payload
anchor = hashlib.sha256(
    f"{payload.signature}{payload.pqc.signature}".encode()
).hexdigest()
assert anchor == payload.pqc.hybrid_anchor

payload.pqc.public_key is the 1952-byte ML-DSA-65 public key (hex). Verify the signature over the raw digest bytes with any FIPS 204 implementation. The Python SDK requests the envelope; it does not bundle a lattice library.

Async

import asyncio
from hashsign import AsyncHashSignClient

async def main() -> None:
    async with AsyncHashSignClient(api_key="hs_live_...") as client:
        document = await client.documents.upload("contract.pdf")
        await client.documents.sign(document.id)
        proof = await client.documents.verify(document.id)
        print(proof.network, proof.verified)

asyncio.run(main())

Rotate agent credentials

rotated = client.keys.rotate()
print(rotated.key.secret)  # shown once — persist immediately

Configuration

Argument Default Description
api_key required hs_live_... or hs_test_...
base_url https://api.hashsign.io/v1 API origin including /v1
timeout 30.0 httpx timeout (seconds)
transport None Custom httpx transport (tests)

Errors

All failures — HTTP status errors, transport failures, and malformed responses — subclass HashSignError, so one except HashSignError boundary is sufficient:

  • AuthenticationError — invalid or revoked key (401 / 403)
  • ValidationError — request / hash mismatch (400 / 422), or malformed local metadata
  • RateLimitError — includes retry_after_seconds (429)
  • HederaNetworkError — consensus or mirror-node outage (502 / 503)
  • NotFoundError / ConflictError
  • APIConnectionError — DNS, refused connection, TLS; wraps httpx.TransportError
  • APITimeoutError — subclass of APIConnectionError for connect / read timeouts
  • InvalidResponseError — 2xx body that is not JSON, empty, or fails schema validation

In the async client, file hashing runs in a worker thread (asyncio.to_thread) so large uploads never block the event loop.

Local crypto

hashsign.crypto hashes files with SHA-256 and can produce detached Ed25519 signatures. Production deployments should swap those helpers for Hedera operator-key signing (hedera-sdk-py) at the marked HOOK comments.

Tests

pytest

The suite uses httpx.MockTransport and does not call a live API or Hedera network. tests/test_contract.py additionally validates every request body the SDK emits against packages/shared/openapi.yaml, so SDK/spec drift fails CI.

Metadata

Release files for hashsign-python 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hashsign-python 0.1.1
File Size Uploaded
hashsign_python-0.1.1.tar.gz 16.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hashsign-python 0.1.1
File Interpreter ABI Platform
hashsign_python-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 31.0 kB

Release files / hashsign_python-0.1.1.tar.gz

Download URL hashsign_python-0.1.1.tar.gz
Size 16.8 kB
Tags Source
SHA-256 checksum
How to use checksums
e63bdb5bbc3189d5f65769d7d646135afb988e24bcdc01b91d06003d5eb2efb0
BLAKE2b-256 checksum
How to use checksums
4f239c51af6babee3b1ed22a690c2ab9a18517d5cd9d2ee4b8720aaad3d56c07
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / hashsign_python-0.1.1-py3-none-any.whl

Download URL hashsign_python-0.1.1-py3-none-any.whl
Size 14.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3e8cb390e71531519a1e4f74bdd34dda7f47d7c4af5a2fd647e2f18af1cb40da
BLAKE2b-256 checksum
How to use checksums
cecbf06e49f8695c1c845e6f7a5e81c6d8204c83fd0dcefe573775d496b569af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page