Skip to main content
Endpoints for managing FHE keys (cryptographic objects). For API keys (auth tokens), see Authentication API. The recommended pattern is client-side keygen + eval-key upload (FHE-blind mode). The server-side keygen endpoint is provided for backward compatibility and convenience demos.

POST /api/v1/keys/upload

Upload a client-generated public + evaluation key. The server stores no secret key — this is the FHE-blind path. Auth: TRIAL+

Request

POST /api/v1/keys/upload
Authorization: Bearer wvs_live_<key>
Content-Type: application/json

{
  "public_key": "<base64-public-key>",
  "eval_key": "<base64-evaluation-key>",
  "scheme": "rns-ckks",
  "params": {
    "poly_degree": 8192,
    "scale_bits": 40,
    "max_depth": 10,
    "security_level": "128-bit"
  }
}
FieldTypeRequiredNotes
public_keystring (base64)Yes≤2 MB
eval_keystring (base64)Yes≤10 MB
schemestringNo"ckks" or "rns-ckks" (default)
paramsobjectYesSee below

Response — 200 OK

{
  "key_id": "key_a1b2c3d4",
  "scheme": "rns-ckks",
  "slot_count": 4096,
  "created_at": "2026-04-28T12:00:00Z",
  "blind_guarantee": "Server stores only public_key and eval_key. Secret key is NOT present."
}

POST /api/v1/keys/generate

Generate keys server-side. Deprecated for production — the secret key briefly exists on the server during keygen. Prefer /keys/upload. Auth: TRIAL+

Request

POST /api/v1/keys/generate
Authorization: Bearer wvs_live_<key>
Content-Type: application/json

{
  "scheme": "rns-ckks",
  "params": {
    "poly_degree": 8192,
    "scale_bits": 40,
    "security_level": "128-bit",
    "max_depth": 10
  }
}

Parameter constraints

FieldTypeAllowed values
poly_degreeint64, 256, 4096, 8192, 16384, 32768
scale_bitsint10–50 (default 15)
security_levelstring"testing", "128-bit", "192-bit", "256-bit"
max_depthint1–14 (default 5)
poly_degree of 64 or 256 yields keys below 128-bit security and triggers a X-Security-Warning response header.

Response — 200 OK

{
  "key_id": "key_xyz789",
  "public_key": "<base64>",
  "secret_key": null,
  "eval_key": "<base64>",
  "params": {
    "scheme": "rns-ckks",
    "poly_degree": 8192,
    "modulus_chain": [60, 50, 40, ...],
    "total_q_bits": 880,
    "scale_bits": 40,
    "max_depth": 10,
    "security_bits": 128
  },
  "slot_count": 4096,
  "created_at": "2026-04-28T12:00:00Z"
}
secret_key is always null in production. To enable returning it (for local testing only), set WAVIS_ALLOW_SK_IN_RESPONSE=true on the server.

Response — 400 Bad Request

{
  "error": {
    "code": "INSUFFICIENT_SECURITY",
    "message": "poly_degree=64 with security_level=128-bit gives ~80-bit security. Use poly_degree>=4096."
  }
}

GET /api/v1/keys/{key_id}

Fetch metadata about a key. Does not return the secret key, ever. Auth: READ+ (viewer, developer, or account_admin)

Request

GET /api/v1/keys/key_xyz789
Authorization: Bearer wvs_live_<key>

Response — 200 OK

{
  "key_id": "key_xyz789",
  "scheme": "rns-ckks",
  "params": {
    "poly_degree": 8192,
    "scale_bits": 40,
    "security_bits": 128,
    "max_depth": 10
  },
  "slot_count": 4096,
  "created_at": "2026-04-28T12:00:00Z",
  "ciphertext_count": 127,
  "operation_count": 1843
}

DELETE /api/v1/keys/{key_id}

Delete a key and all ciphertexts encrypted under it. Auth: WRITE+ (developer or account_admin)

Request

DELETE /api/v1/keys/key_xyz789
Authorization: Bearer wvs_live_<key>

Response — 200 OK

{
  "key_id": "key_xyz789",
  "status": "deleted"
}
Deletion is irreversible. Cached ciphertexts encrypted under the deleted key are unrecoverable — both server-side (deleted) and client-side (undecryptable without the key).

GET /api/v1/keys

List all keys for the authenticated account. Cursor-paginated. Auth: READ+

Request

GET /api/v1/keys?limit=20&cursor=<opaque>
Authorization: Bearer wvs_live_<key>
Query paramTypeDefaultRange
limitint201–100
cursorstringopaque base64 from prior response

Response — 200 OK

{
  "items": [
    {
      "key_id": "key_a1",
      "scheme": "rns-ckks",
      "slot_count": 4096,
      "created_at": "2026-04-01T10:00:00Z"
    }
  ],
  "next_cursor": "eyJvZmZzZXQiOiAyMH0=",
  "has_more": true,
  "total_count": 42
}

Common errors

CodeStatusMeaning
INVALID_PARAMS400Parameter out of range or wrong type
INSUFFICIENT_SECURITY400Selected params give <128-bit security with security_level=128-bit
KEY_NOT_FOUND404key_id doesn’t exist or belongs to another account
PAYLOAD_TOO_LARGE413Public key >2 MB or eval key >10 MB
QUOTA_EXCEEDED402Account is over its plan quota

Best practices

  1. Always use /keys/upload for production. The endpoint that touches the secret key (/keys/generate) is for demos.
  2. One key per security boundary. Don’t reuse a key across users — if one user is compromised, they can decrypt the others.
  3. Delete keys when done. Active keys count against your storage quota and consume server memory for cached eval keys.
  4. Cache the key_id client-side. Avoid round-tripping /keys to look it up.
  5. Set parameters once and stick with them. Switching poly_degree means re-encrypting everything.

Next Steps

TFHE API

Boolean gate evaluation

Compute API

CKKS arithmetic on ciphertexts