WISPR is an OpenAI compatible gateway with four extra things: a sharder, an exit network, a secrets vault and a compute market. If your code talks to OpenAI, it talks to WISPR after changing one line.
Tip
In a hurry? The Quickstart gets a private request out in two minutes. Everything else here is optional detail.
What is WISPR?
A request goes in through the same /v1 routes you already use. Instead of landing on one provider, it can be redacted, split into fragments inside an attested enclave, sent out through exits that are not the gateway, answered by several models and merged back. The provider sees a fragment from an exit IP. We see ciphertext and shard metadata. You see one normal response plus a receipt of what happened.
Base URL https://api.wispr.xyz/v1. Every OpenAI endpoint is mirrored: chat completions, responses, embeddings, images, audio, video. Privacy is switched on with headers, so nothing about your request body changes.
1. Get a session
A session is a secret file plus a password you choose. The password is never stored and never sent.
terminal
# creates a session file and asks for a password
npx wispr session new
# or in the dashboard: Sessions, New, download the file
2. Fund it
Top up with any crypto (settled in USDC on Base), with a deposit note if you want the funding unlinkable, or by card. Agents can skip the balance and pay per request over x402.
The response is a normal chat completion plus a wispr object: which shards were made, which provider served each one, the exit it used, what it cost at provider price, and the attestation of the enclave that did the split and the merge.
cost_usd is the sum of the provider calls at the per token price of the route, nothing added. The WISPR fee is charged once at top up, not per request. See Pricing and fees.
Sessions live
A session is the only identity WISPR has for you. There is no account, email or wallet behind it. It is made of two halves: a secret saved in a file and a password you remember. Either half alone is useless.
How a session is built
secret = random 32 bytes (saved in wispr-session.txt)
password = chosen by you (never saved, never sent)
session_id = H("wispr/session/v1" || secret) public, like an account number
auth_key = scrypt(password, secret) stays on your machine, seeds an Ed25519 key
server stores: session_id -> public key, balance nothing else
request header:
Authorization: Bearer wispr_<session_id>.<sig>.<ts>.<nonce>
The signature covers the timestamp, a nonce, the method, the path and the body hash, so a captured header cannot be replayed or reused for a different request. The 60 second window is enforced by the gateway. SDK helpers (wispr.auth(session, password)) do this for you. With raw curl, set WISPR_SESSION to the output of npx wispr session token, which is valid for a minute.
Rotate
POST /v1/sessions/rotate proves the old key and moves the balance to a fresh session_id. Your past requests and the new ones are no longer connected on our side.
terminal
npx wispr session rotate # new id, same balance, old id dead
npx wispr session me # balance, level, fee rate, spend by day
Compatibility keys
If you do not care about any of this, wispr_sk_... keys work like any API key. They are stored as a hash and shown once. They tie every request to one key, which is the weaker mode and says so in the dashboard.
Warning
Lose the file or the password and the balance is gone. We cannot reset it because we do not have it. Keep small balances in sessions and top up often.
Privacy levels
Set per request with X-Wispr-Level, or per agent at deploy time. Higher levels switch on more of the stack and cost more compute.
Standard
Session auth, no body logging, provider sees a WISPR IP. Shield and Relay off unless you set their headers.
Protected
Relay on, Shield private-split on inside an attested enclave, Vault grants allowed. No provider sees more than its shard, and WISPR never sees the whole prompt.
Confidential
Everything in Protected, plus the gateway path and the agent box also run in attested TDX enclaves. Verify with wispr attest.
What each party can see
Standard
Protected
Confidential
Model provider
whole prompt, WISPR IP
one shard, WISPR exit IP
one shard, WISPR exit IP
Shield enclave
not used
whole prompt, inside TDX, attested
whole prompt, inside TDX, attested
WISPR gateway
plaintext in memory, session_id
ciphertext to the enclave, shard metadata, session_id
runs inside an enclave itself
WISPR operators
session_id, spend, model names
session_id, spend, shard classes, model names
session_id, spend
Anyone on chain
deposits to the pool
deposits to the pool
deposits to the pool
The claim the product rests on
At Protected, the only machine that holds your full prompt is one whose code you can verify, and whose operator (us) cannot read its memory.
Shield live
Shield turns one request into fragments that are useful alone and meaningless together, routes each one, then rebuilds a single answer. Header: X-Wispr-Shield.
Modes
Mode
What happens
Use when
off
Nothing. Request goes to the chosen model as is.
Public data.
redact
Names, amounts, addresses, dates and secrets replaced by typed tokens ([PERSON_1]) before leaving, restored on reply. One model.
Cheap, one hop, you only need the identifiers hidden.
split
Task graph built from the request, independent subtasks sent to different providers, merged.
Long multi part tasks, you want no provider to see the whole.
private-split
Split, plus the sensitive shard goes to private inference (Venice, Phala TEE or your own box). Default at Protected.
Anything with identity or money in it.
Control the split
headers
-H "X-Wispr-Shield: private-split"
-H "X-Wispr-Shield-Sensitive: identity,financial" # classes that must go private
-H "X-Wispr-Shield-Private: venice/llama-4-maverick" # model for the private shard
-H "X-Wispr-Shield-Frontier: openai/gpt-5.2" # model for the rest
Each shard carries a WISPR exit IP and a per shard session, never the parent session. The reconstructor validates the merge against the original task and will re run a shard that contradicts the others. Benchmarks against direct calls will be published per routing policy in the dashboard.
Where the split happens
The analyzer and the reconstructor run inside an Intel TDX enclave hosted on Phala. The gateway outside the enclave sees only ciphertext and shard metadata. Your client encrypts the request to the enclave's key, which is bound to a published code measurement, so a modified enclave would carry a different measurement and your SDK would refuse it.
client
│ encrypted to the enclave key
▼
gateway sees ciphertext and shard metadata only
│
▼
Shield enclave (TDX) decrypt · redact · split
├─▶ shard A ─▶ private inference (exit eu-fra)
├─▶ shard B ─▶ specialist model (exit eu-fra)
└─▶ shard C ─▶ frontier model (exit us-iad)
│ merge · validate · encrypt to client
▼
client answer + attestation quote
terminal
wispr attest shield # checks the quote against the published build
curl https://api.wispr.xyz/v1/attest # raw quote, verify with any TDX tool
Measurements for every released enclave build are published at wispr.xyz/measurements with the source commit. The SDK pins the current one and refuses a different one with 424 attestation_mismatch. A local mode, where the SDK runs the planner on your machine and the enclave is not needed, is planned for the Python and Node SDKs.
What it costs
Split and private-split make two to four provider calls for one request, so the token cost is higher than one direct call, and the reply can be worse on tasks that need the whole context at once. There is no markup on those calls; the response lists each one with its provider price.
Tip
Use redact when hiding identifiers is enough. It stays at one call and one provider.
Relay live
Relay sends the request from a WISPR owned exit instead of the gateway. Headers that identify a client are stripped and bodies are never written to disk on an exit.
Turn it on
headers
-H "X-Wispr-Relay: on" # nearest exit
-H "X-Wispr-Relay: eu-fra" # pick a region
Stripped on the way out: user agent, forwarded for, cookies and any header that names a client. Exits rotate daily, or on demand with POST /v1/relay/rotate.
Regions
Region
Location
Status
eu-fra
Frankfurt
live
eu-ams
Amsterdam
live
us-iad
Virginia
live
us-sjc
San Jose
live
ap-sin
Singapore
live
ap-tyo
Tokyo
live
Vault live
A virtual .env for agents. Secrets are stored once, and agents receive short lived grants instead of the secret. Wallet signers never leave the Vault: the agent asks for a signature, the Vault checks the grant limits and signs.
Note
Vault holds action keys: wallet signers, deploy keys, bot tokens. It never holds model provider keys. Models are paid from your balance through WISPR, which is the point.
Store, grant, revoke
terminal
wispr vault set DEPLOY_KEY ghp_...
wispr vault grant DEPLOY_KEY --to agent-01 --ttl 24h
wispr vault signer add WALLET_SIGNER --chain base --limit 500usdc/day
wispr vault grant WALLET_SIGNER --to agent-01 --ttl 24h --scope "swap,transfer<=100usdc"
wispr vault revoke DEPLOY_KEY --from agent-01
Inside the agent, process.env.DEPLOY_KEY resolves through the grant. After revoke the agent's next read fails. Nothing to rotate, because the agent never had the key.
What a compromised agent can do
Spend its allowance and nothing more. Grants carry a TTL, a scope and a limit, and signing happens inside the enclave. The agent gets a result, never the key.
Compute beta
CPU boxes for always on agents (WISPR Box) and GPUs by the hour from Akash, Vast.ai and WISPR racks. Billed per minute from the session balance at provider price, with a hard stop.
Boxes
terminal
wispr deploy --level protected --box small --stop-at 5.00
wispr agent run "Research new positions and report every morning. Keep holdings private."
wispr logs agent-01 --follow
A workspace box wakes when you open it and sleeps after ten minutes idle. Your files live on an encrypted volume that is written through from the box, so nothing stays on the machine after sleep. One box per session; a second device attaches to the same box.
At Confidential level the box is a TDX confidential VM. wispr attest agent-01 returns the quote and the measured image hash so you can verify it against the published build.
Payments and networks
Three ways money gets into a session: crypto (any coin, any chain, settled in USDC on Base), card, or per request over x402. Usage is always billed at provider price from the balance.
Crypto: any coin in, USDC on Base inside
Inside WISPR every balance is USDC on Base, the one asset every provider we pay accepts without a bridge. Send USDC on Base straight to your session deposit address, or any other coin on any chain: relay.link converts it on the way in and shows the bridge fee before you send. Or or use a deposit note when the paying wallet must not be linkable to the session.
NetworkBase (any chain accepted via relay.link)
AssetUSDC (any coin accepted, converted on arrival)
Deposit addressGET /v1/sessions/deposit-address or Billing in the dashboard
Pool contractPublished with the deposit note launch, with source and verifier
Minimum top up5 USDC direct, 10 USDC by note
CreditedAfter finality, usually under a minute
Check the address
Always take the deposit address from the API or the dashboard for the session you mean to fund. Nothing sent to any other address or any other network can be recovered.
Card
Card top ups go through a processor and carry the highest fee. They are tied to a session, not an account, and the processor sees a card, not a prompt. If the funding link matters to you, use a deposit note instead.
x402 per request
Agents without a balance can pay per call. Send the request with no session; the gateway answers 402 Payment Required with a price; the agent pays in USDC on Base and retries with the payment header. No account, no top up.
The quoted amount is the estimated provider cost plus the x402 fee. Any overestimate is refunded to the paying address. x402 payments are visible on chain, so use a deposit note instead when the payer must not be linkable to the session.
Deposit notes beta
A deposit note funds a session without a link between the paying wallet and the session. The design borrows the deposit side of Tornado Cash and deliberately drops the withdraw side: credits only ever land inside WISPR, they cannot be sent to an address.
Flow
1. deposit wallet -> WisprPool (Base, USDC), fixed 10 / 50 / 250
commitment = H(nullifier || secret) goes into the Merkle tree
you keep: wispr-usdc-50-base-0x<nullifier><secret>
2. wait any time. anonymity set = every unredeemed 50 USDC deposit
3. redeem POST /v1/deposits/redeem { proof, root, nullifierHash, session_id }
zk proof: "I know a leaf in this root and its preimage"
session_id is a public input, bound into the proof
WISPR checks root + nullifier, credits the session, marks nullifier
What WISPR learns: a 50 USDC note was redeemed into session S. Not which deposit, not which wallet. What the chain shows: a wallet deposited 50 USDC into the pool. Timing is the only correlation, so the CLI waits a random delay by default.
terminal
wispr deposit 50 --from 0xYourWallet # writes the note to wispr-notes.txt
wispr redeem wispr-usdc-50-base-0x... # into the current session, after a random delay
What it is not
Not a mixer
Credits never leave WISPR, there are no session to session transfers, denominations are small and the pool refuses deposits from sanctioned addresses. This is prepaid credit with a privacy layer. Contract, circuit and verifier are published.
Pricing and fees
Every model, box and GPU is billed at provider price. There is no multiplier and no per request markup. WISPR charges one fee when money comes in.
Fees at top up
Top up method
Fee
Notes
Card
8%
Session only, no account. Card rails and chargeback risk cost us close to half of this.
Crypto (any coin, settled in USDC on Base)
6%
Direct transfer or a deposit note; the fee is taken when the note is redeemed.
x402 per request
6%
Added to the quoted price of that request.
$WISPR staked
0%
Stake $500 of $WISPR (valued at stake time) for 90 days, bound to a session. While the stake runs, every top up into that session is fee free and the session gets priority routing and exits. Unstake after the term; the tokens stay yours throughout.
terminal
wispr stake 500 --days 90 --from 0xYourWallet # stakes $500 of $WISPR, bound to this session
wispr session me # shows balance, stake, fee rate, spend by day
Staking is on chain
The staking wallet is linked to the session it benefits. If that link matters to you, stake from a fresh wallet or skip staking and fund with deposit notes at 6%.
What privacy costs
Privacy is paid for in provider calls, not in fees. redact is one call. split and private-split are two to four calls, one of which lands on private inference at that provider's price. Confidential level adds the enclave box at 0.011 USD/h. Every response carries the per call breakdown, so the premium is visible, never hidden in a rate.
x402
Per request payment adds 6% to the estimated provider cost of that request. Overestimates are refunded to the paying address. Details and the header format are in Payments and networks.
Compared
WISPR
OpenRouter
AnonRouter
Card top up
8%
5.5%
8% (5% launch promo)
Crypto top up
6%
5%
8% (5% launch promo)
Per token markup
none
none
none
Fee free tier
$WISPR stake
none
none
Competitor figures from their public pricing pages, checked 29 October 2026.
API reference
All OpenAI endpoints under /v1 with identical request and response shapes. Listed here are the routes and headers WISPR adds.
Sessions
POST/v1/sessions
Register a session. Body: { session_id, public_key }, both made on your machine from the secret and the password. No auth.
One hour bearer token (wispr_st_…) for clients that cannot sign, such as the OpenAI SDKs.
POST/v1/sessions/keys
Compatibility key (wispr_sk_…), shown once, stored hashed. The weaker mode.
POST/v1/sessions/rotate
Move the balance to a fresh id. Body: { new_session_id, new_public_key }. Must be signed with the session key; every token and compat key on the old id dies.
GET/v1/sessions/deposit-address
This session's USDC deposit address on Base. Other coins and chains are accepted through relay.link and arrive as USDC. Credited after confirmations, minus the top up fee.
GET/v1/sessions/stake POST
GET returns the contract, your session id as bytes32 and the requirement. After staking on chain, POST re-reads stakeOf(session_id) and switches the fee to 0%.
Requests
POST/v1/chat/completions
OpenAI shape. With an empty balance, send X-PAYMENT (x402) or receive 402 with the price and pay-to details. Sealed requests send { sealed } instead of the body: the request is encrypted to the enclave key from /v1/attest and the answer comes back sealed to a key you put inside.
GET/v1/models
Catalogue with provider, route, prices per million, tags (private inference, frontier, cheap) and whether the route is live.
GET/v1/attest
Shield enclave measurement, mode (tdx or inprocess), TDX quote when present, and the sealing public key.
POST/v1/relay/rotate
New exit region for this session.
POST/v1/deposits/redeem
Redeem a deposit note. Body: { denomination, proof, publicSignals: [root, nullifierHash, sessionId] }. Verified against the published key, nullifier marked, denomination credited minus the fee.
Vault
GET/v1/vault/key
Public key to seal secrets to before storing them. Plaintext values are refused.
GET/v1/vault/secrets POSTDELETE/:name
List, store ({ name, kind, sealed }, kind ed25519secp256k1token) and remove secrets.
POST/v1/vault/grants DELETE/:id
Grant an agent a secret for a window: { agent, name, hours, max_uses, limit }.
POST/v1/vault/sign
{ agent, name, digest } under a live grant. The secret is opened only inside the Vault; you get the signature.
Compute
GET/v1/compute/gpus
GPU offers with hourly price and route.
GET/v1/compute/boxes POST
List or create a box: { name, level, size, region, stop_at_usd, keep_awake }. Billed per minute while awake, free asleep, sleeps after 10 idle minutes, stops at the budget.