Skip to main content

Developers

Canadian privacy data, as an API and MCP server

Enforcement actions, a plain-language privacy glossary, the Quebec Law 25 checklist, a cookie and tracker knowledge base, and the AI Crawler Registry, served as JSON and as MCP tools. Free, read-only, and usable without an account.

Quickstart

No key needed for the first 2,000 calls a day. Try it:

curl "https://movahedi.ca/api/v1/enforcement?regulator=cai&per_page=5"

The response is wrapped in a small envelope: data holds the payload, meta holds pagination, lang is always "en".

Endpoints

MethodPathWhat it returns
GET/api/v1/enforcementVerified CAI and OPC enforcement actions (filter by regulator, year, q)
GET/api/v1/enforcement/:idOne enforcement action, full record
GET/api/v1/glossaryPrivacy glossary terms (filter by q, letter)
GET/api/v1/glossary/:termOne glossary definition by slug
GET/api/v1/law25/checklistQuebec Law 25 requirements (filter by category)
GET/api/v1/cookiesCookie and tracker patterns (filter by q, vendor)
GET/api/v1/cookies/classify?name=Classify one cookie name by the organisation that receives its data
GET/api/v1/crawlersAI Crawler Registry records (filter by operator, purpose, status, q)
GET/api/v1/crawlers/:tokenOne crawler record by user-agent token, case-insensitive
GET/api/v1/crawlers/metaRegistry version, coverage counts, and the citation string
GET/api/v1/openapi.jsonMachine-readable OpenAPI 3.1 spec
GET/api/v1/termsAPI terms of use
GET/api/v1/healthService status and data version
POST/mcpMCP server (Streamable HTTP, JSON-RPC)

Every response carries ETag for caching. Send If-None-Match to get a 304 when nothing changed.

Quotas

  • Anonymous: 2,000 calls per IP per UTC day.
  • With a free key: 10,000 calls per key per UTC day.
  • Poppy agent session: 2,000 calls per agent identity per UTC day (the anonymous quota).

Quota headers come back on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. When the quota is spent you get HTTP 429 with a Retry-After header and a link to get a key.

Authentication

Keys are free and need no account or email. Pass yours as a bearer token:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://movahedi.ca/api/v1/glossary?query=consent"

Get a key by solving a Cloudflare Turnstile challenge and accepting the API terms. The key is shown once and never stored on our side.

Examples

JavaScript

const res = await fetch(
  "https://movahedi.ca/api/v1/law25/checklist?category=Consent",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } }
);
const { data } = await res.json();
console.log(data.items.map((c) => c.title));

Python

import requests

res = requests.get(
    "https://movahedi.ca/api/v1/enforcement",
    params={"regulator": "cai", "per_page": 5},
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
res.raise_for_status()
for case in res.json()["data"]["items"]:
    print(case["date"], "-", case["title"])

MCP server

Point any MCP client at the Streamable HTTP endpoint: https://movahedi.ca/mcp. No signup, no key needed.

Claude Code

claude mcp add --transport http movahedi-privacy https://movahedi.ca/mcp

Claude Desktop

Open Settings > Connectors > Add custom connector, or use the button above. Enter name Movahedi Privacy API and URL https://movahedi.ca/mcp. On older builds without custom connectors, add this to claude_desktop_config.json instead (requires Node.js):

{
  "mcpServers": {
    "movahedi-ca-privacy": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://movahedi.ca/mcp"]
    }
  }
}

Cursor

Add to ~/.cursor/mcp.json (every project) or .cursor/mcp.json (this project), or use the one-click button above:

{
  "mcpServers": {
    "movahedi-ca-privacy": {
      "url": "https://movahedi.ca/mcp"
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "movahedi-ca-privacy": {
      "serverUrl": "https://movahedi.ca/mcp"
    }
  }
}

VS Code

Add to .vscode/mcp.json:

{
  "servers": {
    "movahedi-ca-privacy": {
      "type": "http",
      "url": "https://movahedi.ca/mcp"
    }
  }
}

Any other client

{
  "mcpServers": {
    "movahedi-ca-privacy": {
      "url": "https://movahedi.ca/mcp"
    }
  }
}

Twelve read-only tools are exposed:

  • privacy_search_enforcement_actions: find cases by keyword, regulator, or year
  • privacy_get_enforcement_case: full record for one case ID
  • privacy_lookup_glossary_term: definition for one term slug
  • privacy_list_glossary_terms: browse or search the glossary, paginated
  • privacy_law25_requirements: the Law 25 checklist, optionally by category
  • classify_cookie: classify one cookie name by vendor, receiving organisation, purpose, and typical retention
  • lookup_tracker: search the cookie and tracker knowledge base by name, vendor, or purpose
  • lookup_crawler: one AI crawler record by exact user-agent token: operator, purpose, robots.txt behavior, and the operator's own documentation
  • list_crawlers: browse the AI Crawler Registry by operator, purpose, or status
  • privacy_search_api: search the API by plain question when unsure which operation fits
  • privacy_execute_plan: run several read-only operations in one call, with $ref between operations
  • canadian_privacy_consequential_action_lookup_v1: the twelve consequential actions: statutory triggers in English and French with citation status, what an agent may prepare, and what it must never do

Example prompts once connected:

  • "Search CAI enforcement actions involving video surveillance and summarize the outcomes."
  • "What is the privacy glossary definition of meaningful consent?"
  • "List the Law 25 requirements on consent and data retention."
  • "Classify the _fbp cookie: who receives its data, and is it first-party or third-party?"
  • "Look up GPTBot and OAI-SearchBot: which one trains models, and which one gets a site cited?"

Send the API key as Authorization: Bearer ... if you have one. The server negotiates the MCP protocol version on initialize and returns structured output on every tool call.

Search and execute

Unsure which operation fits? Call privacy_search_api with a plain question first, then call the operation it returns. Need several lookups? Call privacy_execute_plan once, with up to 10 read-only operations, instead of many single-tool calls. Each operation counts as one call against the daily quota. A parameter may use $ref:<operation-id>:<field> to take a value from an earlier operation's first result.

Worked execute example: enforcement search for facial recognition with regulator cai, the Law 25 checklist for Automated decisions, and the glossary term privacy-by-design, in one call, with selected fields only:

{"operations": [{"id": "enf", "path": "/enforcement", "params": {"query": "facial recognition", "regulator": "cai"}, "select": ["id", "title", "penalty"], "limit": 5}, {"id": "law25", "path": "/law25/checklist", "params": {"category": "Automated decisions"}}, {"id": "gloss", "path": "/glossary/{term}", "params": {"term": "privacy-by-design"}, "select": ["term", "definition"]}]}

Breach rules are available the same way: REST GET /api/v1/breach-deadlines and an execute operation on path /breach-deadlines. No fixed deadline is invented: PIPEDA uses as soon as feasible, Law 25 uses with diligence, and Alberta PIPA uses without unreasonable delay.

Resources and prompts

Resources, read-only and versioned, at resources/list: movahedi://api/openapi, movahedi://api/terms, movahedi://datasets/meta, movahedi://datasets/crawlers/meta, movahedi://guides/law25-checklist. Prompts, user-invoked and auditable, at prompts/list: law25_gap_check, enforcement_briefing, cookie_audit_summary, crawler_check. A prompt never fills a gap or claims compliance on its own.

Version and contract

Tool contract hash (SHA-256 over tool names, descriptions, input schemas, and output schemas): 53fd37ff08fe37900a0c9888ea8e71599fa9064975c851656f6e5d808982a85a, updated 2026-11-04. Tool names are stable: a breaking change gets a new name or a 90-day overlap, and the hash and changelog change in the same commit. Consumers should pin this hash at approval, recheck it before each call, and refuse on drift until a human reviews the diff. Registry scans only see what the server served the crawler at scan time; a live endpoint can vary by client, key, region, or hour.

Personal Agent Protocol (Poppy)

movahedi.ca speaks the Personal Agent Protocol (Poppy), draft 0.2. A personal agent acting for you can open a session, call the same read-only API and MCP server described above, and report back when a task cannot be done here. Discovery starts at /.well-known/poppy.json; the issuer metadata is at /.well-known/oauth-authorization-server.

How it works here:

  • Sessions, not accounts. There is no sign-in. An agent presents signed assertions from its published client metadata and receives an opaque session token bound to its own key with DPoP. A session lasts 24 hours at most. Tokens last one hour and can be renewed or revoked at /poppy/token and /poppy/revoke.
  • Same data, same limits. A Poppy session gets read-only access to the public endpoints and the anonymous quota, 2,000 calls a day. Nothing extra is exposed to agents.
  • Feedback. When a task cannot be completed through the protocol, the agent can POST a short report to /poppy/feedback. Reports are read by a person and kept for 90 days.

Our positions, in plain terms:

  • Signed-out only, for good. We will never offer mediated sign-in, where an agent enters your credentials for you. If a task needs your account, it needs you.
  • Short-lived, pairwise identifiers. The user ID an agent presents is specific to that agent and this site. Session records hold no names, emails, or IP addresses, and they are deleted when the session expires.
  • Blocking is about abuse, not identity. Any agent can open a session. Session creation is rate-limited, and the blocklist exists for abusive clients only.
  • Declared access equals actual access. What the discovery document and the metadata say an agent can do is exactly what it can do. There are no hidden tiers.

Listings

Also listed in the Claude Market MCP directory and on Glama.

Registry copy: read-only, public data, no signup for MCP, keyed quota only for REST above the anonymous limits, on the Cloudflare Free plan. Install, list, search, execute, and verify from this page alone, with no private help, in under 10 minutes.

Error codes

StatusCodeMeaning
400invalid_parameterA query parameter failed validation. The message names the parameter and its allowed values.
404not_foundNo record matches the ID or slug. The message points to the search endpoint.
405method_not_allowedOnly GET is accepted on data routes.
429quota_exhaustedDaily quota spent. Includes key_url and Retry-After.
500internal_errorSomething broke on our side. Safe to retry after a short wait.

AI Crawler Registry

A versioned registry of AI crawler user-agent tokens: who operates each one, what it is for (training, search indexing, or user-triggered fetching), whether it honors robots.txt, and the operator's own documentation as the citation of record. Dataset page with coverage, citation format, and method: /developers/crawlers/. The same records are served at /api/v1/crawlers and through the lookup_crawler and list_crawlers MCP tools.

Changelog

2026-11-04

  • New MCP tool canadian_privacy_consequential_action_lookup_v1: the twelve consequential actions (corpus v2026.12.0) with statutory triggers in English and French, per-provision citation status, enforcement record IDs, allowed agent scope, and prohibited agent actions. Bilingual index pages at /agents/consequential-actions/ and /fr/agents/actions-consequentielles/; versioned JSON at /corpus/v2026.12/consequential-actions.json. Tools now stand at 12.

2026-10-25

  • MCP and API full integration: discovery tool (privacy_search_api), execute plan tool (privacy_execute_plan, up to 10 read-only operations, per-operation quota and log, $ref only), breach deadlines REST endpoint (/api/v1/breach-deadlines) and execute operation, MCP resources and prompts, site search and chat on the same query data, and a published tool contract hash. Tools now stand at 11.
  • Client-only tools stay client-only in this build: the PII redactor, policy grader, PIA builder, scope checker, and cookie auditor paste-HTML mode send nothing to the server. The cookie auditor server fetch stays at /api/cookie-audit and is not an MCP tool.

2026-10-23

  • AI Crawler Registry, dataset v1.0.0: 51 crawler records across 26 operators, new REST endpoints (/api/v1/crawlers, /api/v1/crawlers/:token, /api/v1/crawlers/meta) and two new MCP tools (lookup_crawler, list_crawlers). See the registry page.

2026-10-21

  • API data now regenerates from the site's source data on every build, so the API and MCP glossary can no longer drift behind the website. Glossary now stands at 333 terms (the API had been serving 271).

2026-10-20

  • Personal Agent Protocol (Poppy) draft 0.2: signed-out agent sessions with DPoP-bound tokens on the REST API and the MCP server, protected-resource metadata, and a feedback endpoint for agents. See the Poppy section above.

v1.0.0, 2026-09-24

  • Initial release: enforcement actions, glossary, Law 25 checklist, MCP server, free API keys.
  • Data version 2026-10-30: 10 enforcement actions compiled from public CAI and OPC decisions as of 2026-10-30, 333 glossary terms, 11 Law 25 checks.

Developer blog

Engineering notes on how movahedi.ca's tools are built: the MCP server, the data-mapping chatbot, the tiny in-browser AI model. Every technical build gets one article.

Read the developer blog

Terms

The data is free for personal and commercial use with attribution to movahedi.ca. It is provided as-is, for information only, and is not legal advice. Full terms: /api/v1/terms.