Documentation
REST API, SDK, protocol reference, and team management for PARAMANT Ghost Pipe v2.
Quick start
Send your first encrypted blob in under 5 minutes.
# Python SDK pip install paramant-sdk from paramant_sdk import GhostPipe gp = GhostPipe("pgp_your_key", "device-001") hash = gp.send(open("document.pdf", "rb").read()) data = gp.receive(hash) # burn-on-read — then gone forever
# Direct HTTP — no SDK needed curl -X POST https://health.paramant.app/v2/inbound \ -H "X-Api-Key: pgp_your_key" \ -H "Content-Type: application/json" \ -d '{"hash":"sha256_of_payload","payload":"base64_blob","ttl_ms":300000}'
Authentication
All endpoints require an API key as a header or query parameter.
X-Api-Key: pgp_your_key_here
# or via query param
GET /v2/check-key?k=pgp_your_key_here
Keys are plan-based: devproenterprise
SDK & scripts
The Python SDK and CLI scripts handle encryption, chunking, retries, and DID auth automatically. Download them below — your API key is required to use the relay.
gp = GhostPipe(
api_key="pgp_xxx",
device="device-001",
sector="health", # health / legal / finance / iot
use_edge=False # True = via Fly.io edge (geo-routed)
)
hash = gp.send(data, ttl_ms=86400000, webhook="https://you.com/cb")
data = gp.receive(hash)
All endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /health | Node status, version, uptime, slots | — |
| POST | /v2/inbound | Upload encrypted blob | Key |
| GET | /v2/outbound/:hash | Download + burn — one retrieval only | Key |
| GET | /v2/status/:hash | Check availability without consuming | Key |
| POST | /v2/ack | Confirm delivery, log latency | Key |
| GET | /v2/monitor | Live delivery stats, ACK rate | Key |
| GET | /v2/stream | WebSocket — blob_ready push events | Key |
| POST | /v2/webhook | Register delivery webhook URL | Key |
| POST | /v2/pubkey | Register ML-KEM + ECDH keypair | Key |
| GET | /v2/check-key | Verify key validity and plan | — |
| POST | /v2/did/register | Register W3C Decentralized Identity | Key |
| GET | /v2/did/:did | Resolve DID document | — |
| GET | /v2/ct/log | Certificate Transparency log | — |
| GET | /v2/audit | Merkle audit chain — JSON + CSV export | Key |
| GET | /v2/key-sector | Resolve sector for this key | Key |
| GET | /v2/team/devices | List team devices | Key |
| POST | /v2/team/add-device | Add device to team (Pro+) | Key |
| GET | /metrics | Prometheus scrape endpoint | Admin |
POST /v2/inbound
Upload an encrypted blob. Stored in RAM only. Returns hash and download token.
{
"hash": "sha256_of_padded_payload",
"payload": "base64_encoded_5mb_blob",
"ttl_ms": 300000
}
200: { "ok": true, "hash": "...", "ttl_ms": 300000, "download_token": "..." }
409: hash already exists
503: relay at capacity
TTL is clamped to plan maximum: dev 1h · pro 24h · enterprise 7 days.
GET /v2/outbound/:hash
One retrieval only. Blob is overwritten with random bytes and removed from RAM after this call.
GET /v2/outbound/abc123...
X-Api-Key: pgp_xxx
200: binary blob (5MB padded)
404: burned or expired
403: wrong API key
GET /v2/monitor
{
"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
{ "hash": "blob_hash", "callback_url": "https://you.com/hook" }
Payload on delivery:
{ "event": "blob_retrieved", "hash": "...", "ts": "2026-04-02T..." }
GET /v2/stream
const ws = new WebSocket('wss://health.paramant.app/v2/stream?k=pgp_xxx') ws.onmessage = e => { const msg = JSON.parse(e.data) // { type: "blob_ready", hash: "...", size: 5242880 } }
Crypto stack
| Algorithm | Role | Standard |
|---|---|---|
| ML-KEM-768 | Post-quantum key encapsulation | NIST FIPS 203 |
| ECDH P-256 | Classical key exchange (hybrid) | NIST SP 800-56A |
| AES-256-GCM | Symmetric encryption | NIST FIPS 197 |
| HKDF-SHA256 | Key derivation | RFC 5869 |
| ML-DSA-65 | Post-quantum signatures (optional) | NIST FIPS 204 |
Burn-on-read
After GET /v2/outbound/:hash the relay overwrites the blob buffer with random bytes and removes it from memory. The relay never writes to disk. No backup, no recovery.
20MB fixed padding
All blobs are padded to exactly 20MB with cryptographically random bytes before upload. An observer on the network cannot determine the size or type of the transferred file.
W3C Decentralized Identity
POST /v2/did/register
{ "device_id": "mri-001", "ecdh_pub": "base64...", "dsa_pub": "base64..." }
{ "did": "did:paramant:abc123...", "ct_index": 42 }
# Authenticate subsequent requests:
X-DID: did:paramant:abc123...
X-DID-Signature: base64_request_signed_with_dsa_key
Certificate Transparency log
Every public key registration is appended to a public Merkle tree at GET /v2/ct/log. Anyone can verify a device registration without seeing transferred data.
Team management
# Create team python3 paramant-admin.py team-create --label my-org --stripe-sub sub_xxx --sector health # Add device — auto-bills +€12/mo python3 paramant-admin.py team-add --team team_abc123 --label laptop-jan --sector health # List teams python3 paramant-admin.py team-list
Retention policy
| Plan | Default TTL | Maximum TTL |
|---|---|---|
| dev | 5 min | 1 hour |
| pro | 5 min | 24 hours |
| enterprise | 5 min | 7 days |
Relay sectors
| Sector | URL | Use case | Compliance |
|---|---|---|---|
| health | health.paramant.app | DICOM, patient records, vitals | NEN 7510, GDPR |
| legal | legal.paramant.app | Contracts, notary, evidence | AVG, eIDAS |
| finance | finance.paramant.app | Compliance data, signing keys | No CLOUD Act |
| iot | iot.paramant.app | SCADA, PLCs, sensor streams | IEC 62443 |