Vigil

Data Processing Addendum

Last updated: 5 October 2026

The Article 28 terms under which Vigil processes personal data on your behalf. This addendum forms part of the Terms of Service and applies automatically to every customer routing traffic through the proxy — you do not need to sign anything to be covered by it.

1.Parties and scope

This addendum is between you (the Customer) and Evolmet B.V. (Vigil), and applies whenever Vigil processes personal data on your behalf under the Terms of Service.

The processor's registration details in full — the ones a due-diligence questionnaire asks for, so you do not have to write and request them:

The processorAs registered
Legal nameEvolmet B.V.
Legal formBesloten vennootschap (private limited company), Netherlands
Trade register (KvK)42006185
Registered addressSaturnusstraat 95, 2516 AG ’s-Gravenhage, Netherlands
VAT numberNL869250759B01
Contact for this addendumsam@vigil.wtf

Terms defined in the GDPR — controller, processor, personal data, processing, data subject, supervisory authority — carry their GDPR meanings here.

If this addendum conflicts with the Terms of Service on the processing of personal data, this addendum wins.

2.Roles: who is controller, who is processor

Vigil occupies two different roles, and a DPA that blurred them would be useless to you.

DataYou areVigil is
Your account: email, auth identity, plan, preferences, API key digestsThe data subjectThe controller
Telemetry from traffic you route through the proxyThe controllerThe processor

This addendum governs the second row only. For the first row — the data Vigil holds about you as our customer — we are the controller and the Privacy Policy applies instead.

You determine what traffic you send through the proxy and therefore what personal data, if any, passes through it. You are responsible for having a lawful basis for that processing and for giving your own data subjects the notice they are owed.

3.Nature and purpose of processing

Subject matter: providing the Vigil Proxy and the Vigil dashboard — observability, cost analysis, error detection, and cost optimisation for AI API traffic, such as prompt caching.

Duration: for as long as your account exists, plus the retention windows in section 11.

What processing actually consists of

Two distinct operations, and the difference between them is the substance of this document:

1. Transient processing in memory. The proxy parses each request body to locate the cacheable span of the prompt and insert cache markers — and, where history trimming or model routing runs for an agent, to tell which conversation the call belongs to, which earlier messages trimming would drop, and, for routing, how long the conversation's opening is, how many tools it defines, and whether the request needs something a cheaper model cannot handle (such as images, documents, certain tools, structured output, extended thinking, or more input or output than it supports) — and scans the model's response to detect leaked personal data and, where Vigil records how a response ended, to see how: whether it finished, stopped at a token limit, was refused, or called a tool with arguments that are not valid JSON. This is necessary to provide the service, happens in memory for the duration of the request, and is not persisted.

2. Persistent storage of metadata. One row per call, containing only the fields listed in section 4 — until the plan's monthly logged-call volume is used up, after which a call is counted but not logged. A request the proxy refuses or cannot complete leaves at most one row in a separate ledger, containing only the fields listed in section 8 of the Privacy Policy, and a problem our detectors find leaves a record of the finding, never the evidence. A score you send for a call, when we accept it, is kept as a record of its own, described in section 4 of the Privacy Policy. Beyond these, the proxy updates only your API key's last-used time; your plan's usage meter, described in section 3 of the Privacy Policy: with its counts, the meter keeps when they last changed, one SHA-256 checksum per optimised prompt shape each month, made from two of the section 4 fingerprints, and a note of any call it failed to count, or failed to count in full; and, for an optimisation that can change answers, per agent: the share of conversations it is tried on, when it first ran in Shadow mode, when Vigil last checked its trial and, when a trial does worse than the calls it is compared with, its share set to zero with when and why, and an alert saying so — with when its share, its first Shadow day or a stop last changed, how many times they have changed since it was created, and whether that alert is still to be filed. Prompt and response content is not among any of them, apart from the two disclosures in section 4.

4.Categories of data and data subjects

Data subjects: your end users, employees, or other individuals whose personal data may appear in the AI requests you route — determined entirely by you.

What is stored, per call

Usage and cost

  • Input, output, cache-read and cache-creation token counts, the input-plus-output total, and how much of the cache creation was for the one-hour cache lifetime
  • Cost in USD, and the cache-read ratio
  • How many web searches the provider billed on the call; when the call used advisor, fallback or compaction steps, how many billed model steps the provider reported, the model’s own turns included; and how much the searches and those extra steps added to the cost
  • Latency in milliseconds
  • Model and provider names. A model id is kept as the provider or your request gave it, so it can carry your cloud account number or organisation name — an AWS inference-profile ARN or an OpenAI fine-tuned model id, for example
  • How the call was priced, where recorded: the platform that served it and that platform’s own id for the model, whether it went to a global, regional or multi-region endpoint, the billing mode (for example on-demand or batch), whether the prompt was long enough to fall in a long-context price tier, and the evidence behind the rate — for example VERIFIED, read off the provider’s own price list
  • Success or error status; the error type when one occurred; and the names of any problems our detectors found on the call, even a successful one — for example pii_leak or cost_spike — never the evidence
  • The HTTP status code the provider returned — or, for a call Vigil refused, the one Vigil returned
  • The provider’s own error code when a call failed — for example authentication_error — drawn from a fixed list we recognise, or the word “unrecognized”
  • When we can tell why a call failed, a one-sentence reason in our own words, from a fixed list — for example “The provider rejected the API key as invalid”. Never the provider’s wording.
  • What the call would have cost without Vigil’s cache markers, and the difference from the bill — the saving, which can be negative; for an agent with prompt caching in Shadow mode, Vigil’s estimate of that saving; and a short code when a saving could not be worked out. Where recorded, when an optimisation changed the call, what it would have cost without Vigil’s changes — Vigil’s estimate where history trimming changed it; the bill alone where a saving could not be worked out; zero where the bill itself could not be — and zero when no optimisation changed the call

Fingerprints of your prompt shape

  • prefix_hash, system_hash, tools_order_hash — 8-character FNV-1a checksums
  • An estimated token length for the cacheable prefix
  • On OpenAI-compatible providers, where recorded, the cache key Vigil sends — or, in Shadow mode, would send — so the provider can reuse its cache: two more checksums of the same kind, one of the model with your system messages and one of the model with your tool definitions

Prompt structure — counts, lengths and a yes/no flag, plus two fragments kept verbatim: tool names and a timestamp excerpt

  • The character LENGTH of your system prompt
  • The NUMBER of tools on the request
  • The NAMES of your tools
  • Whether a timestamp was detected in the prefix
  • If one was: a short excerpt of that timestamp, capped at 32 characters
  • The token offset of your first cache marker, and the model’s minimum cacheable length

Labels and identifiers

  • The id of the Vigil account the call belongs to
  • The agent label you supply in the X-Vigil-Agent header
  • Whether the call presented a Vigil API key, and what the check found: valid, missing, not found or revoked, belonging to a different Vigil account, or the check itself failed
  • A row id and a timestamp for the call itself, and — when there was one — the request id we returned to you in the x-vigil-request-id response header: a random identifier we generate when the request arrives, so you can find the call later
  • Whether the call is Vigil’s own test traffic, decided from a fixed list of Vigil’s test agents and accounts
  • The path you called on the provider, as you sent it, never the query string — for example v1/messages. It can name your Google Cloud project and region (Vertex AI); your AWS region and model, or an inference-profile ARN that includes your AWS account number (Bedrock); or a provider’s id for a batch or a file
  • Where recorded, an identifier for the provider-side cache the call could use, which keeps one credential’s cache apart from another’s. For Google Vertex AI it is your Google Cloud project id and location, in clear. For other providers it is a one-way digest of the provider credential the request carried — on Bedrock, with the AWS region in clear — never the credential itself. The digest is two 8-character FNV-1a checksums, not encryption: it cannot be turned back into the credential, but someone who already had your API key could confirm the match, and the same API key always gives the same digest
  • Three fields reserved for a session id, a parent-call id and a trace id, which the proxy does not write. The only rows with a value in them are Vigil’s own test traffic from June 2026, each holding a random session id

Cache decision metadata

  • The cache lifetime chosen, the estimated cached span, and how many cache markers were placed
  • Where the cache markers went — the system prompt, the messages or the tools — whether the cached span stopped at a timestamp, and whether your system prompt was sent as plain text
  • Whether the call qualified for Vigil’s caching and, when Vigil did not add cache markers, why not, from a fixed list — for example your request already carried its own, part of the prompt changes on every call, the prompt was shorter than the model’s minimum, the provider caches automatically, the request was signed with AWS SigV4 so it could not be changed, or the step failed — and a broader label for that reason, such as whether it would resolve itself as the prompt grows or needs the prompt to change; with the figures behind that decision: the span measured, the model’s minimum and the model it came from, which part of the prompt changed, how much text came before a timestamp, the shape of the system prompt, and the kind of AWS credential used
  • On OpenAI-compatible providers: how the provider caches, where Vigil puts its cache key — a field in the request or a header — whether Vigil asked the provider to report token usage on a streamed call and, if not, why not, and pricing notes: why a call could not be priced, the price-list entry it was priced as when that differs from the model’s name, and whether a cache saving can be shown for that model
  • For an agent in Shadow mode, what the saving estimate rested on: the typical gap between the calls it was compared with, this one included; roughly how many calls one cache write would serve at that pace — the cache lifetime divided by that gap, capped at 10,000; how many earlier calls from the past seven days it drew on; and the span it assumed would be cached

Optimisation decisions, trials, and how the response ended

  • For each optimisation, the mode you set and the mode actually applied to the call — and, where recorded, whether the setting came from the agent, from your account default, or from Vigil’s default of Off when neither was set, and why the applied mode was lower than the one you set, from a fixed list (for example: your request switched it off with X-Vigil-Optimise or X-Vigil-Skip, your plan’s limit applied, the provider does not support it, Vigil could not verify your Vigil API key on the call, the call fell in the group a trial is compared with, or the optimisation had not yet run a full day in Shadow mode)
  • Whether Vigil added cache markers to the call, and whether your request already carried its own; and, where recorded, what each optimisation did — changed the request, would have changed it (Shadow mode), decided not to, failed and let the request go on unchanged, or did not run
  • Where recorded, for each optimisation, the saving attributed to it, whether that figure was measured or is Vigil’s estimate — Shadow mode is always an estimate, and so is what history trimming saves in On — and a short code when it could not be worked out
  • For an optimisation that can change answers — history trimming or model routing — where recorded: whether the call fell, or in Shadow mode would have fallen, in the group the optimisation is tried on or in the group it is compared with; the share of conversations set to be tried at the time; and, for each such optimisation, a number from 0 to 9,999 that decides the group and lets a trial count conversations rather than calls. It is the same on every call that shares the conversation’s first user message — or its X-Vigil-Conversation header, when you send one — and the agent label. Vigil works it out in memory from your account id, that label and that message or header; neither the message nor the header is written down. The number cannot be turned back into either, but someone who already had your account id, the label and a message could confirm the match — and with only 10,000 numbers, many messages share each one
  • Where recorded, how the model’s response ended, from a fixed list — it finished, stopped at a token limit, stopped to call a tool, stopped at a stop sequence, refused, was blocked by a content filter, or other — how many tool calls it made, how many tool calls it attempted with arguments that were not valid JSON, and whether it was refused or blocked. Never the arguments themselves, and never the words of a refusal
  • For history trimming, where recorded: how many recent turns it keeps, how many earlier turns and messages it dropped — or, in Shadow mode, would have dropped — and an estimate of how many tokens they held; when it dropped none, why, from a fixed list — for example a cache marker sat on the part it would drop, the conversation carried the model’s thinking, the conversation was too short, or the request was too large to examine; and, on providers that cache automatically, whether the provider’s cache reached past that part and what dropping it would have saved
  • For model routing, where recorded: the model it would have chosen for the call and the model your request asked for; the size band and the tool-count band of the conversation’s opening — its system prompt, tool definitions and first message — and the opening’s length in characters, never its text; the routing level the agent was at, and the lowest level that would route the call; the estimated saving, and how much prompt-cache saving switching models would give up; when it would have kept the model your request asked for, why, from a fixed list — for example the model was pinned, the request needed something the cheaper model lacks (and what, from a fixed list), or the opening’s bands are above the agent’s level. The models it chooses between are the one your request asked for and cheaper ones from the same provider: the next one down, and any further down you allow; like any model id, the one your request asked for can carry your cloud account number or organisation name. The choice depends on the conversation’s opening, not its later turns, so every call of a conversation gets the same answer — except a call the cheaper model could not take

Separately, a score you send for a call, when we accept it, is kept as a record of its own: the account, the request id, the score and when it arrived — section 4 of the Privacy Policy.

What is never stored

  • Your prompt text, apart from the tool names and timestamp excerpt disclosed separately
  • Your message content
  • The model’s responses
  • Your tool call arguments
  • Your tool schemas, or your tool descriptions beyond a timestamp excerpt
  • Your tool results
  • The text of a provider’s error message

Two disclosures we make explicitly, because a due-diligence reviewer needs them stated rather than inferred:

Tool names are stored. The names only — not descriptions, schemas, arguments, or results.

A timestamp excerpt is stored when one is detected in the system prompt or a tool description — the matched substring only, capped at 32 characters, used to identify cache-busting content. With the tool names above, this is the only prompt text retained anywhere in the system.

On the fingerprints

The prefix_hash, system_hash and tools_order_hash fields are 8-character FNV-1a checksums. These are not cryptographic hashes and we do not present them as a security control. They are four bytes, so the source prompt cannot be reconstructed from them; but a party holding both a fingerprint and a candidate prompt could verify a match. They are used only to compare requests with one another — to tell whether two share a prefix, the same system prompt or the same tool names — for example, to diagnose a cache that was missed, or to count the optimised prompt shapes your plan's limit applies to (the usage meter in section 3 of the Privacy Policy).

Special categories

Vigil is not designed for Article 9 special-category data and we ask that you do not route it through the proxy. If your use case requires it, contact us before you begin so we can agree the additional measures in writing.

5.Our obligations as processor

Vigil will:

  • Process personal data only on your documented instructions — which, for the standard service, are the Terms of Service, this addendum, and the configuration you set in the dashboard.
  • Tell you if we believe an instruction breaches the GDPR, and not carry it out until it is resolved.
  • Ensure everyone authorised to process the data is bound by confidentiality.
  • Implement the technical and organisational measures in section 7.
  • Not train models on your data, sell it, or disclose it to anyone beyond the sub-processors in section 6.
  • Assist you as described in section 9, and delete data as described in section 11.

If we are legally compelled to disclose your data, we will tell you before doing so unless the law forbids it.

6.Sub-processors

You give general authorisation for the sub-processors below. Each is bound by data protection terms no less protective than this addendum.

Sub-processorPurposeLocation
SupabaseDatabase, authentication, and auth email deliveryCentral EU (Frankfurt) · eu-central-1
CloudflareRuns the proxy at api.vigil.wtfGlobal edge network
VercelHosts the dashboard at vigil.wtfGlobal edge network
GitHubOAuth sign-in, if you use itUnited States
GoogleOAuth sign-in, if you use itUnited States
AI providers (Anthropic, OpenAI, Google, Mistral, and others)Receive the requests you route through the proxyDetermined by the provider you choose
StripePayments — subscriptions, invoices, and card details, which go to Stripe directlyUnited States / Ireland
PlausibleCookieless analytics on the public pages, if NEXT_PUBLIC_ANALYTICS_ID is setEuropean Union · Falkenstein, DE
RedditAdvertising attribution on the public pages — only if you accept advertising cookies, and only if NEXT_PUBLIC_REDDIT_PIXEL_ID is setUnited States

AI providers are sub-processors you select. The proxy forwards your request to the provider you configure. Which provider receives your data, and on what terms, is your choice and is governed by your agreement with them.

We will give you at least 30 days' notice before adding or replacing a sub-processor. If you reasonably object on data protection grounds, tell us within those 30 days and we will work to find an alternative; if we cannot, you may terminate the affected service and receive a refund of any prepaid unused period.

7.Security measures

Our Article 32 measures:

  • Tenant isolation via Row Level Security. Every table enforces auth.uid() = user_id at the database level, so isolation does not depend on application code remembering to filter.
  • Credentials stored as digests. Vigil API keys are held as SHA-256 digests, with the key's first 12 characters kept as a display prefix so keys can be told apart; raw keys are generated client-side and displayed once. The dashboard's servers never receive one, and the proxy, which receives one with each request that carries it, only checks it against the stored digest. Provider API keys are never stored either: to keep one credential's cache apart from another's, a call record can hold a one-way digest of the provider credential the request carried (for Vertex AI, the Google Cloud project id and location instead). That digest is two FNV-1a checksums, not a cryptographic hash — it cannot recover a key, but a party holding a candidate key could verify a match.
  • Encryption in transit. TLS on every hop — to the dashboard, to the proxy, to the database, and onward to AI providers.
  • Encryption at rest, provided by our database and infrastructure sub-processors.
  • Privileged credential separation. The database service-role key is held only by the proxy and server-side code, and is never exposed to a browser.
  • Data minimisation by architecture. The strongest control we have is not keeping the data: prompt and response content has no column to be stored in — the tool names and timestamp excerpt disclosed in section 4 aside — so it cannot be exposed by a misconfiguration, a bad query, or a breach.

We hold no security certifications. Vigil is not SOC 2 audited and not ISO 27001 certified. If your procurement process requires either, we do not currently meet it, and we will not claim otherwise to get through a review.

8.Breach notification

We will notify you without undue delay, and in any event within 48 hours, of becoming aware of a personal data breach affecting data we process for you — so that you can meet your own 72-hour deadline under Article 33.

The notification will describe, so far as we know it:

  • The nature of the breach and the categories and approximate number of records affected.
  • The likely consequences.
  • The measures taken or proposed to address it and mitigate its effects.
  • A contact point for more information.

Where we cannot provide all of it at once, we will send what we have and follow up as the investigation progresses, rather than delaying the first notification.

9.Assistance with your obligations

Taking account of the nature of the processing, we will assist you with Articles 32 to 36:

  • Data subject requests. If one reaches us directly, we will not respond to it ourselves — we will refer it to you without undue delay and help you answer.
  • Erasure and rectification. Deleting your account erases all telemetry we hold for you. Targeted deletion of a single individual's data is discussed in the note below.
  • Impact assessments. We will provide the information you reasonably need to complete a DPIA or a prior consultation.

An honest limit on erasure assistance. Because we do not store prompt content, we generally cannot identify an individual data subject inside our telemetry. Every row we hold for you is keyed to your Vigil account; beyond that, a stored row maps to a person only if something identifying went into a value we keep as it was sent: an agent label; a tool name; a timestamp excerpt, which is up to 32 characters matching a date, a time or a long number, so it could be a birth date or a phone number; a name or account number inside a model id, a cloud project id or a request path; or, on a refused request, the account identifier and provider as they were typed. A digest of a provider credential can also be matched by whoever holds that credential, and the prompt fingerprints in section 4, with the usage meter's checksums made from them, by whoever holds the exact prompt text they came from.

In practice this means an erasure request for one of your end users usually requires no action from us: we are not holding their personal data to erase. Where you can identify the affected records by agent label or time range, we will delete on that basis. We would rather set this expectation now than in the middle of your response deadline.

10.International transfers

The database holding customer telemetry and account records is hosted by Supabase in Central EU (Frankfurt) (eu-central-1). Data at rest therefore sits in the EU.

Processing is not EU-only, and this addendum does not represent that it is. Two flows leave the EEA by design — the proxy executes on Cloudflare's global edge network, and requests are forwarded to the AI provider the customer selects. Both are described below.

Where personal data is transferred outside the EEA, the transfer is covered by Standard Contractual Clauses or an adequacy decision applying to the receiving sub-processor.

Transfers to AI providers are directed by you. When you route to a US-based provider, your request is forwarded there and processed on their infrastructure. That transfer happens on your instruction and under your agreement with that provider — we are the conduit, not the party determining it.

Cloudflare and Vercel operate global edge networks, so processing may occur at an edge location outside the EEA. Both operate under Standard Contractual Clauses.

11.Retention and deletion

Telemetry retention is set by the customer's plan:

PlanRetention window
Free7 days
Plus30 days
Pro90 days
Supreme365 days
EnterpriseSet per contract

TODO — not yet finalised

Automatic deletion of call telemetry is not currently running. The retention sweep is implemented and tested, and its daily schedule is registered, but it operates in preview mode — the switch that lets it delete call telemetry is not set — so telemetry older than the plan window has not been deleted to date. Only refused-request records are deleted automatically, after seven days. This is stated here because a customer relying on the windows above for their own retention schedule needs to know it. It must be updated when the sweep is armed.

Deletion on termination

On termination of your account we delete the personal data processed on your behalf: call telemetry and the scores you sent for calls, detected errors, preferences, alert rules, optimisation settings, API key records, team invitations, and the monthly usage meter. This happens immediately and irreversibly when you delete your account from Settings.

We keep no backup copy for you to retrieve afterwards. If you need an export, take it before you delete — CSV export is available in Settings.

We retain data after termination only where applicable law requires it, and in that case only for the required period and purpose.

12.Audit rights

We will make available the information necessary to demonstrate compliance with Article 28, and allow and contribute to audits conducted by you or an auditor you appoint.

In practice:

  • Written security questionnaires: we will complete a reasonable one at no charge. Email the address below.
  • On-site or in-depth audits: with 30 days’ written notice, no more than once a year unless a breach or a supervisory authority requires otherwise, during business hours, and without unreasonable disruption to the service.
  • The auditor must be bound by confidentiality, and must not be a competitor of Vigil.

We have no third-party audit report to offer in place of this — see section 7. Where a documented answer will satisfy your reviewer, we would rather give you that quickly than schedule an audit.

13.Liability and governing law

The liability limits in the Terms of Service apply to this addendum, except where the GDPR does not permit them to.

This addendum is governed by the law of the Netherlands, where Evolmet B.V. is established, and the courts of The Hague have jurisdiction — which matches the Terms of Service deliberately, so a dispute about the processing and a dispute about the contract cannot end up in two different forums.

For any question about this addendum, or to request a signed copy or a completed security questionnaire, email sam@vigil.wtf.