Skip to content

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.txt
https://terms.fru.dev/llms-full.txt

Call the API

MethodPathParamsReturns
GET/api/vendorsnoneEvery vendor with its answers: stance, short answer, quoted clause, page URL, check state
GET/api/vendors/{slug}slugOne vendor: answers, watched pages, page changes, answer changes
GET/api/answerstopic (train_business, train_consumer, retention, opt_out, zdr, subprocessors, residency), vendor, stance (no, limited, yes)Answers across vendors for one question
GET/api/changessince (YYYY-MM-DD), vendor, limit (max 200), offsetPage changes (counts, first changed paragraph) and answer changes, newest first
GET/api/changes/{id}idOne page change with its added and removed paragraphs
GET/api/documentsvendorWatched pages: URL, kind, text hash, last checked, last changed
GET/api/companiessince (YYYY-MM-DD or datetime)Vendors keyed by companies.fru.dev slug, with dated page changes
GET/api/searchq, 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.

Terms changes by email

Mondays, only in weeks when a watched page changed.

Double opt-in. Unsubscribe any time.