Skip to main content

From payment to spendable funds

The protocol has six stages. Each one exists to separate public discovery from private ownership while keeping the result usable in today’s wallets.

Stage 1: Generate your keys

The backend generates two ML-KEM-768 keypairs:
  • Spending keypair (spending_pk / spending_sk) - determines where money lands
  • Viewing keypair (viewing_pk / viewing_sk) - lets you find your payments
These are bundled into your meta-address: the public-facing profile that senders use.
curl -s -X POST https://backend.specterpq.com/api/v1/keys/generate | jq .
Response includes meta_address, spending_pk, spending_sk, viewing_pk, viewing_sk.
Setup flow

Stage 2: Publish your meta-address

Make your meta-address discoverable. Two options: ENS (Ethereum): Upload meta-address to IPFS, set your ENS text record to point at the IPFS CID. Senders resolve alice.eth to your meta-address automatically. SuiNS (Sui): Same pattern with Sui name records. Or just share the raw meta-address string directly. Name services are convenient, not required.

Stage 3: Sender creates the payment

This is where ML-KEM does its work. The sender:
  1. Reads your viewing_pk from the meta-address
  2. Runs ML-KEM encapsulation to produce:
    • A ciphertext (1,088 bytes) - this is the encrypted hint
    • A shared secret (32 bytes) - known to both sender and recipient
  3. Computes a 1-byte view tag from the shared secret
  4. Derives a stealth address (Ethereum and/or Sui) from the shared secret + your spending_pk
curl -s -X POST https://backend.specterpq.com/api/v1/stealth/create \
  -H "Content-Type: application/json" \
  -d '{"meta_address":"<RECIPIENT_META_ADDRESS>"}' | jq .
The sender then sends ETH/tokens to the returned stealth_address.
Send flow

Stage 4: Sender posts an announcement

The announcement is the public breadcrumb. It contains:
FieldPurpose
ephemeral_keyThe ML-KEM ciphertext (encrypted shared secret)
view_tag1-byte filter for fast scanning
tx_hashTransaction reference (optional)
amountPayment amount (optional)
chainTarget chain (optional)
channel_idYellow channel link (optional)
curl -s -X POST https://backend.specterpq.com/api/v1/registry/announcements \
  -H "Content-Type: application/json" \
  -d '{
    "ephemeral_key":"<HEX_CIPHERTEXT>",
    "view_tag":42,
    "tx_hash":"0x...",
    "amount":"0.1",
    "chain":"ethereum"
  }' | jq .

Stage 5: Recipient scans

This is the discovery process. The recipient:
  1. Loads announcements from the registry
  2. For each announcement, decapsulates the ciphertext using viewing_sk
  3. Computes the expected view tag from the shared secret
  4. Fast path: if the view tag doesn’t match, skip (filters ~99.6% of announcements)
  5. Full path: if it matches, derive the stealth address and compare
curl -s -X POST https://backend.specterpq.com/api/v1/stealth/scan \
  -H "Content-Type: application/json" \
  -d '{
    "viewing_sk":"<HEX>",
    "spending_pk":"<HEX>",
    "spending_sk":"<HEX>"
  }' | jq .
Receive flow

Stage 6: Spend the funds

The scan returns everything needed to spend:
FieldWhat it is
stealth_addressThe Ethereum address holding the funds
stealth_sui_addressThe Sui address (if applicable)
eth_private_keyThe derived private key for spending
Import the private key into any Ethereum wallet and spend normally.
The scan response contains wallet secret material (eth_private_key, stealth_sk). Treat it like a seed phrase. Never log it, never expose it in analytics.

The three objects that matter

ObjectWhat it doesWho holds it
Meta-addressPublic receiving profilePublished by recipient, read by senders
AnnouncementEncrypted breadcrumb for discoveryPublished by sender, scanned by recipient
Stealth private keyControls the fundsOnly the recipient

What sender and recipient each see

The sender needs only the recipient’s meta-address or name.They never learn the recipient’s real wallet address. They derive a fresh stealth address, send funds to it, and post an announcement. From their side, it’s three API calls.

The security split

The receiving path (stages 1-5) uses ML-KEM-768 and is post-quantum safe. The spending path (stage 6) produces a secp256k1 key for Ethereum wallet compatibility. That part is classical. Read Security Boundaries for why this split exists and how it could be resolved.

Post-quantum crypto details

What ML-KEM-768 actually does under the hood.

Try the full flow

Run every stage against the live API.