Security and trust

Boring where it counts

Trust is a foundation here, not a compliance sprint before the enterprise deal. Everything on this page is built today and covered by tests that run before anything ships. Where we do not have something yet, this page says so.

Isolation by defaultAppend-only historyConsent from day one

Controls

How the boundary is enforced

These are the mechanisms, not the marketing words for them. Each one is something a reviewer can point at in the code.

  • Workspace isolation, deny by default

    Every query is scoped by a workspace id taken from the session or the API key, never from anything a client sends. A record in another workspace answers 404 rather than 403, so an id cannot be used to prove that something exists.

  • API keys, hashed and scoped

    Keys are stored hashed. The secret is shown once at creation and never again. Every key carries explicit scopes and separate test and live modes. A missing scope is a refusal that names the scope it wanted.

  • Signed webhooks with a closed replay window

    Each delivery carries an HMAC SHA-256 signature over a timestamp and the raw body. Verify it in constant time and reject anything older than five minutes. Failed deliveries retry with exponential backoff and every attempt is logged with its request and response.

  • Roles that hold on every read and write

    Permissions are checked on the server for every action, not hidden in the interface. A teammate without a permission gets a refusal, not a disabled button they can work around.

  • An audit trail nobody can edit

    Events are append-only rows. They are never updated and never deleted, not by us and not by a workspace admin. A correction is a new row, so the history you read is the history that happened.

  • Rate limits and idempotency on public routes

    Every public route is rate limited. Writes accept an Idempotency-Key so a retry after a timeout returns the first result instead of creating a second record.

Privacy

Consent is part of the data model

Most tools bolt consent on when a customer asks about GDPR. It has been a column on every contact here since the first migration, which changes what the product can guarantee.

  • Consent is a column, not a checkbox we remember

    Consent status, where it came from and when it was given sit on every contact from the first migration, alongside unsubscribe and suppression state. They are not a later retrofit, which is why a send can be blocked at the data layer rather than at the send layer.

  • Suppression is honored on every send

    An unsubscribe or a suppression stops sends for that person across the workspace. It is not per campaign and it is not something a bulk import can quietly override.

  • Personal data is masked before any model call

    Where the product uses a model, personal fields are masked first. New fields that describe a person go through a privacy classification before they are allowed into the schema.

Your data

Leaving is a feature, not a support ticket

A product that makes leaving hard is telling you what it thinks of its own value. Export and deletion are built in and covered by tests.

  • Export the whole workspace in one click

    Contacts, submissions and the event stream, in a format you can load somewhere else. Not a support ticket, not a CSV of the current page.

  • Deletion that sticks

    Delete a person and a tombstone remains, so a later CSV import cannot quietly bring them back. The deletion itself is recorded as an event.

Who else touches the data

The full list of processors

Every company that can see workspace data and what each one does. If this list changes, this page changes with it.

  • Edge and file storageServes the public capture endpoints and holds uploaded files, in the region the workspace was created in.
  • Managed databaseHolds workspace records, encrypted at rest, with point in time recovery.
  • Application hostingRuns the product interface and this site.
  • Email deliverySends what a workspace sends and reports what happened to it. Nothing else.
  • StripeTakes payment. Card details go to Stripe and never reach us.

Responsible disclosure

Found something? Tell us first

Email support@popziq.com with what you found and how to reproduce it. We aim to acknowledge within two business days and will keep you posted while we fix it. Please do not run tests that degrade service for other workspaces or access data that is not yours.

Every control on this page is enforced on the free plan too. You do not have to talk to anyone to see it working. The privacy policy and developer overview spell out the rest.