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}/search
Query params: q (required, the raw consumer string) and limit (1–25, default 10). Do not pre-clean the text — normalization, aliasing and fuzzy matching happen server-side.
{
"dataset": "watches",
"query": "fenix7 pro",
"count": 3,
"ambiguous": false,
"size_ambiguous": true,
"size_options": [
{ "slug": "garmin-fenix-9-43mm", "case_size_mm": 43, "lug_width_mm": 20, "status": "current" },
{ "slug": "garmin-fenix-9-47mm", "case_size_mm": 47, "lug_width_mm": 22, "status": "current" },
{ "slug": "garmin-fenix-9-51mm", "case_size_mm": 51, "lug_width_mm": 26, "status": "current" }
],
"results": [
{
"id": "…",
"slug": "garmin-fenix-7-pro",
"canonical_name": "Garmin fenix 7 Pro",
"brand": "Garmin",
"aliases": ["fenix 7 pro"],
"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": 0.94
}
]
}When ambiguous is true the top candidates score within 0.05 of each other — the correct agent behaviour is to ask one clarifying question rather than pick the first row.
Lug width follows case size within a family — a Garmin fēnix 9 is 20 mm at 43 mm, 22 mm at 47 mm and 26 mm at 51 mm. Each case size is a separate model record, and when a query matches several sizes of one family with different widths the response sets size_ambiguous and lists every size in size_options. Ask which case size the customer has before answering.
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_compatibilityonly. A strap type withcompatible: truefits at the givensize_mm;falsemeans 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.