API reference
Receive & ack
Poll your inbox for sealed envelopes, decrypt them locally, then acknowledge. Delivery is ack-based: nothing is dropped until you confirm you decrypted it.
GET/api/v1/envelopesPOST/api/v1/envelopes/ack
1 · Pull
Returns undelivered envelopes addressed to your key's wallet. Non-consuming — the same envelopes appear on every pull until acked.
bash
curl https://api.sealedlabs.net/api/v1/envelopes \
-H "Authorization: Bearer $SEALED_API_KEY"2 · Decrypt locally
Derive the shared secret from your device private key and the envelope's ephemeralPublicKey, then open the AES-256-GCM ciphertext with the nonce. If recipientDeviceKeyis set and isn't yours, skip that envelope — it belongs to another of the account's devices.
3 · Ack
Confirm the ids you decrypted and stored. The relay marks them delivered and prunes them on its schedule (delivered > 7 days, anything > 30 days).
bash
curl https://api.sealedlabs.net/api/v1/envelopes/ack \
-H "Authorization: Bearer $SEALED_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "ids": ["8b1f…"] }'A minimal bot loop
python
import base64, os, time, requests
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
BASE = "https://api.sealedlabs.net"
AUTH = {"Authorization": f"Bearer {os.environ['SEALED_API_KEY']}"}
DEVICE_PRIV_HEX = os.environ["SEALED_DEVICE_PRIVATE_KEY"] # your device key
def open_envelope(env: dict) -> str:
"""Reverse of seal(): X25519 + HKDF-SHA256("sealed-v1") + AES-GCM."""
priv = X25519PrivateKey.from_private_bytes(bytes.fromhex(DEVICE_PRIV_HEX))
shared = priv.exchange(
X25519PublicKey.from_public_bytes(
bytes.fromhex(env["ephemeralPublicKey"])
)
)
key = HKDF(
algorithm=hashes.SHA256(), length=32, salt=None, info=b"sealed-v1"
).derive(shared)
return AESGCM(key).decrypt(
base64.b64decode(env["nonce"]),
base64.b64decode(env["ciphertext"]),
None,
).decode()
while True:
envelopes = requests.get(
f"{BASE}/api/v1/envelopes", headers=AUTH
).json()["envelopes"]
decrypted = []
for env in envelopes:
try:
handle_message(env["senderAddress"], open_envelope(env))
decrypted.append(env["id"])
except Exception:
pass # wrong device / bad envelope — leave unacked
if decrypted:
requests.post(
f"{BASE}/api/v1/envelopes/ack",
headers=AUTH, json={"ids": decrypted},
)
time.sleep(15)Only ack after a successful decrypt and durable store. Acking blind means an envelope you failed to process is gone for good. Poll gently — the rate limit is per key.