POST /api/v1/compute/{operation}
Run a single FHE operation. Path-based variant.
Auth: TRIAL+
Request
URL operation | Description |
|---|---|
add | Element-wise addition |
multiply | Element-wise multiplication |
add-plain | Add a plaintext vector |
multiply-plain | Multiply by a plaintext vector |
negate | Element-wise negation |
rescale | Modulus reduction (consumes a level) |
rotate | Cyclic rotation of slots |
matmul | Matrix-vector multiplication |
poly-eval | Evaluate a polynomial on ciphertext |
bootstrap | Refresh noise budget (≥CKKS depth limit) |
Body schema
| Field | Type | Required | Notes |
|---|---|---|---|
key_id | string | Yes | From /keys/upload or /keys/generate |
ciphertext_ids | array<string> | Yes | 1 element for unary, 2 for binary |
plain_operand | array<float> | For *-plain ops | Plaintext vector, length = slot_count |
polynomial_coeffs | array<float> | For poly-eval | Coefficients (low→high), max 65 |
scale_stable | bool | No | Enables scale-stable multiplication |
Response — 200 OK
Response headers
| Header | Description |
|---|---|
X-Noise-Budget-Remaining | Same as noise_budget_remaining field (% of noise budget left) |
X-Noise-Budget-Warning | "true" if remaining <50% — bootstrap soon |
X-Noise-Budget-Recovery | Recovery hint, e.g. "POST /api/v1/compute/bootstrap to refresh" |
POST /api/v1/compute
Generic variant — operation in the body instead of the path.
Request
FCU costs (per operation)
Each operation has a FHE Compute Unit weight that determines billing under PAYG and quota consumption under fixed-tier plans.| Operation | FCU weight | PAYG cost (USD) |
|---|---|---|
add, negate, rescale, add-plain | 1 | $0.000002 |
multiply-plain | 2 | $0.000004 |
multiply, rotate, key_switch | 5 | $0.000010 |
poly-eval | 10 | $0.000020 |
matmul | 20 | $0.000040 |
bootstrap | 50 | $0.000100 |
infer_7b | 100 | $0.000200 |
infer_70b | 1000 | $0.002000 |
cost_jpy in the response is the FCU weight × current JPY rate.
Operation specifics
add and multiply
Element-wise. Both ciphertexts must:
- Be encrypted under the same
key_id - Have the same number of slots
- Be at the same modulus level (or use
rescalefirst)
scale_stable: true keeps the result at the same scale as the inputs (auto-rescale).
Recommended unless you’re managing the modulus chain manually.
add-plain and multiply-plain
Mix plaintext into a ciphertext.
plain_operand.length must equal slot_count.
poly-eval
Evaluate a polynomial (Horner-style) on a ciphertext. Useful for activation
functions in encrypted ML.
sin(x) ≈ x - x³/6 + x⁵/120 over the encrypted vector.
polynomial_coeffs.length ≤ 65. Higher-degree polynomials should be
decomposed into multiple poly-eval calls or use a Chebyshev expansion.
matmul
Matrix-vector multiply. The matrix is encoded as slot_count rotated copies
of the vector (BSGS — baby-step-giant-step optimization).
rotate
Cyclic rotation of slots — needed for matmul, dot-product, and any
inter-slot data movement.
rotation_steps is in plain_operand[0] if your client puts it there.)
bootstrap
Refresh the noise budget so the ciphertext can support more operations.
Expensive (~500 ms for poly_degree=8192) but unavoidable in deep circuits.
bootstrap_effective_degree: residual depth after bootstrapbootstrap_degraded:trueif precision dropped below threshold
GET /api/v1/compute/{op_id}
Poll status for an asynchronously running operation.
Auth: WRITE+
Response — 200 OK
status: "pending", "running", "completed", "cancelled", "failed".
For completed operations, the full response is in the original POST
response (not re-fetchable via GET).
DELETE /api/v1/compute/{op_id}
Cancel a pending or running operation. Best-effort — already-completed work
isn’t refunded.
Auth: WRITE+
Response — 200 OK
Common errors
| Code | Status | Meaning |
|---|---|---|
KEY_NOT_FOUND | 404 | key_id invalid |
CIPHERTEXT_NOT_FOUND | 404 | One of ciphertext_ids missing or evicted |
MISMATCHED_KEY | 400 | Ciphertexts under different keys |
MISMATCHED_LEVEL | 400 | Ciphertexts at different modulus levels (use rescale) |
NOISE_BUDGET_EXHAUSTED | 400 | Result would fail decryption — bootstrap first |
INVALID_OPERATION | 400 | operation not recognized |
MISSING_PLAIN_OPERAND | 400 | *-plain op without plain_operand |
POLYNOMIAL_TOO_LARGE | 400 | More than 65 coefficients |
Best practices
- Track noise budget. Read
X-Noise-Budget-Remainingand bootstrap when it dips below 30%. - Batch independent ops at the application level — multiple parallel
/computerequests with HTTP/2 multiplexing. - Use
scale_stable: trueunless you’re explicitly managing the modulus chain. - Prefer
multiply-plainovermultiplywhen one operand is public — 2× cheaper. - Cache ciphertext_ids client-side. Avoid re-uploading.
Next Steps
Performance
CKKS performance tuning
Webhooks
Async events for long-running compute