For AI agents
Vendor data terms as data: 63 answers for 17 vendors, each quoting its clause, and every change to 39 watched pages. Checked daily.
Point your agent here
https://terms.fru.dev/llms.txthttps://terms.fru.dev/llms-full.txtCall the API
| Method | Path | Params | Returns |
|---|---|---|---|
| GET | /api/vendors | none | Every vendor with its answers: stance, short answer, quoted clause, page URL, check state |
| GET | /api/vendors/{slug} | slug | One vendor: answers, watched pages, page changes, answer changes |
| GET | /api/answers | topic (train_business, train_consumer, retention, opt_out, zdr, subprocessors, residency), vendor, stance (no, limited, yes) | Answers across vendors for one question |
| GET | /api/changes | since (YYYY-MM-DD), vendor, limit (max 200), offset | Page changes (counts, first changed paragraph) and answer changes, newest first |
| GET | /api/changes/{id} | id | One page change with its added and removed paragraphs |
| GET | /api/documents | vendor | Watched pages: URL, kind, text hash, last checked, last changed |
| GET | /api/companies | since (YYYY-MM-DD or datetime) | Vendors keyed by companies.fru.dev slug, with dated page changes |
| GET | /api/search | q, limit (max 20) | Ranked vendors, questions and pages |
/api/vendors
curl -s "https://terms.fru.dev/api/vendors"{
"count": 17,
"vendors": [
{
"slug": "openai",
"name": "OpenAI",
"domain": "openai.com",
"products": "Model APIs, ChatGPT",
"answered": 7,
"documents": 4,
"lastChange": "2026-09-24",
"answers": [
{
"vendor": "openai",
"topic": "train_business",
"stance": "no",
"answer": "No, unless you opt in",
"quote": "By default, we do not train on any inputs or outputs from our products for business users, including ChatGPT Business, ChatGPT Enterprise, and the API.",
"doc": "openai-training-help",
"sourceUrl": "https://help.openai.com/en/articles/5722486-how-your-data-is-used-to-improve-model-performance",
"capturedAt": "2026-09-24",
"checkState": "ok",
"verifiedAt": "2026-09-24"
}
]
}
]
}/api/vendors/{slug}
curl -s "https://terms.fru.dev/api/vendors/openai"{
"vendor": {
"slug": "openai",
"name": "OpenAI",
"domain": "openai.com",
"products": "Model APIs, ChatGPT",
"answered": 7,
"documents": 4,
"lastChange": "2026-09-24"
},
"answers": [
{
"vendor": "openai",
"topic": "train_business",
"stance": "no",
"answer": "No, unless you opt in",
"quote": "By default, we do not train on any inputs or outputs from our products for business users, including ChatGPT Business, ChatGPT Enterprise, and the API.",
"doc": "openai-training-help",
"sourceUrl": "https://help.openai.com/en/articles/5722486-how-your-data-is-used-to-improve-model-performance",
"capturedAt": "2026-09-24",
"checkState": "ok",
"verifiedAt": "2026-09-24"
}
],
"documents": [
{
"id": "openai-api-data",
"vendor": "openai",
"kind": "docs",
"title": "Data controls in the OpenAI platform",
"url": "https://platform.openai.co
.../api/answers
curl -s "https://terms.fru.dev/api/answers?topic=train_business"{
"count": 14,
"answers": [
{
"vendor": "anthropic",
"topic": "train_business",
"stance": "no",
"answer": "No, unless you opt in",
"quote": "By default, we will not use your inputs or outputs from our commercial products (e.g. Claude for Work, Anthropic API, Claude Gov, etc.) to train our models.",
"doc": "anthropic-training-commercial",
"sourceUrl": "https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training",
"capturedAt": "2026-09-24",
"checkState": "ok",
"verifiedAt": "2026-09-24"
}
]
}/api/changes
curl -s "https://terms.fru.dev/api/changes?since=2026-01-01"{
"count": 194,
"changes": [
{
"id": 176,
"doc": "openrouter-zdr",
"vendor": "openrouter",
"date": "2026-09-24",
"oldHash": "e1542eb810d519d1",
"newHash": "80d4f80cf6e61ef1",
"added": 24,
"removed": 11,
"excerpt": "Zero Data Retention (ZDR) means that a provider will not store your data for any period of time. OpenRouter has privacy settings that, when enabled, only allow you to route to endpoints that have a Zero Data Retention policy. You can enforc",
"source": "live",
"sourceUrl": "https://openrouter.ai/docs/features/zdr",
"archiveUrl": "",
"affected": []
}
]
}/api/changes/{id}
curl -s "https://terms.fru.dev/api/changes/1"{
"change": {
"id": 176,
"doc": "openrouter-zdr",
"vendor": "openrouter",
"date": "2026-09-24",
"oldHash": "e1542eb810d519d1",
"newHash": "80d4f80cf6e61ef1",
"added": 24,
"removed": 11,
"excerpt": "Zero Data Retention (ZDR) means that a provider will not store your data for any period of time. OpenRouter has privacy settings that, when enabled, only allow you to route to endpoints that have a Zero Data Retention policy. You can enforc",
"source": "live",
"sourceUrl": "https://openrouter.ai/docs/features/zdr",
"archiveUrl": "",
"affected": []
},
"lines": [
{
"op": "add",
"text": "..."
}
]
}/api/documents
curl -s "https://terms.fru.dev/api/documents?vendor=anthropic"{
"count": 39,
"documents": [
{
"id": "anthropic-zdr",
"vendor": "anthropic",
"kind": "docs",
"title": "API and data retention",
"url": "https://platform.claude.com/docs/en/manage-claude/api-and-data-retention",
"via": "live",
"hash": "ae0c7912a81ed39a",
"chars": 20541,
"checkedAt": "2026-09-25 00:05:59",
"changedAt": "2026-09-24",
"state": "ok",
"note": "",
"changes": 5,
"firstSeen": "2026-05-07"
}
]
}/api/companies
curl -s "https://terms.fru.dev/api/companies?since=2026-09-01"{
"companies": [
{
"slug": "openai",
"name": "OpenAI",
"domain": "openai.com",
"site": "terms",
"url": "https://terms.fru.dev/vendors/openai",
"items": [
{
"type": "terms:page-change",
"date": "2026-06-02",
"title": "...",
"url": "..."
}
]
}
]
}/api/search
curl -s "https://terms.fru.dev/api/search?q=retention"{
"q": "retention",
"results": [
{
"id": "page:/questions/retention",
"group": "pages",
"title": "How long are API inputs kept?",
"href": "/questions/retention"
}
]
}OpenAPI 3.1: /openapi.json. Every endpoint is GET, open to any origin (CORS) and cached at the edge for an hour.
Add to your agent
System prompt line
When asked whether an AI or data vendor trains on customer data, how long it keeps inputs, or how to opt out, look it up at https://terms.fru.dev/api/answers?vendor=<slug>&topic=<topic> and quote the clause with its page URL. Say it is not legal advice. Fetch https://terms.fru.dev/llms.txt for the vendor list.Tool definition
{
"name": "fru_terms_lookup",
"description": "What an AI or data vendor says about your data: whether it trains on API or consumer data, retention, how to opt out, zero data retention, subprocessors and data residency. Each answer quotes the clause word for word with the page URL, checked daily. Source: Terms (terms.fru.dev). Not legal advice.",
"input_schema": {
"type": "object",
"properties": {
"vendor": {
"type": "string",
"description": "Vendor slug (companies.fru.dev), e.g. openai, anthropic, google, microsoft, aws, mistral-ai, cohere. List them with GET /api/vendors."
},
"topic": {
"type": "string",
"enum": [
"train_business",
"train_consumer",
"retention",
"opt_out",
"zdr",
"subprocessors",
"residency"
],
"description": "The question."
}
}
},
"endpoint": "GET https://terms.fru.dev/api/answers?vendor={vendor}&topic={topic}"
}Python
import json, urllib.request
def answers(vendor: str) -> list[dict]:
"""What one vendor says about training, retention, opt-out and more, with the quoted clause."""
url = f"https://terms.fru.dev/api/answers?vendor={vendor}"
with urllib.request.urlopen(url, timeout=20) as r:
return json.load(r)["answers"]
for a in answers("openai"):
print(a["topic"], a["answer"], a["sourceUrl"])TypeScript
type Answer = { vendor: string; topic: string; stance: 'no' | 'limited' | 'yes'; answer: string; quote: string; sourceUrl: string }
async function whoTrains(): Promise<Answer[]> {
const res = await fetch(`https://terms.fru.dev/api/answers?topic=train_business`)
if (!res.ok) throw new Error(`terms ${res.status}`)
const { answers } = (await res.json()) as { answers: Answer[] }
return answers.filter((a) => a.stance !== 'no')
}Terms
- Free to read. Please cite "Terms (terms.fru.dev)" and the vendor's page. Not legal advice.
- Responses are cached for an hour; pages are checked daily. Keep to about 60 requests a minute.
- An answer with checkState "missing" quotes a clause that was not on its page at the last check; a person is re-reading it.
- Clauses are verbatim; one that ends with an ellipsis is part of a longer sentence.