build 0.1.0·aes-256-gcm / post-quantum·eu/de·ram onlyrelay online
BUILD · DOCS

Documentation.

API reference, SDK guide, self-hosting, and compliance docs for Paramant v0.1.0. The relay is untrusted by design — it never holds a decryption key.

Quick start

Send your first encrypted file in under 5 minutes. Create a free account (TOTP protected, key visible in dashboard).

bash# Sender
python3 paramant-sender.py --key pgp_your_key --device laptop-01 document.pdf
# → HASH: abc123... (share with the receiver)

# Receiver (burn-on-read: one download only)
python3 paramant-receiver.py --key pgp_your_key --hash abc123...
# → document.pdf saved locally. Blob destroyed on relay.

Direct HTTP API access requires no SDK:

bashcurl -X POST https://relay.paramant.app/v2/inbound \
  -H "X-Api-Key: pgp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"hash":"sha256_of_payload","payload":"base64_5mb_blob","ttl_ms":3600000}'

curl https://relay.paramant.app/v2/outbound/abc123... \
  -H "X-Api-Key: pgp_your_key" -o received.bin

Authentication

Two key types exist — never interchangeable:

  • pgp_ — end-user keys for file operations
  • plk_ — relay operator license keys (in .env only)
X-Api-Key: pgp_your_key_here
# or:
GET /v2/check-key?k=pgp_your_key_here

SDK & scripts

The Python scripts handle ML-KEM-768 encryption, 5 MB padding, chunking, retries, and DID auth.

pythonfrom paramant_sdk import GhostPipe

gp = GhostPipe(
    api_key='pgp_xxx',
    device='device-001',
    sector='health',
)

hash_ = gp.send(open('scan.dcm', 'rb').read(), ttl=3600)
data = gp.receive(hash_)

# Anonymous drop with 12-word mnemonic
mnemonic = gp.drop(b'sensitive data', ttl=3600)
data = gp.pickup(mnemonic)

JavaScript/TypeScript SDK:

typescriptimport { GhostPipe } from '@paramant/sdk';

const gp = new GhostPipe({ apiKey: 'pgp_xxx', device: 'device-001', sector: 'health' });
const hash = await gp.send(new TextEncoder().encode('hi'), 3600);
const data = await gp.receive(hash);

Use cases

Each sector relay is tuned for its compliance domain.

bash# Healthcare — NEN 7510, DICOM, HL7 FHIR
python3 paramant-sender.py --key pgp_xxx --device mri-001 --sector health scan.dcm

# Legal — eIDAS-grade evidence
paramant-notary deed.pdf --sign --receipt

# Industrial IoT — IEC 62443 quantum-safe data diode
python3 paramant-sender.py --heartbeat 15 --device plc-factory-01 --sector iot

# Finance — NIS2, DORA, ISO 20022
python3 paramant-sender.py --watch /export/iso20022/ --device bank-nl-01 --sector finance

All endpoints

MethodEndpointDescriptionAuth
GET/healthNode status, version, uptime, edition
POST/v2/inboundUpload encrypted blob (RAM-only)Key
GET/v2/outbound/:hashDownload + burn — one retrieval onlyKey
GET/v2/status/:hashCheck blob availability without consumingKey
POST/v2/ackConfirm delivery, log latency to CTKey
GET/v2/monitorLive stats: blobs in flight, ACK rateKey
POST/v2/ws-ticketGet 30s one-time WebSocket ticketKey
GET/v2/streamWebSocket push — blob_ready eventsTicket
POST/v2/webhookRegister delivery webhook URLKey
POST/v2/pubkeyRegister ML-KEM + ECDH keypairKey
GET/v2/check-keyVerify key validity and plan
POST/v2/did/registerRegister W3C Decentralized IdentityKey
GET/v2/did/:didResolve DID document
GET/v2/ct/sthSigned Tree Head (public)
GET/v2/ct/leavesCT log entries with proofs
GET/v2/relaysRegistered relay nodes and status
GET/v2/auditMerkle audit chain — JSON + CSV exportKey
GET/v2/team/devicesList team devicesKey
POST/v2/team/add-deviceAdd device to team (Pro+)Key
GET/metricsPrometheus scrape endpointAdmin

POST /v2/inbound

Upload an encrypted, padded blob. Stored in RAM only. Returns a hash for retrieval.

json{ "hash": "sha256_of_padded_payload", "payload": "base64_encoded_5mb_blob", "ttl_ms": 3600000 }

200: { "ok": true, "hash": "...", "ttl_ms": ... } · 409: hash already exists · 503: relay at capacity. TTL clamps to plan max. Hash is SHA-256 of the padded payload.

GET /v2/outbound/:hash

After this call the blob buffer is overwritten with random bytes and removed from RAM.

GET /v2/outbound/abc123...
X-Api-Key: pgp_xxx

200: binary blob (5 MB padded) · 404: burned/expired/never existed · 403: API key mismatch.

GET /v2/stream

WebSocket endpoint for real-time blob_ready push. Use a one-time ticket.

javascriptconst { ticket } = await fetch('https://health.paramant.app/v2/ws-ticket', {
  method: 'POST', headers: { 'X-Api-Key': 'pgp_xxx' }
}).then(r => r.json());

const ws = new WebSocket(`wss://health.paramant.app/v2/stream?ticket=${ticket}`);
ws.onmessage = e => {
  const msg = JSON.parse(e.data);  // { type: "blob_ready", hash, size, ts }
};

GET /v2/monitor

json{
  "ok": true, "plan": "pro", "blobs_in_flight": 3,
  "stats": { "inbound": 42, "burned": 38, "webhooks_sent": 12 },
  "delivery": { "total": 42, "acked": 38, "success_rate": 0.905 }
}

POST /v2/webhook

Relay POSTs to your callback on delivery. Body is HMAC-SHA256 signed via X-Paramant-Sig (secret = your API key).

json{ "hash": "blob_hash", "callback_url": "https://you.com/hook" }
// → { "event": "blob_retrieved", "hash": "...", "ts": "..." }

GET /health

json{
  "ok": true, "version": "0.1.0", "sector": "health",
  "edition": "licensed", "uptime_s": 3600
}

Self-hosting — Docker Compose

Community Edition is free forever for up to 5 users. One docker compose up starts 6 containers: five sector relays and an admin panel.

bashgit clone https://github.com/mocrofifa-alt/paramant
cd paramant
cp .env.example .env
echo "ADMIN_TOKEN=$(openssl rand -hex 32)" >> .env
docker compose up -d
curl http://localhost:3000/health

Container ports: relay-main :3000 · health :3001 · finance :3002 · legal :3003 · iot :3004 · admin :4200. All bind 127.0.0.1 — terminate TLS at nginx.

nginx & TLS

bashapt install -y nginx python3-certbot-nginx
certbot certonly --nginx -d your-domain.com \
  -d relay.your-domain.com -d health.your-domain.com \
  -d finance.your-domain.com -d legal.your-domain.com \
  -d iot.your-domain.com

First user

bashpython3 scripts/paramant-admin.py add --label alice --plan pro --email alice@example.com
python3 scripts/paramant-admin.py sync   # pushes to all sector containers
open https://your-domain.com/admin/

Community Edition cap: 5 users. The 6th add returns HTTP 402. Add PLK_KEY to .env to unlock unlimited.

Upgrade

bashcd /opt/paramant
git pull --ff-only
docker compose up -d --build

paramant-client — .deb install

bash# One-line install (Ubuntu / Debian / Pi OS)
curl -fsSL https://paramant.app/install-client.sh | bash

CLI reference

  • paramant-send — Encrypt and upload a file or stdin
  • paramant-receive — Download and decrypt by hash
  • paramant-watch — Watch a directory and auto-send
  • paramant-stream — Listen for incoming blobs via WebSocket
  • paramant-admin — Manage users, keys, relay config
  • paramant-scan — Discover relay nodes on the network

ParamantOS — operator tools

ParamantOS is a hardened Linux distribution for relay operators. Pre-installed tool categories: setup & diagnostics, relay control, sector tools (referral / notary / legal / payslip / firmware / cra), CT log verification, key management, network, security, backup & data.

Crypto stack

AlgorithmRoleStandard
ML-KEM-768Post-quantum key encapsulationNIST FIPS 203
ECDH P-256Classical key exchange (hybrid)NIST SP 800-56A
AES-256-GCMSymmetric authenticated encryptionNIST FIPS 197
HKDF-SHA256Key derivation from hybrid KEM outputRFC 5869
SHA3-256CT log Merkle hashing · DID hashesNIST FIPS 202
ML-DSA-65Relay identity signaturesNIST FIPS 204
Argon2idPassword-protected blob deriveRFC 9106

Burn-on-read

After GET /v2/outbound/:hash the relay overwrites the blob buffer with cryptographically random bytes and removes the entry from memory. Two-step burn: zero-in-place, then Map entry deletion. CT log preserves only Merkle hashes — never payload content.

5 MB fixed padding

ParaShare authenticated blobs are padded to exactly 5,242,880 bytes (5 MiB) with cryptographically random bytes. Effective DPI masking: an observer cannot determine size, type, or content. Anonymous /send blobs retain actual encrypted size up to 5 MB.

Certificate Transparency log

Every transfer hash and device registration appended to a public Merkle tree. Root hash changes with every write and is publicly verifiable. Anyone can prove a transfer occurred without learning what was transferred.

bashGET https://relay.paramant.app/v2/ct/leaves?from=0&to=100
json{
  "tree_size": 56,
  "leaves": [
    { "index": 56, "leaf_hash": "ecb779...", "blob_hash": "ce56ff...",
      "sector": "health", "inserted_at": "2026-04-14T19:07:57Z" }
  ]
}

W3C Decentralized Identity

Devices can register a W3C DID backed by ML-DSA-65 + ECDH keys.

bashPOST /v2/did/register
{ "device_id": "mri-001", "ecdh_pub": "base64...", "dsa_pub": "base64..." }
# → { "did": "did:paramant:abc123...", "ct_index": 42 }

# Authenticate with DID:
X-DID: did:paramant:abc123...
X-DID-Signature: base64_request_signed_with_dsa_key

Team management

bashpython3 scripts/paramant-admin.py add --label "scanner-room-3" --plan pro --email admin@hospital.nl
python3 scripts/paramant-admin.py sync
python3 scripts/paramant-admin.py revoke --label "scanner-room-3"

Key changes are zero-downtime — the relay hot-reloads users.json on sync. Revoked keys receive WebSocket close code 4401 within seconds.

Retention policy

PlanDefault TTLMaximum TTLMax file
Free (pgp_)1 hour1 hour5 MB (padded)
Pro1 hour24 hours5 MB
Enterprise1 hour7 days5 MB (tested 50 MB)

Relay sectors

All sector nodes run identical Ghost Pipe relay software. Sectors are routing domains — they provide traffic isolation and sector-specific compliance documentation.

SectorURLUseCompliance
healthhealth.paramant.appDICOM, patient records, vitalsNEN 7510, GDPR
legallegal.paramant.appContracts, notary, evidenceAVG, eIDAS
financefinance.paramant.appISO 20022, compliance dataNIS2, DORA
iotiot.paramant.appSCADA, PLCs, sensor streamsIEC 62443

Threat model

The relay is untrusted by design. Security does not depend on trusting the operator.

A compromised relay can: deny or delay service, learn transfer timing/frequency, observe blob sizes (all 5 MB on ParaShare), block specific device hashes.

A compromised relay cannot: read file contents, substitute registered ML-KEM public keys, forge ML-DSA-65 relay signatures, decrypt stored ciphertext.

Security audits

  • Apr 2026 · R. Zwarts (verification) · 14 findings · all resolved (commit e6f216d)
  • Apr 2026 · R. Zwarts (independent) · 6 findings · all resolved (commit 0db3ef0)
  • Apr 2026 · Ryan Williams · Smart Cyber Solutions · 4C/5H/6M/5L · all resolved (commit 0db3ef0)

Findings publicly documented in SECURITY.md. Report vulnerabilities to privacy@paramant.app.

NIS2 / DORA

NIS2 (EU 2022/2555) supported via post-quantum encryption, Merkle CT log audit trail, EU-only Hetzner DE infrastructure, burn-on-read minimisation, zero-downtime key revocation. Full mapping →

NEN 7510 (Healthcare)

health.paramant.app sector designed for NEN 7510 with encrypted-in-transit-and-at-rest (RAM only), CT log access logging, DID device identity, key-based access control, EU GDPR jurisdiction. Control mapping →

IEC 62443 (Industrial / OT)

iot.paramant.app acts as quantum-safe data diode — PLCs/sensors push outbound only without inbound ports. Fixed 5 MB padding defeats traffic analysis. ML-DSA-65 device signatures. Control mapping →

FAQ

Can the relay operator read my files?

No. Encryption happens in the browser or SDK before the file leaves your device. The relay receives ciphertext it cannot decrypt. Even a full root compromise of the relay server yields only encrypted blobs and Merkle hashes.

What happens after the file is downloaded?

The blob buffer is immediately overwritten with random bytes and removed from memory. No recovery, no backup, no second download.

Is Community Edition really free forever?

Yes. Up to 5 users, no license key required, no time limit. The 6th user returns HTTP 402 — add a PLK_KEY to .env to unlock unlimited users.

What is the difference between pgp_ and plk_ keys?

pgp_ keys are for end users (file operations). plk_ keys are relay license keys for operators (in .env, not in API calls). Never interchangeable.

How does 5 MB padding protect me?

All ParaShare transfers — regardless of actual file size — appear as identical 5 MiB blobs on the network. A passive observer cannot distinguish a 1 KB heartbeat from a 4.9 MB DICOM scan.

Can I run this on a Raspberry Pi?

Yes. The relay runs on arm64 — Pi 3B+, 4, 5. Minimum 512 MB RAM for a single-sector relay. Use install-pi.sh.

Is the source code auditable?

Yes — github.com/Apolloccrypt/paramant-relay under BUSL-1.1. Three independent security audits in April 2026 — all findings publicly documented in SECURITY.md.

What is Ghost Pipe?

The relay protocol: WebSocket-based, post-quantum encrypted transfer where data is stored in RAM only, destroyed after one download, padded to a fixed size.