Data Processing Agreement
GDPR Article 28 processor terms, accepted for the company when its account is created.
Last updated: October 26, 2026
This Data Processing Agreement ("DPA") forms part of the Terms of Service between NOVIXAGENT ("Processor") and the company or other organisation for which a NovixAgent AI account is held ("Controller"). This DPA reflects the parties' agreement with regard to the processing of Personal Data under the EU General Data Protection Regulation (GDPR), the UK GDPR, and the California Consumer Privacy Act (CCPA) where applicable.
1. Definitions
- "Personal Data" means any information relating to an identified or identifiable natural person processed under this DPA.
- "Data Subject" means an end-user who interacts with the Controller's website via the NovixAgent AI widget.
- "Processing" has the meaning given in the GDPR.
- "Sub-processor" means any third party engaged by the Processor to process Personal Data.
2. Roles and Scope
The Controller determines the purposes and means of processing. The Processor processes Personal Data only on documented instructions from the Controller, including with regard to transfers of Personal Data to a third country, unless required to do so by law.
3. Nature and Purpose of Processing
- Purpose. Providing the NovixAgent AI AI chatbot service — answering end-user questions, capturing leads, generating analytics.
- Categories of Data Subjects. Visitors to the Controller's website who interact with the widget.
- Categories of Personal Data. Chat inputs, uploaded files, voluntarily provided contact information, feedback ratings, technical log data (IP, user agent, referrer, device fingerprint), coarse location (country, region, city) derived from the IP address on the Processor's own servers against an offline database (except the country on the live-chat path, which is read from the header the CDN already attaches), and any additional data fields configured by the Controller in their lead-capture integration.
- Derived Data. The Processor also stores data it derives from the above rather than receives: in particular the searchable index built from the Controller's own site content and uploaded documents, which holds each extracted passage together with its vector embedding. The Processor treats such derived data as Personal Data of the material it was derived from, and applies to it the same instructions, security measures, breach obligations and retention periods as to that material. Where a Data Subject right is exercised against a source document, the entries derived from it are withdrawn on the schedule stated in the Data Retention Policy.
- AI apps and API access. The Controller may switch on access for customers' AI apps (it is off until the Controller does, and it needs the Controller to have proved control of the site's domain), connect an AI app or assistant to its account, and issue API keys. Each is a documented instruction under item 1 of section 4. The Data Subjects are the people on whose behalf a customer's AI app contacts the Controller's site and, for connections and keys, the Controller's own users who set them up. The Personal Data is the details such an app types into the lead form or a booking request (typically name, email address, telephone number and a message), the name the app gives for itself, counters of its use, and the name, display prefix, scopes, sites and dates of each key or connection, including when it was last used and, for a key, the list of addresses allowed to use it if one is set. A question put by a customer's AI app is answered as a widget question is and is not stored as a visitor record. A lead from such an app is marked as coming from a customer's AI app, and the Processor sends no automatic follow-up or reminder to an address such an app typed; the calendar provider sends the address its own invitation or confirmation for a booking. The records of an app's conversations, with the booking requests made in them, are deleted 30 days after the conversation ends, and the daily counts of a key's or connection's requests after 90 days, on the schedule in the Data Retention Policy. The keyed digest of who asked for a booking, and the retry key the app chose, are removed a day after the conversation ends, and the keyed digest of the address used for the per-person limits no later than two days after that person's last request, except while a legal hold suspends expiry under section 4 of the Data Retention Policy; the Controller can remove a booking listed for checking from that list once it has checked it.
- Duration. For the term of the subscription and the retention period configured by the Controller, within the bounds stated below. The Controller sets two things per website: what conversation text is retained (nothing / only turns the assistant could not answer confidently / every turn) and for how long that text is kept before it is nulled. The default, the range the Controller may choose within, and the reason the upper bound is where it is — the surrounding analytics record is deleted at that point, so no longer text window could be honoured — are stated in the Data Retention Policy, which is the single place every period the Processor's own systems enforce is published. Where the Controller selects "nothing", no question or reply wording is written to storage at any point, and the same filter removes the End-User-supplied content of an analysed document — its extracted text and the filename — from the analytics row that would otherwise carry it. Two limits on that: it governs the assistant's own chat, so messages exchanged through connected messaging channels or with a human operator follow those systems' own retention; and it governs conversation wording rather than the surrounding visit record, which continues to hold the technical and coarse-location fields listed in section 3.
4. Processor Obligations
- Process Personal Data only on the Controller's documented instructions.
- Ensure that personnel authorised to process Personal Data are bound by confidentiality.
- Take all measures required pursuant to Article 32 GDPR (security of processing) — including encryption in transit, encryption at rest (disk-level for the database and cache volumes, AES-256 applied by the backup tool itself to the point-in-time recovery repository on the database host, plus AES-256-GCM for secrets and authentication credentials), role-based access controls, and an append-only audit trail of privileged actions, protected from modification through the Processor's application and retained for the period stated in the Data Retention Policy and removed only on that schedule (see section 7).
- Respect the conditions referred to in paragraphs 2 and 4 of Article 28 GDPR for engaging another processor.
- Assist the Controller in responding to Data Subject rights requests (access, erasure, rectification, portability, objection).
- Notify the Controller without undue delay (and no later than 72 hours) after becoming aware of a Personal Data breach.
- On termination of services, delete or return all Personal Data to the Controller, and delete existing copies unless law requires storage.
- Make available all information necessary to demonstrate compliance with Article 28 GDPR.
5. Sub-processors and other recipients
This section lists the parties outside the Processor's own systems that receive data processed under this DPA, as known to the Processor on the date under the title. It is divided into three groups because the Controller's position differs in each: in 5.1 the Processor holds the contract, in 5.2 the Controller does, and in 5.3 the Controller names the destination itself.
5.1 Sub-processors engaged by the Processor
The Controller authorises the Processor to engage the sub-processors listed below. The Processor shall impose the same data-protection obligations on each sub-processor by contract.
| Sub-processor | Purpose | Region |
|---|---|---|
| OpenAI | Generative AI inference (chat, embeddings, and speech synthesis for most languages) — API platform, whose terms exclude using API inputs for model training. Receives End User message text, conversation history, retrieved knowledge-base passages, the text extracted from a document the End User attached to a message, the address of the page the End User is viewing on the Controller's site (normalised to origin and path, so the query string is discarded before transmission), and the assistant reply text sent for speech synthesis. In the Processor's own help assistant, which is not mounted on a Controller's site, the signed-in user's name, email address and account identifier are sent as well. In addition to those End User inputs, OpenAI receives material belonging to the Controller itself, outside a conversation: when the Controller's knowledge base is indexed, each passage is sent together with a sample of the page or document it came from so that a short description of where it sits can be written for it, and when the Controller corrects an indexed passage in the dashboard, that corrected passage is sent together with the passage before it and the passage after it so the description can be rewritten. When the Controller's site is crawled, its pages are also sent so that the facts it states about the business (opening hours, service areas, credentials) can be extracted and the kind of business it is can be classified. Passages from the Controller's indexed content are sent so that the assistant's welcome message can be drafted, and that message is sent again to be translated into the other languages the widget offers. The custom instructions the Controller writes for the assistant are sent each time they are saved, so that their language can be identified and, where it is not English, an English version can be produced for the answering model. This applies to both the Controller's crawled pages and the documents the Controller uploads. Separately, where the Controller has switched outbound follow-ups on, an End User's lead is sent so that the follow-up message can be written: for an automatic message, the End User's first name, the topic of the enquiry and the language detected from it, and for an automatic reminder of an appointment the End User booked, also the service booked and its duration, the time and its timezone, the location, the host's name and, in an email or WhatsApp reminder, the link to reschedule or cancel; for a draft the Controller reviews before sending, also the name, what the End User asked about, the detected intent and the details the End User submitted in the lead form. | United States |
| Google (Gemini) | Generative AI inference — paid tier with no model-training on inputs. Where Gemini is the answering model it receives the same conversation inputs listed for OpenAI above. Where Gemini is the system model it receives the same Controller-side inputs described for OpenAI above, from indexing and correction to the welcome message and the custom instructions, and the lead and appointment details sent for outbound follow-ups and appointment reminders. In addition, Gemini performs higher-tier parsing of PDFs an End User attaches to a message, which means the uploaded file itself is transmitted where that parsing tier is enabled for the Controller's plan | United States / EU |
| Anthropic | Generative AI inference for chat answers only — commercial API, whose terms provide that Anthropic may not train models on customer content and incorporate Anthropic's Data Processing Addendum by reference. Where a Claude model is the answering model — assigned to the Controller's website, or standing in because the model first chosen for it was unavailable — it receives End User message text, conversation history, retrieved knowledge-base passages, the text extracted from a document the End User attached to a message, and the address of the page the End User is viewing on the Controller's site (normalised to origin and path, so the query string is discarded before transmission). In the Processor's own help assistant, which is not mounted on a Controller's site, the signed-in user's name, email address and account identifier are sent as well. It is not used for speech synthesis, embeddings or the Processor's internal model work around a conversation, so the Controller-side material described for OpenAI above does not reach it, and it receives no file: an attached document reaches it as extracted text only | Data stored at rest in the United States; by the vendor's default routing the model may run in other regions the vendor operates (read 2026-10-15) |
| Speechify | Text-to-speech audio synthesis — receives the assistant reply text, and no website, session or visitor identifier accompanies it. Which speech provider is called first is decided by the language of the reply text, which our servers detect from the text itself; the microphone and browser languages play no part. Speechify's pinned model officially covers English, German, Spanish, French, Italian and Portuguese and is called first for those; for every other supported language the reply text is sent to OpenAI's speech model first, and so is a reply whose language cannot be determined or is not on the supported list. The two are each other's fallback, so either may receive the text when the first is unavailable | United States |
| Stripe | Subscription billing, payment processing, customer portal — Controller account and billing data only | Global (PCI-DSS Level 1) |
| Resend | Transactional email (welcome, billing, lead notifications, system alerts). Where the Controller has switched outbound follow-ups on, Resend also carries the follow-up and appointment-reminder emails written for an End User to that End User's own address, so it receives the End User's email address, the subject and body of the message (written from the lead details described for OpenAI above) and, where the Controller keeps the archive copy on, a copy addressed to the Controller. Each such message carries a machine-readable header marking its text as AI-generated, which names the generating product, the model, the time of generation and a hash of the text. Separately, where the Processor sends a marketing broadcast to its own account holders — a staff-operated feature that is not available to the Controller — Resend additionally stores an audience list as a segment in the Processor's Resend workspace: the account holders' email addresses and names, rather than receiving them only in transit. That list is Controller contact data, not End User data | EU / United States |
| Zoho Desk | The helpdesk the Processor's own support mailbox is worked in. That mailbox is polled by Zoho Desk, so anything addressed to it is raised there as a ticket, and two routes address it. First, a message submitted through the marketing site's contact form under the Support topic, carrying the sender's name, email address, company and message text, together with what the notification email carrying them adds: the topic, the subject line where one was given, the submission time, the sender's IP address, the browser user-agent string, the address of the page that referred them to the form, and the identifier assigned to the submission. Of that form's topics only Support is forwarded; sales, partnership, security and general enquiries are triaged in the Processor's own console. Second, a support request raised from the help bubble embedded in the Controller's own dashboard, carrying the requester's name, email address, account identifier and a list of the workspaces they own with the status of each. Listed for completeness: it receives no End User (website visitor) data and no Controller conversation data — the in-dashboard bubble is resolved by the workspace identifier it is mounted under, which is one of the Processor's own, and a widget on a Controller's site is not — and it is therefore outside this DPA: the personal data it holds is that of whoever wrote to the Processor, for which the Processor is the controller | Determined by the Zoho account the desk runs under; not selected by the software and not established in this document |
| Hetzner Cloud | Application, database and object-storage hosting. The files the service retains — Controller knowledge-base uploads and typed notes, attachments exchanged in a live chat in either direction (the End User's to the operator and the operator's to the End User), the encrypted archive of expired audit records, and the record of each erasure described in section 7 under "Erasure survives a restore" — are stored in Hetzner Object Storage under the encryption described in section 7. A document an End User attaches to a chat message for analysis is parsed in memory and is not stored there | Germany (EU) |
| Vercel | Hosting and edge delivery of the public marketing website (not the product). Receives visitor IP addresses and request logs for that site | Global edge; the deployment pins no single region |
| Cloudflare | DNS, CDN and reverse proxy in front of the product's public hostnames, so visitor web traffic to them transits Cloudflare (IP address and country are read from its headers), while relayed voice-call audio reaches the Processor's own relay directly; also the Turnstile bot challenge on the marketing site's contact form, on its ROI calculator's request to email a projection, on the service's public endpoint for a request, made without an account, to erase what is held under an email address (no page calls it) and on the email sign-up form of the customer dashboard, whose verification transmits the challenge token together with the visitor's IP address, and, where it is shown, on its newsletter sign-up | Global edge |
| Sentry | Error monitoring with EU data residency (de.sentry.io, enforced for the product surfaces by an EU-only connect-src in the production Content-Security-Policy) and server-side PII redaction enabled. Sentry also runs inside the chat widget in the End User's browser, where it is configured without session replay and without default PII collection, so it reports diagnostic error data rather than conversation content. On the marketing site Sentry additionally collects a 10% sample of performance traces |
Germany (EU) for the product; the marketing site's Content-Security-Policy also permits Sentry's non-EU ingest hosts |
| PostHog | Product analysis of how the Controller's own staff use the dashboard. It receives one record per action taken — the action name, a short list of coded values (identifier, category, count, size band), the time, and an internal random identifier for the account. This is individual behavioural data about an identified account, not an aggregate statistic: records arrive singly and can be read back as one account holder's sequence of actions. They are forwarded from the Processor's own servers, never from the browser. PostHog runs no code in the dashboard: it is not loaded there, it places no cookie and no browser storage on anyone's device, and it receives nothing directly from a device. There is no session replay and no click recording; both were removed, together with the library that performed them. Listed for completeness — it processes no End User (website visitor) data: the chat widget does not contact it, and no screen displaying End User data produces a forwarded record containing that data. The Processor holds each record only until PostHog accepts it, and if delivery is interrupted no longer than the period stated for it in the Data Retention Policy, which is the single place every period the Processor's own systems enforce is published; PostHog retains it thereafter under the retention period configured on the Processor's project there — a setting inside PostHog's own system rather than a setting of a system the Processor runs, and therefore not among the periods that policy publishes. The Processor will state that period on request. EU cloud (Frankfurt). Property values are refused at ingest unless they are a plain identifier, category, number or flag, so a sentence, an email address and a page address do not pass; a screen is identified by an internal short name | Germany (EU) |
| Healthchecks.io | Out-of-band liveness and failure monitoring of the Processor's own infrastructure — a dead-man's switch over the job scheduler, over the alert-delivery pipeline and over the metrics collector. A ping from the metrics collector carries only the word firing or resolved and, when it reports that the product is down for everyone, the names of the alert rules. The critical check is pinged only by such an alert, labelled as a platform-wide outage, and by an hourly keepalive that carries the word resolved alone. Each other ping carries a check identifier and, where something failed, a typed fault code — never a sentence, an address or a recipient. The timestamp is applied by the vendor on receipt rather than transmitted by the Processor. Listed for completeness: it receives no Controller and no End User personal data, and therefore processes nothing under this DPA | Not stated by the vendor. Its privacy policy names Hetzner as the sub-processor hosting the service and refers to transfers outside the EEA without naming a country (read 2026-08-25) |
| Have I Been Pwned (Pwned Passwords) | Checking a new password against known data breaches when an account holder or a member of the Processor's staff sets or changes one. The password is hashed on the Processor's server and only the first five characters of that hash are sent; the service answers with every breached hash sharing those characters, padded so that the size of the answer reveals nothing, and the comparison is made on the Processor's server. The password, the full hash, the account and the email address never leave the Processor's systems. Listed for completeness: it receives no Controller and no End User personal data, and therefore processes nothing under this DPA | Not established in this document |
| Browser push services (Google, Apple, Mozilla and other browser vendors) | Delivery of missed-chat notifications to the Controller's operators. The notification body — which contains a preview of the End User's message — is encrypted end-to-end to the operator's device under the Web Push standard, so the push service relays it without being able to read it. Delivery metadata (device endpoint, timing) is visible to that service | Determined by the browser the operator uses; not selectable by either party |
| Google Analytics 4 | Website analytics on the marketing site only, with Consent Mode v2 — the script is not loaded and no data is sent until Analytics cookies are accepted, IP anonymised, advertising and ad-personalisation signals disabled | United States |
| Formbricks (optional) | Feedback surveys on the marketing site. Surveys presented unprompted are gated behind analytics consent; the Feedback button is not, on the ePrivacy Art. 5(3) basis that the visitor explicitly requested the service — its cookies are placed on that click. Disabled entirely unless a workspace is configured | Formbricks Cloud (app.formbricks.com) by default; a self-hosted origin can be substituted by configuration. The hosting region of the workspace in use is not established in this document |
| FirstPromoter (optional) | Partner and affiliate attribution and commission accounting for the Processor's partner programme. Loads only where a partner programme is configured, and is disabled by default. It receives, from the visitor's browser on the marketing site and only after the visitor grants the marketing cookie category, the request for its tracker script and the click on a partner's link, together with what such a request carries (the IP address and browser details); the fields its script sends beyond that are not listed in the vendor's documentation and are not established in this document. It receives, through its own connection to the Processor's Stripe account, the paying account holder's email address (the one on the Controller's Stripe customer, which changes to the new owner's address when the company changes owner), a pseudonymous account identifier (fp_uid, the user id of the account that owned the company when its first payment completed, which the Processor writes to the Stripe customer once, when the first payment of the company completes, because Stripe itself creates that customer during the payment; a write that Stripe refuses is repeated at the company's next completed checkout or paid invoice until it is accepted, and once written it is not written again, so a change of owner does not move it) and the amounts and identifiers of the invoices of each website of the company; the permissions that connection asks for are set by the vendor and are not established in this document. It receives from the Processor's servers, for a partner the Processor has approved, the partner's email address, name, website, country, company name and the partner's user id, and, for a client who accepted that partner's invitation, the client's email address, the same account identifier and the partner's referral identifier. When a partner's account is erased, the Processor removes the partner's record there: it is deleted if it earned no commission and archived if it earned one, because the financial history stays. When an account other than a partner's is erased, the Processor does not send it a request to erase the record it holds of that person, whether that is a client registered under a partner or an account holder who paid; the record stays with it for the periods stated below. It receives no End User (website visitor) data and no Controller conversation data. It keeps its copy for the periods its own privacy page states, 2 years for expired trial and cancelled users and 5 years for the rest, and describes itself as a processor for its customers that provides a data processing agreement to paying customers on request (read 2026-10-18) |
Not stated by the vendor |
| YouTube (Google) | Playback of the product tour video on the marketing site. Nothing is requested from Google until the visitor presses play; that press loads the video from the privacy-enhanced host youtube-nocookie.com and the player script from www.youtube.com, which is an ordinary Google domain. No End User data is involved — this is the marketing site, not the product |
Global |
Implemented but not engaged. Two providers are present in the Processor's software and are named here so that the list above remains a register of actual transfers rather than of possible ones. Neither is enabled on the deployment the Processor operates, and neither receives Controller or End User personal data:
- Cohere — search re-ranking. If enabled it would receive the End User query and candidate knowledge-base passages. Its absence does not remove that step: how retrieved passages are ordered while no dedicated re-ranking service is configured, and which sub-processors receive them, is set out under 5.1.1 below. No recipient beyond the register above is added by its absence.
- Retell AI — outbound AI voice calls. If enabled it would receive the End User's telephone number and a spoken script naming the End User, the service and the appointment.
Enabling either is the addition of a sub-processor, and carries the advance notice and right to object stated at the end of this section.
5.1.1 Ordering of retrieved passages
Every search orders its results, and no configuration hands the retrieved passages to the answering model in the order the database returned them. That ordering always includes a first stage, and on some searches a second one follows it.
The first stage is a scoring pass carried out inside the Processor's own service. It is carried out on every search, it re-orders the candidate passages, and it transmits nothing.
The second stage is not carried out on every search. Where a dedicated re-ranking service is configured for the deployment, that service carries it out and receives the End User query and the candidate passages; it is not engaged where the ordering step's share of the answer-time budget is already spent, the Controller's plan does not include that stage, the plan's monthly allowance for it is zero, that monthly allowance is already spent, the search returned no more than one passage or the plan engages it selectively and the leading candidates already score far enough apart.
Where none is configured, the second stage is carried out instead by the internal model the Processor runs for the work around a conversation rather than for answering it; it is not asked where the ordering step's share of the answer-time budget is already spent or the search returned no more than five passages. When it is asked, that model receives the End User query together with at most twelve candidate passages, each truncated to its first 300 characters. It runs on OpenAI and Google (Gemini), OpenAI being attempted first and the other standing as its failover, so either may receive that request.
Where the second stage is not carried out, the order established by the first stage is the order the answering model is given, and neither the End User query nor the retrieved passages leave the Processor's service for either recipient named above.
5.2 Integrations engaged on the Controller's instruction
These providers are engaged only where the Controller connects them, against credentials the Controller supplies, and into an account that belongs to the Controller. The Controller's own agreement with that provider governs the processing carried out there. Where an integration is not connected, no data reaches it.
| Provider | Data transmitted | Region |
|---|---|---|
| Cal.com | End User name, email address, phone number and time zone; the meeting note, which opens with "Booked via" and the web address of the Controller's website (its host name) and goes on with the assistant's own note where there is one (the note is cut at 500 characters); the Controller's website identifier and web address | United States (api.cal.com) or EU (api.cal.eu), per the region configured on the Controller's integration |
| Calendly | End User name, email address and time zone. No phone number and no meeting note are transmitted | Determined by the vendor; the integration exposes no region selection |
| Meta Platforms — WhatsApp Business, Messenger, Instagram | Where the Controller connects a messaging channel, the entire conversation travels over that channel: the End User's channel identifier (WhatsApp telephone number, or the page-scoped Messenger / Instagram identifier) and the full text of the messages exchanged. A second, outbound path exists and is disclosed separately because the inbound framing does not cover it: where the Controller has connected WhatsApp and the outbound channel is enabled for the deployment, the Processor sends a template message to an End User's telephone number obtained from a booking or lead captured elsewhere, so that number and the template variables reach Meta for a person who had not contacted the Controller on that channel | Not established. Meta's Cloud API developer documentation describes encryption in transit and at rest but does not disclose a hosting region. For WhatsApp only, Meta lets each business phone number choose a region where its message data is stored at rest; the Processor's integration does not choose one |
| Slack | Captured lead details — the fields of the lead form, which typically include name, email address and telephone number — posted into the Controller's workspace | Determined by the Controller's own Slack workspace. Slack's default storage location is the United States; a workspace on Slack's data-residency plan may store message data elsewhere |
| Shopify | Order lookups requested by an End User: the order number and email address the End User supplies are sent to the merchant's store as a search query, and order, fulfilment and tracking details are returned | The merchant's own Shopify store; the integration selects no region |
| An AI app or assistant the Controller connects | What the app requests within the sites and kinds of data the Controller allowed when it connected the app: this can include the contact details in leads, conversation transcripts, live-chat messages, analytics and knowledge-base content. A question the app puts to the site's assistant is answered by the providers in 5.1, and a change it suggests to the knowledge base is held until the Controller approves it | Determined by the provider of the app; the integration exposes no region selection |
| Google (single sign-on) | Where the Controller signs in with Google, the sign-in identity is exchanged with Google. No End User data is involved | Determined by the vendor |
Google Calendar is not connectable where the deployment has not enabled it. The Processor's software implements it, but the connection path is exposed only where the deployment has enabled it: where it has not, a Controller cannot link a Google calendar, no booking is transmitted to one, and Google Calendar receives no Controller or End User personal data. Cal.com and Calendly serve the same purpose and are listed above. Were it offered, it would be added to the table above with the notice stated at the end of this section.
The Processor does not choose, engage or hold a contract with the provider of an AI app or assistant that the Controller connects, so that provider is listed here as a recipient on the Controller's instruction and not in 5.1. A connection is personal to the person who allowed it, is limited to what that person's account may do, lasts 90 days unless renewed, and can be ended by that person whenever they choose; it ends when that person's account is erased.
5.3 Destinations designated by the Controller
The Controller may direct data to an endpoint of its own choosing. The recipient is therefore not known to the Processor in advance and cannot be enumerated here; the Controller is responsible for the destination it configures and for any onward processing there. Lead-webhook deliveries are signed (HMAC-SHA256); a custom action's request is not signed and carries only the headers the Controller configured for it. Both are sent over TLS and validated against the SSRF protections described in section 7.
| Mechanism | Data transmitted | Region |
|---|---|---|
| Lead webhook | A payload containing the full lead form data — whatever fields the Controller configured, typically name, email address and telephone number — with the event type lead.captured, the website and session identifiers, the lead identifier (left out if the lead could not be stored), the form's name, and the time it was sent. Failed deliveries are retried from the dead-letter queue with the same payload. The product offers ready-made presets for Zapier, Make, n8n, Slack and Discord alongside a free-form HTTPS endpoint. Zapier, Make, n8n and a free-form endpoint receive that payload unchanged. An address on Slack's or Discord's incoming-webhook service — which is what the Slack and Discord presets deliver to — receives a plain-text summary instead: a title naming the form, the form's field labels and the visitor's non-empty answers, each answer shortened to 500 characters and the message to 3,000 characters for Slack and 2,000 for Discord, without the website, session or lead identifiers |
The Controller's endpoint. A preset therefore places the data with the vendor the Controller selected, under that vendor's own terms |
| Custom actions | Values the assistant extracted from the conversation, as declared by the action the Controller defined, sent to the endpoint that action names | The Controller's endpoint |
| API key | What the key's scopes cover on the sites it reaches: the lead form data of leads and their export, conversation transcripts, analytics, knowledge-base content, live-chat messages, the records of failed webhook deliveries (with the lead answers they carry only for a key that also reads leads), and the widget settings where the scopes allow them to be changed. A key does not add or change a webhook destination. The holder is the integrator the Controller gave the key to | The holder's own systems |
The meeting note referenced in 5.2 and the custom-action values in 5.3 are free text the assistant composes from the conversation, so the Controller should treat them as capable of carrying whatever the End User disclosed in that conversation.
The current list is also published in the Privacy Policy. The Processor shall notify the Controller of any intended changes concerning the addition or replacement of sub-processors with reasonable advance notice. The Controller may object to such a change by writing to support@novixagent.ai within that notice period and giving its reasons. The parties will try to resolve the objection; if it is not resolved, the Controller may terminate by cancelling its subscriptions and closing its account. The dashboard has no control for objecting; the written objection is the process.
5.4 Recipients neither party engages
One transfer happens under this agreement that neither party contracts for, and it is recorded here because omitting it would make section 5 read as exhaustive when it is not.
| Recipient | What it receives, and why neither party controls it |
|---|---|
| The End User's browser vendor (Google for Chrome; for other browsers, whichever speech service the browser's maker uses) | Where the Controller has enabled voice input, the End User may dictate a message. The browser captures the audio and transmits it directly to its own vendor's speech service; it does not traverse the Processor's systems, and the Processor receives only the resulting text once the End User sends the message. Which vendor receives it follows from the browser the End User chose. Neither the Controller nor the Processor can select it, route it elsewhere, or disable it below the level of switching voice input off entirely. By default browsers perform the recognition on a server rather than on the device, and the service does not request on-device recognition |
This is not a sub-processor of the Processor: there is no contract to flow down, no instruction to give, and no audit right to grant. It is disclosed so that the Controller, who decides whether to offer voice input, can account for it.
Note for readers of the table in 5.1: browser-to-browser voice calls are connected through the Processor's own relay rather than a third-party service, so the table names no separate provider for them — the hosting and network entries above apply to it as they do to the rest of the service. That absence should not be read as a statement that no audio ever reaches a third party: where the Controller enables outbound AI voice calls or voice input, the recipients named in 5.1 and 5.4 do receive audio.
6. International Transfers
Where Personal Data is transferred outside the EEA/UK, the parties rely on the European Commission's Standard Contractual Clauses (2021) or, where applicable, the EU-US Data Privacy Framework. The Processor implements supplementary technical measures (encryption in transit, encryption at rest, pseudonymisation, payload minimisation) to ensure an equivalent level of protection.
7. Security Measures
The Processor maintains the following technical and organisational measures:
- Encryption in transit. Client traffic is served over HTTPS: the Processor's edge network terminates the client's connection, and the Processor's servers accept only TLS 1.2 or higher and answer a plain HTTP request for a public hostname with a redirect to HTTPS. The edge network accepts a client connection only at TLS 1.2 or higher. Outbound webhook deliveries use TLS 1.2 or higher; the webhook case is enforced by refusing any destination scheme other than
https. Calls between the Processor's own services do not traverse the public internet: they run inside a private network that is not externally routable. For the Processor's own service-to-service API calls, integrity and origin are established by request signing (below) rather than by a second transport-encryption hop. The remaining internal traffic is not signed, and what protects it differs by destination: the database and cache connections rely on network isolation and on credentials, while dispatch to the page-fetching service relies on the isolation and on a shared token that service requires on every request except its health check — it is reachable only from inside the private network. - Encryption at rest (disk-level). The database and cache volumes reside on a LUKS2 / AES-256-XTS encrypted volume, auto-unlocked at boot.
- Encryption at rest (object storage). Uploaded files are not held on that volume. They reside in object storage under SSE-C with AES-256: the Processor supplies the key on every write and every read, the storage provider discards it after each request and retains no copy, and the deployment refuses to start unless the key is configured. Because the provider holds no key, it holds no means of reading the objects at rest.
- Encryption at rest for secrets (application-level). Webhook authentication credentials, stored integration tokens, and the webhook destination address (both the configured endpoint and the dead-letter record of where a failed delivery was headed) are additionally encrypted with AES-256-GCM. The credentials and the destination address the Controller supplies are encrypted by the application before they are written, and that write is fail-closed: with no encryption key configured the write is refused, and a row is not stored with the value in clear. One value is sealed after the fact rather than before, and it is stated rather than left to be found — the outbound signing secret generated for a new integration is created by the database itself, and a convergence sweep running at six-hour intervals encrypts it, so a freshly created secret may be stored unsealed for at most that interval. The encryption key is held in configuration, separate from the ciphertext store.
- Encrypted backups. Off-site backups are encrypted by borg in its
repokey-blake2mode — AES-256 for confidentiality and a BLAKE2b-256 authentication tag per chunk, so modification of the stored archive is detected rather than restored — on isolated storage under a separate account. The repository key resides within the repository and is unusable without a passphrase; that passphrase is held on the Processor's own host and in the Processor's password manager and is never disclosed to the storage provider, which therefore holds no means of reading the archive it stores. Point-in-time recovery runs from a continuously archived repository on the database host; the off-site copy is a periodic archive and recovers to the last shipped archive rather than to an arbitrary moment. Restores are exercised by restoring a real database and verifying row counts, not by checking that backup jobs ran: the off-site copy is exercised by restoring from it in that way. A point-in-time restore from the on-host repository has been rehearsed once, in a drill whose record states no target time and no comparison against production, and the time to rebuild on a new host has not been measured, which is why no recovery time is committed for the loss of the host itself. - Erasure survives a restore. Each erasure the Processor performs — of an account, of an address through the erasure link, and of a deleted workspace — is also recorded in encrypted object storage outside the database: a workspace by its identifier, an erasure by address with the address inside the encrypted record, and an account both by its identifier and, where the account had an email address, with that address inside an encrypted record of its own. When a database is restored from a backup, the service applies the recorded erasures again as it starts and hourly after that, except where a legal hold now covers the data, and reports the ones it could not apply. Each record is kept for the period the Data Retention Policy sets for it, longer than the oldest backup, and then deleted. The records are held in one copy, in the same object storage as the uploaded files and not yet copied elsewhere, so a loss of that storage loses them, and a database restored after such a loss has no record of which erasures to apply again.
- Service-to-service authentication. Internal API calls between our own services use HMAC-SHA256 signed requests with timestamp anti-replay, so their secrets do not travel as plaintext bearer tokens. The one exception is the page-fetching service, which accepts only a shared bearer token; that token travels inside the private network described above.
- Append-only audit trail with a defined retention period. Privileged actions are written to an append-only
audit_logsstore. A database-level trigger rejects any attempt to modify or delete a record, and the runtime database role holds no update, delete or truncate privilege on it, so no request reaching the application can alter the trail. That protection does not by itself detect a change made with the database owner's credentials, and the Processor does not promise to detect one. Audit-write failures are independently alerted. Records are retained for the period stated in the Data Retention Policy: a period during which they remain searchable, followed by a further period in an encrypted archive, after which they are removed. Removal happens only on that schedule, only after the archive has been written and verified, and never as a result of any action taken through the Processor's application or by the Controller. - Role-based access control. Administrative access is gated behind named roles (Administrator, Supreme Administrator, Support Agent, Marketing Agent, Client) and time-bound impersonation grants for support scenarios, with grant lifetimes bounded in the database itself rather than only in application code. Support Agent, Marketing Agent and Client hold enumerated, least-privilege permission sets. The two administrator roles currently hold a wildcard permission rather than an enumerated set — stated here rather than left to be discovered, since it is the difference between "least privilege throughout" and "least privilege for every role that is not an administrator". Narrowing them into enumerated sub-administrator roles is planned work. Within a Controller's own account, teammates hold one of two fixed kinds: an operator answers chats and sees the screens the owner allows, and a delegate does not answer chats, works within a fixed set of sections and must have a second factor. Company-defined roles are not yet offered. Every staff account carries a mandatory second factor: after the password is accepted, an account with no confirmed factor is intercepted and confined to the enrolment routes alone — it cannot reach the application, not even the list of sections it would otherwise be entitled to — until a factor is confirmed, and a factor is required again before impersonation or break-glass access. Controller accounts may enable the same protection voluntarily. Outside impersonation, support personnel may additionally watch the live processing status of a site they name — each such feed covers one named site, and a staff member may hold more than one feed open at once up to a configured ceiling, so this bounds what a single feed carries rather than how many a person may open — crawl and indexing progress only. That feed excludes conversation content, captured leads, operator identities, and integration diagnostics. The staff member names the site; what the server decides is whether that credential is entitled to watch a site outside its own tenant, and a caller without that entitlement — or one acting under an impersonation session — is refused outright. Every observation writes an audit row identifying the staff member and the site.
- Machine credentials (API keys and AI-app connections). An API key is shown once, when it is made; the Processor keeps a digest of it, its name, a short display prefix, its scopes, its sites, the list of addresses allowed to use it if one is set, and its dates, including when it was last used, and refuses it on a site or for a scope outside those. Creating a key, and allowing an AI app to connect, asks for the account password and for the second-factor code where one is enrolled, and a scope is limited by what the issuing account may do. A key belongs to the Controller's workspace and not to the person who made it: it stays when ownership of the workspace changes hands, and the incoming owner is emailed the list of keys that others issued so that they can revoke what they do not recognise. A connection of an AI app is personal to the person who allowed it. Revoking a key or connection, rolling a key, renewing a connection, the end of a connection's 90 days and closing the account each write a row to the audit trail that names it by identifier and a code for the reason, without the secret. Erasing a person ends the keys of the workspaces they own and the connections they allowed, and removes their name as the issuer of keys in workspaces others own, which stay with their workspace. The daily counts of a key's or connection's requests are kept for 90 days, and the record of an ended key or connection, without the secret, for 24 months so that an audit entry naming it still resolves.
- Network isolation. Backend services run inside a private Docker network. Database, cache, and inference endpoints are not exposed to the public internet.
- PII masking (defence in depth). Personal data is masked at more than one layer. Operational telemetry is masked before logs leave the application. The same masking is applied server-side to conversation content (visitor questions and assistant replies) before it is surfaced to internal support tooling, and an independent least-privilege response whitelist excludes financial and business fields. What that masking replaces, and what it leaves as written, is set out under What the masking recognises below. Captured lead submissions are reduced field by field wherever support tooling shows them to a reader who does not own the site: the lead list and its export, a failed webhook delivery, and a chat transcript read on screen on the support desk, or by a platform administrator on the Controller's conversations route, on screen or as a downloaded file. The reduction shows an answer only where it is a choice from the form catalogue's fixed list, a date or a time as the form's date and time pickers record it, a whole number of at most six digits or a yes or no, under a catalogue question the Controller kept as worded; shows an answer to an identifying catalogue question (the email question or any of those listed next) only where it is a whole email address, and then masked (
j***@example.com), and withholds an email address in any other answer with that answer; and withholds every other answer — names, telephone numbers, street addresses, cities, postal codes, company names, job titles, websites, order numbers, a student's age, free text, every field the Controller defined and every answer to a catalogue question the Controller reworded — each replaced by a marker naming the reason. What a failed webhook delivery keeps, and which captured answers a transcript is compared against, are set out in the two paragraphs after this item. Each such read writes an audit record naming the staff member and the site (for a lead list or export covering every site, each site whose leads it contained; none for a failed delivery whose site has since been deleted) with the number of answers withheld and masked (for a transcript, also the number of messages withheld), never the answers themselves. Support personnel therefore receive conversation text with these masks applied, and personal data a visitor typed that none of them recognises — a name never given in a lead form, for example — reaches them as typed; a support search across conversations reads a fixed number of the most recent End User questions in the period searched, chosen by time alone, each as support tooling shows it after these masks and the lead-answer comparison, decides which conversations it returns and their number on that text alone, lists them by when each conversation started, and requires every word typed (a leading minus sign or the word "or" is read as a word), so neither a result nor a missing one can confirm a value they hide; and unmasked content is reachable only through a separate, MFA-gated, audited support workflow that notifies the Controller. Sentry events undergo additional sanitisation (body / query-string / cookie removal, UUID masking in URLs) prior to transmission.
A failed webhook delivery keeps its event type, its website, lead and session identifiers, form name, source channel, whether a person was asked for and send time, and the delivery record (failure time, attempt count, error class, receiver HTTP status, and the names but not the values of configured authentication headers), withholds any other key of the payload, and is withheld whole when it carries the answers as prose (a Slack or Discord delivery).
In a transcript, the answers compared are those captured in lead forms during that same conversation, at most its 50 most recent submissions, and a conversation message repeating, as it was recorded, a captured answer this reduction withholds or masks is withheld whole, replaced by a marker naming the reason; case, spacing and punctuation are ignored in the comparison. So is a message containing a word of at least three characters, digits counting as characters, of an identifying answer (name, email address before the @, telephone number, street address, city, postal code, company name, job title, website, order number, a student's age), or a run of at least seven digits that is part of, or contains, the digits of an answer it withholds or masks; only those identifying answers are looked for word by word, any other answer as a whole and by its digits. A word of an identifying answer written in Thai, Chinese, Japanese or Korean with an ending attached is found even inside a longer run of letters, as names are usually written there, if it is at least two characters long; any other word, and any other answer, is found only where spaces or punctuation set it apart from the rest of the message, a vowel sign counting as part of a word (as in Hindi or Bengali). Digits are compared whatever script they are written in. Not looked for, so a message repeating one of them is shown as written: an answer captured in a different conversation; a word of an identifying answer shorter than three characters; any other answer (free text, a Controller-defined field, an answer under a reworded catalogue question) that is a single word shorter than four characters or only a number of fewer than seven digits; a yes or no answer; and a fixed-list choice of the form catalogue, which the reduction withholds only under a reworded question; an answer the assistant recorded in a spelling the visitor did not type is not recognised either.
What the masking recognises. In conversation content surfaced to support tooling, in structured logs and in server-side error reports, the masking replaces email addresses in Latin letters (jane.doe@example.com), with an accented letter before the @ (müller@example.de), with accented letters in the domain (jöhn.doe@exämple.de), inside a web address (a=bea.ch@d.com) and with letters of another script before the @ (иван.петров@пример.рф); telephone numbers with a country code and a bracketed trunk zero (+44 (0) 20 7946 0958), in national groups (020 7946 0958), as two groups of four digits (2123 4567), in dotted pairs (06.12.34.56.78), with a slash after the area code (0151/23456789), in groups of 3-3-4 digits joined by dashes (415-555-1234), after other digits (1 2 3 4 5 6 0170 7654321), written two in a row (0170 7654321 0170 1234567), written two in a row around a slash (030 1234567 / 0170 7654321) and in another script's digits (+٤٤ ٢٠ ٧٩٤٦ ٠٩٥٨); card numbers of 13 to 19 digits even in a list (4111111111111111), joined to a word (card4111111111111111), stored as a number in structured data and in another script's digits; other long numbers of twenty digits in groups of four (1234 5678 9012 3456 7890); access tokens written after the word Bearer. A masked email address reads like j***@example.com. It leaves as written a telephone number in four dotted groups with no plus sign (44.20.7946.0958) or written as ten digits with no space or separator (4155551234); a long number of eleven digits written together (12345678901) or of thirty-two digits written together. Because they read as one of those, it also replaces order and ticket numbers whose digits are grouped like a telephone number (INV2026-000123); decimal numbers with four digits either side of a point (1234.5678) and with a long fraction after a decimal comma; dates and times written as a count of milliseconds (1755387688123). Error reports sent from a browser are masked the same way, except that they also replace record identifiers in the standard hyphenated form (550e8400-e29b-41d4-a716-446655440000) and of 32 or more hexadecimal characters even with a card number inside it.
- SSRF protection. All outbound URLs (crawler targets, webhook receivers) are validated against an allow-list of safe schemes and rejected if they point to private network ranges.
- Abuse prevention. Layered rate limiting per-IP, per-fingerprint, and per-website, backed by Redis with atomic sliding-window counters; CSRF protection on state-changing requests; bot challenges (Cloudflare Turnstile) on the marketing site's contact form, on its ROI calculator's request to email a projection and, where it is shown, on its newsletter sign-up, and on the service's public endpoint for a request, made without an account, to erase what is held under an email address (no page calls it), and on the email sign-up form of the customer dashboard.
- Dead-letter queue for webhooks. Outbound webhook deliveries that fail are persisted, retried with exponential back-off (5 min → 30 min → 2 h → 12 h → 24 h), and visible to both the Controller and our customer-success team; the team reads the lead answers in them reduced as described under PII masking, and does not receive the destination address or its host, only whether the delivery is a signed event, a Slack message or a Discord message; the address is reachable only through the MFA-gated, audited support workflow described under PII masking.
- Incident response. Documented escalation procedure; 72-hour breach notification to Controllers.
8. Audits and Inspections
The Controller may, on 30 days' written notice and no more than once per year, request reasonable information to verify the Processor's compliance with this DPA. The Processor will respond with the technical and organisational measures in place at that time and may, when available in the future, satisfy such requests with third-party audit reports (e.g. SOC 2, ISO 27001).
9. Liability and Term
The liability of each party under this DPA is subject to the limitations set out in the Terms of Service. This DPA remains in force as long as the Processor processes Personal Data on behalf of the Controller.
10. Execution
The person who creates a NovixAgent AI account accepts this DPA on the Controller's behalf by ticking the box on the sign-up form, together with the Terms of Service; the form does not create an account until it is ticked. The acceptance is recorded once that person confirms the email address through the link the Processor sends and enters the password chosen at sign-up, and not on a password reset; the record holds the Controller, the account that accepted, the revision (the date under the title and the code described in section 11) and the time the sign-up form was received. An account created through Google or another single sign-on provider does not pass through the form, and its owner accepts in the dashboard as section 11 describes, once the account holds its first website. For questions about the DPA or specific contractual requirements (e.g. enterprise security questionnaires, data-residency commitments), contact support@novixagent.ai.
11. Changes to this DPA
This DPA carries a revision: the date under the title together with a short code that the Processor's publishing tooling works out from the English text of the DPA as published, including the text the page fills in from the product itself. An acceptance counts only for the date and code recorded with it. A change to the published English text therefore gives the DPA a new revision, and the Controller is asked to accept it, whether or not the date moves and whether the change alters the parties' rights or obligations or only corrects or clarifies the wording; the date moves for a change that alters them. A change to a translation alone leaves the revision as it was.
A new revision is accepted for the Controller by the owner of its account, in a window the dashboard shows, which stays open until the owner accepts or signs out. Until the owner accepts:
- the revision the Controller last accepted continues to apply;
- the window covers the dashboard's screens other than Workspaces, Account and Documentation, so the owner can still manage or cancel a subscription, export or delete a workspace, close the account, and read this DPA;
- processing continues: the widget, messaging channels, API keys and connected AI apps keep working, and subscriptions keep renewing;
- a Controller that does not accept the new revision can terminate by cancelling its subscriptions and closing its account, without accepting it first; on termination, section 4 item 7 applies.
Only the owner of the account is asked, and only while the account holds at least one website, including a website in its recovery window after deletion. Teammates who work in the account are not asked and are not stopped. When the Processor's support staff work in an account on its owner's behalf, the window is not shown to them, and an acceptance sent while they do so is refused.