Skip to main content

Before you encrypt

This guide assumes you already have a fully signed request payload. Encryption is the confidentiality step between signing and submission. Do not mutate the request after signing and before encryption.

Encrypt the signed payload correctly

  1. Fetch the operator public key from GET /v2/encryption-key.
  2. Serialize the signed request payload to JSON bytes exactly as it will be submitted.
  3. Generate a fresh ephemeral private key for this submission attempt.
  4. Derive the shared secret with ECDH against the operator public key and compute keccak256(shared_secret).
  5. Use the first 16 bytes of that hash as the AES-GCM key.
  6. Generate a fresh 12-byte nonce.
  7. Prefix the plaintext request bytes with their 4-byte big-endian length.
  8. Encrypt that payload with AES-GCM.
  9. Assemble the final byte payload in the required order: ciphertext || tag || nonce || client_public_key_compressed.
  10. Submit those bytes to POST /v2/request.

Retry posture

Error classRetry posture
InvalidEncryptionRebuild fresh encryption material and resubmit
RateLimitRetry with bounded backoff and jitter
NotAcceptingRequestsPause writes, confirm operator readiness, then retry
ServiceUnavailableRetry only after the transient condition clears
SafetyFailureDo not blind-retry; fix the underlying request or account state first
Always regenerate the ephemeral key pair and AES-GCM nonce for each submission attempt. Do not reuse encryption material across retries.

Practical checks before you hit submit

  • Confirm the payload was signed before encryption, not after.
  • Confirm the request bytes were not reformatted after signing.
  • Confirm the operator public key came from the current GET /v2/encryption-key response.
  • Confirm you are posting bytes, not a JSON wrapper, to POST /v2/request.

Where builders usually go wrong

MistakeConsequence
Encrypting an unsigned requestThe request reaches the operator but still fails authorization
Mutating the request after signingSignature recovery fails even though encryption succeeded
Reusing ephemeral key material or nonceInvalid or unsafe encryption behavior
Retrying SafetyFailure unchangedRepeated deterministic rejection instead of progress

Next routes

Last modified on April 13, 2026