Skip to main content
InviziPoll docs

Documentation for encrypted, anonymous workplace polling.

Answers stay ciphertext on our servers. These guides show you exactly how. Written and maintained by the team that builds it, for poll authors, workspace owners, and developers.

Documentation surfaces index with live article counts by section.

Encryption isn't a setting you turn on

ML-KEM-768 · sealed client-side · no plaintext on our servers

Start here

Three paths through the docs

Pick the role you're in today. Each path is ordered. Finish it and you'll have a working, verifiable poll.

PATH 02 · 14 MIN

Setting up your team

Roles, SSO, provisioning and folder permissions for a workspace you can hand over.

  1. 01Inviting a team member
  2. 02SSO sign-in policy & JIT provisioning
  3. 03Folders, key hierarchy & access
  4. 04Workspace settings and branding
1 articlefor owners
Start path: Setting up your team

Browse

Every article, by section

65 articles

Security & architecture

Read the encryption model before you trust it

Every response is sealed in the respondent's browser against a per-poll public key. The server stores the sealed blob and nothing else: no plaintext, no identity, no IP-linked record.

  • Client-side seal. ML-KEM-768 encapsulation plus AES-256-GCM for the payload.
  • Wrapped poll keys. Private keys are wrapped to admin devices, never held in plaintext by us.
  • Aggregate-only decryption. Results decrypt in the admin's browser above your minimum-n threshold.
What we cannot doRecover an individual answer, or map a response back to a person. By architecture, not policy. The threat model documents the residual risks too.

Read the encryption model overview →

seal-response.tsillustrative · not wire-accurate
// runs in the respondent's browser. Nothing leaves in plaintext
const pollKey = await fetchPollPublicKey(pollId);   // ML-KEM-768
const { ciphertext, sharedSecret } = await mlKem768.encapsulate(pollKey);

const sealed = await aesGcm.seal({
  key:   sharedSecret,
  data:  encode({ q1: "unlikely", q2: "…" }),
  aad:   pollId,
});

await post("/v1/responses", {
  pollId,
  kem: ciphertext,        // encapsulated secret
  payload: sealed,        // opaque blob · size varies
  identity: null,         // never persisted
});

Still stuck

Talk to the people who wrote the docs

Security review pack

Threat model, encryption artifacts and subprocessor list: everything procurement asks for, in one place.

view /security →

Docs answer the how. Security answers the whether.

If you're evaluating rather than implementing, the threat ledger is the faster read.