Quick Access
Check out example:GitHub
SPL Tokens Anchor Implementation
Live Example App
Try private payments
Overview
Private Payments are the privacy use case built on top of SPL tokens on ER. The same deposit / transfer / withdraw primitive runs with private visibility, so the amount, destination, and timing of a payment are shielded rather than broadcast publicly.New to the primitive? Read the Ephemeral SPL Tokens
overview first — this guide
assumes the eATA / Global Vault / delegation model.
API reference
Endpoints for deposit, transfer, withdraw, balances, stealth pools, and auth.
Reference program
The on-chain Ephemeral SPL Token program.
Privacy model
Private payments rely on:- Private visibility — transfers execute inside the Ephemeral Rollup with
visibility: "private", so the transfer is not broadcast publicly. - Stealth handles — send to a human-readable name (e.g.
alice@magicblock.id) instead of a raw public key. The handle resolves to one or more destination keys via a stealth pool, breaking the direct sender → recipient link on-chain. - Queued settlement — private transfers can settle through the program’s transfer queue rather than a direct, immediately-linkable movement.
Authentication
Private reads and stealth-pool operations require a bearer token. Obtain one with the challenge/login flow before calling protected endpoints:1
Request a challenge
GET /v1/spl/challenge returns a message for the user to sign.2
Log in
POST /v1/spl/login exchanges the signed challenge for a bearer token.3
Call protected endpoints
Send
Authorization: Bearer <token> on GET /v1/spl/private-balance and
POST /v1/spl/stealth-pool.Deposits
Move tokens into the mint’s Global Vault and credit the depositor’s ephemeral ATA.POST /v1/spl/deposit— builds the deposit transaction. Setprivate: trueto keep the deposited balance private.
sendTo field (base or ephemeral). Sign it and
submit via POST /v1/transaction/send
or your own RPC.
Private transfers
POST /v1/spl/transferwithvisibility: "private".
To use a stealth handle, initialize it first:
POST /v1/spl/stealth-pool— map a handle (≤255 UTF-8 bytes; not normalized, soAlice@…≠alice@…) to 1–10 destination owner keys, optionally splitting payments across them.GET /v1/spl/stealth-pool?handle=…— check whether a handle’s pool exists.
Handles are stored as their exact UTF-8 bytes.
GET returns only whether the pool exists — never the
destination keys.Withdrawals
Move a balance back out of the Global Vault to a standard base-layer SPL token account.POST /v1/spl/withdraw— builds the withdrawal transaction.
GET /v1/spl/balance— public balance.GET /v1/spl/private-balance— private balance (requires the bearer token).
Developer notes
- Privacy is a spectrum. Ephemeral SPL tokens reduce linkability; they do not hide amounts, timing, or protect against network-level analysis.
- Handles aren’t normalized. Casing/whitespace matter — display and store handles consistently.
- Match the flow. Stealth-handle transfers require
visibility: "private",fromBalance: "base",toBalance: "base"(these are also the omitted-field defaults). - Sign then send. Builder endpoints return unsigned transactions; submit them with
POST /v1/transaction/sendand honor the returnedsendTo.
Next steps
Ephemeral SPL Tokens — Overview
The primitive behind private payments.
SDK Quickstart
The on-chain/SDK integration path.

