Skip to main content
Qustody is a non-custodial orchestration platform. The platform never holds your post-quantum private keys. Signing happens in a separate signing service that you control or that runs alongside Qustody under a strict cryptographic boundary.

Trust boundaries

Three independent boundaries:
BoundaryWhat it holdsWhat it does NOT hold
Qustody APIWallet metadata, public keys, transaction state, audit trail, encrypted webhook secretsPost-quantum private keys, raw transaction signatures (only after the signer returns them)
Signing servicePost-quantum private keys, signing logicTransaction state, policy data, customer identifiers
Quantum Chain nodePublic ledger, mempoolAnything customer-specific

Separation of duties

Qustody enforces separation of duties through the RBAC system:
  • Operator can create transactions but cannot approve them.
  • Approver can approve and reject transactions but cannot create them.
  • Compliance officer can read screening reports and audit logs but cannot create or approve.
  • Admin can manage users, roles, and credentials but is not required to be on the signing path.
Any high-risk action (rotate credentials, change a system role, change a policy) is recorded to the immutable audit log with a chained hash.

Key handling boundaries

  • The Qustody API never sees post-quantum private keys.
  • For any transaction in PENDING_SIGNATURE, the API exposes a signing_payload (the digest to be signed). Your external signer reads it, produces a post-quantum signature using its own keys, and submits the signature back via POST /v1/transactions/{id}/signature.
  • The API verifies the submitted signature against the public key registered to the wallet before accepting it. A wrong key or an invalid signature transitions the transaction to FAILED.
  • Three signer integration modes are supported:
    • Callback (CUSTODY_SIGNER_TYPE=callback) — fully external; the signer pushes signatures to Qustody.
    • Remote (CUSTODY_SIGNER_TYPE=remote) — Qustody calls the signer over HTTPS.
    • gRPC (CUSTODY_SIGNER_TYPE=grpc) — Qustody calls the signer over gRPC with mTLS (recommended for production).

Authentication

Qustody supports two authentication modes:
ModeUse caseConfiguration
API key (default)Service-to-service integrationAuthorization: Bearer <key> header
OIDC / SAML SSOHuman users in dashboardsEnabled with CUSTODY_SSO_ENABLED=true; requires CUSTODY_SSO_JWT_SIGNING_KEY
Both can be active at the same time. Webhook signing uses HMAC-SHA256 with a per-endpoint secret (returned once on creation).

Encryption

SurfaceAt restIn transit
PostgreSQLTLS to disk; column-level AES-256-GCM for webhook secrets when CUSTODY_WEBHOOK_ENCRYPTION_KEY is setsslmode=verify-full enforced in production
Signer connectionmTLS (gRPC mode); bearer token over TLS (remote mode)TLS 1.2+
Webhook deliveriesn/aTLS 1.2+ to your endpoint, HMAC-SHA256 body signature
API requestsn/aHTTPS only when CUSTODY_ENV=production; HTTP allowed in development

Audit trail

Every state-changing API call writes an audit record. Records are chained — each entry includes the hash of the previous entry — so any tampering is detectable.
# List audit records
curl "$BASE_URL/v1/audit" \
  -H "Authorization: Bearer $API_KEY"

# Verify the audit chain
curl "$BASE_URL/v1/audit/verify" \
  -H "Authorization: Bearer $API_KEY"
The audit log records: actor (user or API key), action, resource ID, request ID, IP, user-agent, prior-record hash.

Replay and idempotency

  • Every mutating endpoint accepts an Idempotency-Key header. Duplicate requests with the same key within 24 hours return the original response without re-executing.
  • Webhook deliveries include X-Webhook-ID, X-Webhook-Timestamp, and X-Webhook-Signature. Reject deliveries whose timestamp is more than 5 minutes from your clock to prevent replay.

What Qustody does NOT protect against

Qustody is one layer of a defense-in-depth strategy. It does not protect you from:
  • Compromise of your signing service or its keys. Use HSMs, mTLS, and least-privilege access on the signing service.
  • A malicious or compromised approver. Use multi-approver policies and rotate roles.
  • A malicious tenant administrator with admin role. Limit admin role assignment and review the audit log.
  • Compromise of your webhook endpoint. Always verify the HMAC signature.
  • On-chain reorganizations beyond the configured CUSTODY_CONFIRMATION_DEPTH. Increase the depth for high-value transfers.