Solrouter
APITEE

POST /tee/process

Send one sealed prompt to the Intel TDX enclave. The route the web chat, the SDK, and the MCP server's encrypted_chat use. Each call costs one unit from a plan, free messages, or USDC balance.

This endpoint takes a prompt that your client already encrypted to the enclave's key, relays it to the Intel TDX enclave without reading it, and returns the enclave's encrypted reply. The enclave decrypts the prompt, calls the model on a Nosana GPU node, and seals the reply to your key. The Nosana node sees the prompt and the reply in plaintext while it runs the model. Solrouter does not control that hardware.

The web chat at solrouter.com, @solrouter/sdk's client.chat(), and the MCP server's encrypted_chat all call this route. Call it yourself only in a custom client.

Endpoint

POST https://api.solrouter.com/tee/process

Authentication

HeaderWhoPaid by
Authorization: Bearer sk_solrouter_...API keyPlan, then USDC balance
Authorization: Bearer <sign-in token>Web or mobile sign-inPlan, then free messages, then USDC balance
Partner keyFirst-party Solrouter productsNot metered
No Authorization headerGuest5 calls a day per network address

A token that is present but invalid returns 401. It is not downgraded to a guest call.

Request

FieldTypeDescription
encryptedPromptstring (required)The sealed prompt: a JSON string with ciphertext, nonce, publicKey, and version, encrypted to the key from GET /tee/public-key.
modelstring (required)nosana:gpt-oss:20b, nosana:qwen3.8:27b, or nosana:qwen3-coder:30b.
chatIdstringOptional. Logged by the backend in plaintext. Not forwarded to the enclave.
userPubkeystringOptional. A wallet address stored as a data field in the Solana receipt. Leave it out to keep your wallet off the receipt.

Metering

Every call costs one unit, whatever its length. The backend checks the request first, so a malformed request costs nothing. For a signed-in caller it then takes the first source that covers the call:

  1. A call from the plan or stake allowance. usage.source is plan.
  2. A free message, for web and mobile sign-ins only. usage.source is free.
  3. The USDC balance at $0.02 a call. usage.source is balance.
  4. Nothing covers it: 402 insufficient_funds.

If the enclave call fails, the plan call, free message, or guest message goes back. The USDC balance is charged only after the enclave answers. Guest calls share one daily counter with the plaintext guest chat route. See Pricing.

Response

FieldTypeDescription
successbooleantrue when the enclave answered.
encryptedResponsestringThe reply, sealed to your ephemeral key. Only your client can open it.
requestIdstringThe enclave's id for this request.
attestationobjectThe enclave's per-request attestation, with its TDX quote or tdxQuoteError.
encryptionProofobjectThe enclave's signature over the hash of your ciphertext.
metadataobjectModel and lengths. No prompt or reply text.
provider, modelstringThe provider and model id, split from the model you sent.
backendRolestringAlways BLIND_RELAY.
onchainAttestationobject or nullThe Solana receipt: type, address, encryptedPromptHash, signature, explorerUrl, alreadyExists. null when the receipt could not be committed. The reply is still served.
privacyProofobjectbackendSawPlaintext: false, decryptionLocation, and attestationVerifiable.
usageobjectsource is plan, free, balance, guest, or partner. calls_remaining is present for plan, free, and guest.

Example usage values:

{ "source": "plan", "calls_remaining": 1999 }
{ "source": "free", "calls_remaining": 4 }
{ "source": "balance" }
{ "source": "guest", "calls_remaining": 3 }
{ "source": "partner" }

Errors

StatuserrorMeaning
400Missing encrypted prompt or Missing modelA required field is missing. Nothing is charged.
401unauthorizedThe Authorization header is present but invalid. Sign in again or check the key.
402insufficient_fundsNo plan calls, free messages, or USDC balance left. Pick a plan or add USDC.
429guest_limitA guest used all 5 calls for the day. Sign in to keep going.
502tee_unreachableThe backend could not reach the enclave. Nothing is charged. Retry.
503billing_unavailableBilling could not be checked and nothing else covered the call. Retry shortly.

After an enclave restart its key changes. If a reply fails to decrypt or you get tee_unreachable, fetch the key again from GET /tee/public-key and retry. The SDK does this when you call clearSession().

On this page