API & MCP

One registry, two surfaces. Both take the customer's raw text and return ranked canonical models with their compatibility attributes.

Authentication

Every REST request needs an API key in the X-API-Key header. Keys are issued from the admin area; ask the registry owner for one. Keys are rate limited per minute and every call is logged so unresolved queries can be turned into new registry entries.

curl -H "X-API-Key: fk_live_…" \
  "https://<your-domain>/api/public/v1/watches/search?q=fenix7%20pro"

GET /api/public/v1/{dataset}/models/{slug}

Full record for one model: aliases, every fitment row, specifications, per-row confidence and source URLs.

GET /api/public/v1/datasets

Lists datasets and their attribute schemas. Today: watches (Garmin and Apple). The schema is dataset-agnostic, so other categories can be added without changing the API shape.

MCP server

Streamable HTTP endpoint at /mcp, no key needed. Add it in your assistant's connector settings and it exposes three tools: find_watch, get_watch and list_datasets.

{
  "mcpServers": {
    "productwatch": {
      "url": "https://productwatch.dev/mcp"
    }
  }
}

Concrete find_watch input:

{
  "query": "fenix 7 pro",
  "dataset": "watches",
  "limit": 2
}

Actual output from the live registry (structuredContent; the text block repeats the same facts in one line per model):

{
  "query": "fenix 7 pro",
  "dataset": "watches",
  "ambiguous": false,
  "size_ambiguous": true,
  "size_options": [
    { "slug": "garmin-fenix-7s-pro", "canonical_name": "Garmin fenix 7S Pro", "case_size_mm": 42, "lug_width_mm": 20, "status": "current" },
    { "slug": "garmin-fenix-7-pro",  "canonical_name": "Garmin fenix 7 Pro",  "case_size_mm": 47, "lug_width_mm": 22, "status": "current" },
    { "slug": "garmin-fenix-7x-pro", "canonical_name": "Garmin fenix 7X Pro", "case_size_mm": 51, "lug_width_mm": 26, "status": "current" }
  ],
  "results": [
    {
      "id": "f7e5f186-4fc2-4516-930b-8d89dde03e56",
      "slug": "garmin-fenix-7-pro",
      "canonical_name": "Garmin fenix 7 Pro",
      "brand": "Garmin",
      "aliases": ["fenix 7 pro", "fenix7pro"],
      "status": "current",
      "case_size_mm": 47,
      "lug_width_mm": 22,
      "release_year": 2023,
      "product_compatibility": {
        "quickfit":      { "compatible": true,  "size_mm": 22,   "note": null },
        "quick_release": { "compatible": false, "size_mm": null, "note": null },
        "nato":          { "compatible": false, "size_mm": null, "note": null },
        "apple_slide":   { "compatible": false, "size_mm": null, "note": null },
        "velcro":        { "compatible": false, "size_mm": null, "note": null },
        "other_comments": null
      },
      "source_urls": ["https://www.garmin.com/nb-NO/p/865822/#specs"],
      "score": 1
    }
  ]
}

Only approved models that are switched to visible in the registry are returned. Pending review rows are never part of the API or MCP response.

Admins can inspect actual search inputs, channel, result count and top score under the Queries tab in the admin area. Full output is returned to the calling agent and is not stored in the query log.

Guidance for agents

  • Pass the customer's words verbatim; the registry handles typos and nicknames.
  • Answer from product_compatibility only. A strap type with compatible: true fits at the given size_mm; false means it is not known to fit.
  • Never answer strap compatibility from model memory — it is a common failure case.
  • A machine-readable summary of all of this lives at /llms.txt and /api/public/v1/openapi.

Where the data comes from

Every model carries source_urls pointing at the manufacturer pages the values were read from. Compatibility values are only recorded when they were read from the manufacturer's own page for that exact watch. If we cannot confirm a value, the strap type stays compatible: false rather than being guessed.

  • Garmin: the product page for each watch on garmin.com. The strap width is read from the specification table (QuickFit or quick-release row) and matched to the case size on the same page, e.g. /p/886785/#specs for the Forerunner 265. Discontinued watches that no longer have a product page stay unverified.
  • Apple: Apple states band fit by case size, not lug width — Change your Apple Watch band plus the Apple Store band compatibility chart for the 42mm case introduced with Series 10.

Errors

Errors return { "error": { "code", "message" } } with a matching status: 401 missing/invalid key, 400 invalid query, 404 unknown model, 429 rate limited.