Skip to main content
The WAVIS API is plain HTTPS+JSON. Every endpoint can be hit with curl, fetch, requests, or any HTTP client.

Base URL

https://api.wavis.xyz
All endpoints are versioned under /api/v1/. We follow semver on the path: breaking changes go into /api/v2/, never into v1.

Auth

Bearer token in the Authorization header:
Authorization: Bearer wvs_live_<32-hex>
See Authentication for getting a key.

Content type

All POST/PATCH bodies are JSON. The server returns JSON for every status code except 204 No Content and 429 Too Many Requests (which return empty body).
Content-Type: application/json

End-to-end with curl

A complete TFHE flow using only curl:
# 1. Get a trial key
API_KEY=$(curl -s -X POST https://api.wavis.xyz/api/v1/onboarding/temp-key \
  | jq -r .api_key)
echo "Got: ${API_KEY:0:20}..."

# 2. Health check
curl -s https://api.wavis.xyz/api/v1/health | jq .status
# "healthy"

# 3. Create a TFHE session (server-managed for demo; production uses /eval-session)
SESSION_ID=$(curl -s -X POST https://api.wavis.xyz/api/v1/tfhe/session \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"preset": "fast_128"}' \
  | jq -r .session_id)

# 4. Encrypt two bits
CT_A=$(curl -s -X POST https://api.wavis.xyz/api/v1/tfhe/session/$SESSION_ID/encrypt \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"bit": false}' \
  | jq -r .ciphertext_b64)

CT_B=$(curl -s -X POST https://api.wavis.xyz/api/v1/tfhe/session/$SESSION_ID/encrypt \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"bit": true}' \
  | jq -r .ciphertext_b64)

# 5. Evaluate NAND
RESULT_B64=$(curl -s -X POST https://api.wavis.xyz/api/v1/tfhe/gate \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"session_id\": \"$SESSION_ID\",
    \"op\": \"NAND\",
    \"a\": \"$CT_A\",
    \"b\": \"$CT_B\"
  }" \
  | jq -r .result_b64)

# 6. Decrypt (server-side, demo only)
curl -s -X POST https://api.wavis.xyz/api/v1/tfhe/session/$SESSION_ID/decrypt \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"ciphertext_b64\": \"$RESULT_B64\"}" \
  | jq .bit
# true   (NAND(false, true) = true)

# 7. Clean up
curl -s -X DELETE https://api.wavis.xyz/api/v1/tfhe/session/$SESSION_ID \
  -H "Authorization: Bearer $API_KEY"
For production, replace step 3 with /tfhe/eval-session (FHE-blind) and do encryption/decryption client-side. See Server Mode.

Standard response shape

Successful responses are bare JSON objects:
{
  "session_id": "sess_abc",
  "preset": "fast_128",
  "n": 636,
  "big_n": 1024
}
Errors are uniform across endpoints:
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "field 'preset' must be one of fast_128, standard_128, conservative_128",
    "request_id": "req_abc123",
    "documentation_url": "https://docs.wavis.xyz/api-reference/tfhe"
  }
}
The request_id is the single most useful thing to include in support tickets.

HTTP status codes

CodeMeaning
200Success
201Created
204Success, no body
400Validation error — check error.message
401Auth missing or invalid
402Payment required (over plan limit, no overage allowed)
403Auth valid, but role lacks permission
404Resource not found
409Conflict (e.g. session_id reuse)
413Payload too large (eval keys >40 MB, ciphertexts >2 MB)
422Schema parse failed
429Rate limited — retry after Retry-After seconds
500Server error — safe to retry idempotent requests
502Upstream dependency unavailable (Stripe, Redis, etc.)
503Service in maintenance

Rate limits

Plan limits are enforced at three granularities:
GranularityWindowHeaders
Per-account daily24 hX-RateLimit-Daily-{Limit,Remaining,Reset}
Per-account monthly1 calendar month UTCX-RateLimit-Monthly-{Limit,Remaining,Reset}
Per-IP burst60 sX-RateLimit-Burst-{Limit,Remaining,Reset}
Free tier: 10K FCU/month. PAYG: unlimited (metered). See billing for full quotas. When rate-limited:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Daily-Reset: 1714435200
Wait Retry-After seconds and retry. The SDKs do this automatically.

Pagination

List endpoints (/keys, /webhooks, /billing/invoices) use cursor-based pagination:
GET /api/v1/keys?limit=20
{
  "items": [...],
  "next_cursor": "eyJvZmZzZXQiOiAyMH0=",
  "has_more": true,
  "total_count": 142
}
Fetch the next page:
GET /api/v1/keys?limit=20&cursor=eyJvZmZzZXQiOiAyMH0=
limit ranges from 1–100 (default 20). The cursor is opaque base64 — don’t parse or modify it.

Idempotency

Mutation endpoints (POST /keys/*, POST /tfhe/eval-session) accept an optional Idempotency-Key header (any string ≤256 chars). Replays within 24 h return the cached response — safe to retry.
POST /api/v1/keys/upload
Idempotency-Key: client-generated-uuid-v4-here

Webhooks (vs. polling)

For long-running compute (CKKS deep circuits, batch jobs >30 s), prefer webhooks over polling:
# Register once
curl -X POST https://api.wavis.xyz/api/v1/webhooks \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "url": "https://your-app.com/wavis-webhook",
    "events": ["compute_complete"],
    "secret": "min-32-char-shared-secret-here-..."
  }'

# Now compute responses contain a job_id you can correlate to the webhook event
See Webhooks for HMAC verification and retry semantics.

CORS

The API allows Authorization and Content-Type from any origin (Access-Control-Allow-Origin: *). However, never embed a wvs_live_* key in browser source — get a wvs_trial_* key per session, or proxy through your backend.

OpenAPI spec

Machine-readable schema at:
https://api.wavis.xyz/openapi.json
https://api.wavis.xyz/redoc      # browsable HTML
https://api.wavis.xyz/docs       # Swagger UI
Generate clients with openapi-generator:
openapi-generator-cli generate \
  -i https://api.wavis.xyz/openapi.json \
  -g go \
  -o ./wavis-go-client

Language quickstarts

import requests, base64

r = requests.post("https://api.wavis.xyz/api/v1/onboarding/temp-key")
api_key = r.json()["api_key"]

health = requests.get(
    "https://api.wavis.xyz/api/v1/health",
    headers={"Authorization": f"Bearer {api_key}"},
)
print(health.json())

Next Steps

API Reference

Endpoint-by-endpoint schemas

Webhooks

Async event delivery