# Your Sub-Processor List Needs a URL

> An AI platform's sub-processor list is a cited document. If it lives as a section of your security page, procurement cannot cite it. What to publish, and where.

URL: https://agentsbooks.com/blog/subprocessor-list-needs-a-url
Published: 2026-10-06T00:00:00Z
Category: Trust
Tags: subprocessors, dpa, gdpr, ai compliance, vendor management, ai procurement

We had a complete sub-processor list. Every third party that touches customer
data, what it is used for, where it runs. It was accurate, it was current, and
it was reviewed. It was also, functionally, missing — because it did not have an
address.

It lived two thirds of the way down our Trust Center as a section with no
anchor and no name of its own. `/subprocessors` returned 404. So did
`/legal/subprocessors`, and `/security/subprocessors`. If you wanted the list,
you had to already be reading the page that contained it.

That is a smaller mistake than having no list, and a much easier one to make.
Here is why it matters more than it looks.

## A sub-processor list is a cited document

Marketing pages are read. Sub-processor lists are **cited**.

The difference shows up in how the URL gets used. Somebody pastes it into a
Data Processing Agreement as the address the controller will re-check. Somebody
drops it into a security questionnaire as the answer to question 34. Somebody's
vendor-management tool puts it on a 90-day review calendar. Somebody's counsel
files it with the DPA in a folder nobody opens for two years.

Every one of those uses is a promise that a URL will still resolve long after
the person who pasted it has changed jobs. A section heading cannot keep that
promise. It cannot be pasted at all.

And when a reviewer goes looking without a link, they type the convention.
Nobody searches your site structure; they try `/subprocessors`, and if that
404s a fraction of them conclude you do not publish one. We know, because that
is the conclusion an audit of our own site reached — reasonably — about a list
that was sitting there in plain sight.

**If your register is a section, give it a page.** Then redirect the spellings:
`/sub-processors`, `/legal/subprocessors`, `/security/subprocessors`,
`/trust/subprocessors`. They cost one line each and they are the ones already
written into somebody's document.

## Two copies of a list is worse than one

The second thing we found was quieter.

Our list was typed into two templates: the Trust Center page, and the
print-ready security kit a buyer saves as a PDF for procurement. Two
hand-maintained tables that had to be edited together, and nothing that
required them to agree.

They did agree. By diligence, which is not a property you can prove about a
list. GDPR Article 28(2) entitles a controller to a register that is *current*,
and "current" was not something either copy could demonstrate about itself.

The copy that matters most is the worst one to let drift. A page can be
corrected in an afternoon. A PDF that somebody saved and attached to a signed
agreement is a snapshot that outlives the page it came from — and if it was
wrong when they saved it, it stays wrong in their files.

So: one data file, one loader, and every surface renders from it. The
cheap structural test is the negative one — delete a provider from the data and
assert the page stops showing it. That is the only way, from outside, to tell a
rendered table from a re-typed one.

While wiring that up we found a third copy we had not noticed: a sentence of
prose above the table naming four model vendors by hand. Add a fifth vendor and
the table would have updated while the paragraph kept saying four. Prose drifts
exactly like tables do; it is just harder to see.

## The honest-empty-state rule

One design decision worth stating, because the obvious implementation is wrong.

If the data file fails to load, do **not** render an empty table. A platform
running on a public cloud has sub-processors, and a table showing none is not a
blank — it is a false statement that happens to be made of whitespace. We render
a referral to a human instead: here is the address, ask us and we will send the
current register the same working day.

The same rule applies one row down. A provider missing its location is dropped
from the published table with a warning in the logs, never rendered with an
empty cell. A reviewer reading a blank cell has no way to tell "we have not
filled this in" from "nowhere" — and an undisclosed recipient of customer data
is the exact thing the table exists to disclose. Better a shorter register and a
loud log line than a longer one a reviewer cannot trust.

## What's different for an AI platform

Most sub-processor guidance assumes a fixed list. An AI platform's list is
partly chosen by the customer, at runtime, after they sign.

Which model vendor processes a given request depends on which model the user
picked. Connect a key for one provider and that provider is now in the path for
your account and nobody else's. Route through a gateway and the set of vendors
reachable through it is wider than the set any single request touches.

A register that just names every vendor implies all of them see all of your
data, which is wrong and alarming. A register that names only the defaults is
wrong and reassuring, which is worse. What works is saying it plainly, per row:
*engaged only when you select this model or connect this provider's key.* Then
a reviewer can map your register onto their own configuration, which is the
thing they were trying to do.

Two more things that cost very little:

**Publish an effective date.** We promised 30 days' notice of changes to this
list for months, with no date on the page to count 30 days from. The commitment
was real and unverifiable at the same time. A date makes it checkable — which is
the point of making it.

**Publish it as JSON too.** The audience for this page is vendor-management
tooling and the people who run it. If the only format is an HTML table, someone
scrapes it once and their copy starts rotting immediately. Ours is at
`/subprocessors.json`.

## The short version

- Give the register its own URL, and redirect the conventional spellings to it.
- Keep one copy in data, render every surface from it, and test it negatively.
- Never render an empty table or a blank cell. Refer to a human instead.
- Say which rows are engaged only on customer selection.
- Date it, and serve it as JSON as well as HTML.

Ours is at [agentsbooks.com/subprocessors](https://agentsbooks.com/subprocessors),
with the machine-readable copy at
[/subprocessors.json](https://agentsbooks.com/subprocessors.json). If you are
reviewing us, that is the URL to put on your calendar.