Products Shieldsplit and merge inside an attested enclave Relayhidden origin, rotating exits Vaultscoped secrets and signing for agents Computealways on boxes and GPUs Environmenta private workspace for agents
Developers Documentationquickstart, headers, sessions API referenceevery route WISPR adds Status Changelog
Resources Pricingprovider price, one fee at top up Compareprivate from whom Why WISPR? Blog
Contacthello@wispr.xyz
Try WISPR
DocsStartIntroduction

Introduction

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.

Why use it?

  • No account. A session is a hash and a password. No email, no phone, no KYC, nothing to subpoena.
  • Frontier models, fragment at a time. Use the strongest model on the market without its provider seeing your task.
  • Provider price. No per token markup. One fee at top up, zero while you stake $WISPR.
  • Verifiable. The enclave that does the split publishes a measurement you can check with wispr attest.
  • Agents welcome. Per request payment over x402, secrets through Vault, compute from the same balance.

How it works

client ──encrypted──▶ gateway ──▶ Shield enclave (TDX) ──┬─▶ shard A ─▶ private inference ├─▶ shard B ─▶ specialist model └─▶ shard C ─▶ frontier model client ◀── answer + attestation ◀── merge in enclave ◀──┘
  1. Your client encrypts the request to the enclave key. The gateway in between cannot read it.
  2. The enclave redacts and splits. Identity, money and the analysis itself become separate shards.
  3. Each shard leaves from a different exit. Sensitive shards go to private inference, the rest to a frontier model.
  4. The enclave merges and validates. You get one response, the per call cost and the attestation quote.

Get started

Quickstart

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.

3. Send a request

curl https://api.wispr.xyz/v1/chat/completions \
  -H "Authorization: Bearer $WISPR_SESSION" \
  -H "X-Wispr-Relay: on" \
  -H "X-Wispr-Shield: private-split" \
  -d '{ "model": "auto",
        "messages": [{ "role": "user", "content": "Review this contract and my position." }] }'
from openai import OpenAI
import wispr

client = OpenAI(base_url="https://api.wispr.xyz/v1", api_key=wispr.auth("wispr-session.txt", password))
r = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "Review this contract and my position."}],
    extra_headers={"X-Wispr-Relay": "on", "X-Wispr-Shield": "private-split"},
)
print(r.choices[0].message.content, r.wispr.cost_usd)
import OpenAI from "openai";
import { auth } from "@wispr/sdk";

const client = new OpenAI({ baseURL: "https://api.wispr.xyz/v1", apiKey: await auth("wispr-session.txt", password) });
const r = await client.chat.completions.create(
  { model: "auto", messages: [{ role: "user", content: "Review this contract and my position." }] },
  { headers: { "X-Wispr-Relay": "on", "X-Wispr-Shield": "private-split" } }
);
console.log(r.choices[0].message.content, r.wispr.cost_usd);

4. Read the receipt

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.

response.wispr
"wispr": {
  "level": "protected",
  "shards": [
    { "id": "a", "class": "identity",  "provider": "private-inference",     "exit": "eu-fra", "cost_usd": 0.0021 },
    { "id": "b", "class": "financial", "provider": "venice/qwen3-235b"   , "exit": "eu-fra", "cost_usd": 0.0038 },
    { "id": "c", "class": "analysis",  "provider": "openai/gpt-5.2",        "exit": "us-iad", "cost_usd": 0.0088 }
  ],
  "provider_calls": 3, "cost_usd": 0.0147, "fee_usd": 0,
  "attestation": { "enclave": "shield", "measurement": "sha256:4f1c…a9e0", "quote": "…" }
}
Note

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

StandardProtectedConfidential
Model providerwhole prompt, WISPR IPone shard, WISPR exit IPone shard, WISPR exit IP
Shield enclavenot usedwhole prompt, inside TDX, attestedwhole prompt, inside TDX, attested
WISPR gatewayplaintext in memory, session_idciphertext to the enclave, shard metadata, session_idruns inside an enclave itself
WISPR operatorssession_id, spend, model namessession_id, spend, shard classes, model namessession_id, spend
Anyone on chaindeposits to the pooldeposits to the pooldeposits 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

ModeWhat happensUse when
offNothing. Request goes to the chosen model as is.Public data.
redactNames, 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.
splitTask 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-splitSplit, 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

RegionLocationStatus
eu-fraFrankfurtlive
eu-amsAmsterdamlive
us-iadVirginialive
us-sjcSan Joselive
ap-sinSingaporelive
ap-tyoTokyolive

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.

GPUs

terminal
wispr gpu create --type h100 --hours 2 --image vllm
wispr gpu list
wispr gpu stop gpu-7f2

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.

http
HTTP/1.1 402 Payment Required
X-Payment-Required: {"scheme":"exact","network":"eip155:8453","asset":"USDC","amount":"0.0153","payTo":"0x..."}

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 methodFeeNotes
Card8%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 request6%Added to the quoted price of that request.
$WISPR staked0%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

WISPROpenRouterAnonRouter
Card top up8%5.5%8% (5% launch promo)
Crypto top up6%5%8% (5% launch promo)
Per token markupnonenonenone
Fee free tier$WISPR stakenonenone

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.

GET/v1/sessions/me

Balance, fee rates, stake status, relay exit, spend by day, recent ledger.

POST/v1/sessions/token

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 POST DELETE/:name

List, store ({ name, kind, sealed }, kind ed25519 secp256k1 token) 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.

POST/v1/compute/boxes/:id/wake · sleep · stop · touch PATCH/:id

Lifecycle and settings (keep_awake, stop_at_usd).

Headers

HeaderValues
X-Wispr-Levelstandard protected confidential
X-Wispr-Shieldoff redact split private-split
X-Wispr-Shield-Sensitivecomma list of identity financial medical secrets code
X-Wispr-Shield-Plannerrules (default) or model: a private model re-segments the pseudonymized material
X-PAYMENTx402 payment payload (base64 JSON) when the session has no balance
X-Wispr-Shield-Privatemodel id for the private shard
X-Wispr-Shield-Frontiermodel id for the rest
X-Wispr-Relayon off or a region
X-Wispr-Budgetmax USD for this request

Errors

Every error is typed. The body carries { error: { code, message } } and the codes below never change meaning.

CodeMeaning
401 session_authHMAC or timestamp invalid. Clock skew over 60 s is the usual cause.
402 payment_requiredNo balance and no x402 payment. Body carries the price.
409 nullifier_usedDeposit note already redeemed.
422 shield_unmergeableReconstructor could not validate the merge after retries. Response includes the shards so you can merge yourself.
423 level_unavailableNo enclave capacity for Confidential right now. Retry or drop to Protected explicitly.
424 attestation_mismatchThe SDK refused an enclave whose measurement is not in the published list. Update the SDK or check wispr.xyz/measurements; do not send the request.
429 budget_exceededX-Wispr-Budget was lower than the cheapest plan for this request. Raise it or use redact.
Tip

A refused shard is never silently swapped for a weaker model. You either get a typed error or a real answer.