API reference
Device keys
Fetch the current X25519 device public keys for any address. These are what you seal ciphertext against — one envelope per active device for multi-device delivery.
GET/api/v1/keys/:address
Path parameters
| Name | Description |
|---|---|
| address | Full 0x wallet address (40 hex chars). |
Response
200 — active keys only; revoked devices are excluded automatically:
bash
curl https://api.sealedlabs.net/api/v1/keys/0xabc… \
-H "Authorization: Bearer $SEALED_API_KEY"Sealing against a key
Generate an ephemeral X25519 pair, derive a shared secret against the recipient device key, expand it with HKDF-SHA256 (info sealed-v1), and encrypt with AES-256-GCM. The server never sees the shared secret or plaintext. In Python (pip install cryptography):
python
import base64, os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.x25519 import (
X25519PrivateKey, X25519PublicKey,
)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
def seal(plaintext: str, recipient_pub_hex: str) -> dict:
"""Seal one message for one recipient device key."""
eph = X25519PrivateKey.generate()
shared = eph.exchange(
X25519PublicKey.from_public_bytes(bytes.fromhex(recipient_pub_hex))
)
key = HKDF(
algorithm=hashes.SHA256(), length=32, salt=None, info=b"sealed-v1"
).derive(shared)
nonce = os.urandom(12)
ct = AESGCM(key).encrypt(nonce, plaintext.encode(), None)
return {
"ciphertext": base64.b64encode(ct).decode(),
"ephemeralPublicKey": eph.public_key().public_bytes_raw().hex(),
"nonce": base64.b64encode(nonce).decode(),
}Submit the returned fields, plus toAddress and the recipientDeviceKey you sealed against, as an envelope.
Keys rotate when users add or revoke devices. Fetch fresh keys immediately before encrypting — stale keys produce envelopes the recipient can never open. A 404 means the address has no registered sealed devices yet.