For agents
Constraints resolve against fixed JSON paths with plain comparisons. There is no model at query time, and the three rules below are the whole contract.
Last updated 2026-08-21Query
POST https://itha.ai/api/search
content-type: application/json
{
"constraints": [
{"field": "category", "op": "eq", "value": "cobot"},
{"field": "payload_kg", "op": "at_least", "value": 10},
{"field": "ip_rating", "op": "ip_at_least", "value": "IP65"},
{ "op": "class_any", "value": ["machine_safety", "product_safety"]},
{"field": "price_usd", "op": "at_most", "value": 60000},
{"field": "lead_time_weeks", "op": "at_most", "value": 8},
{ "op": "serves", "value": "CA-ON"}
],
"status": "any",
"include_cards": false,
"limit": 25
}Ops: eq, at_least, at_most, ip_at_least, has_any, has_all, class_any, carries, serves. Every constraint accepts include_unknown; class_any also accepts require_status.
For a quick look, GET /api/search?q= takes one line of buyer language and parses it into the same constraints. The structured form is the contract.
GET /api/vocab returns the query surface as a document: every field with its ops, unit and include_unknown default, the category, protocol, application and brand slugs, certifications with their class, and the region grammar. Fetch it before constraining on a slug you are unsure of. Vocabularies are open, so an unrecognised slug is not an error. It matches nothing, which looks exactly like an empty market.
The three rules
Response
{
"fx": {"source": "...", "as_of": "2026-08-19"},
"total": 1,
"results": [{
"record": {
"domain": "universal-robots.com",
"status": "unclaimed",
"card_url": "https://universal-robots.itha.ai/card.json",
"provenance_url": "https://universal-robots.itha.ai/provenance.json"
},
"matches": [{
"offering_id": "ur-series",
"citation": {"card_url": "...", "offering_id": "ur-series"},
"constraints": [
{"field": "payload_kg", "status": "matched"},
{"field": "price_usd", "status": "unknown_included"}
],
"notes": ["Robot arms are partly completed machines: no CE mark is affixed..."]
}]
}]
}notes carries the seller’s own caveats from terms.notes and pricing.notes. Surface them: they are exactly the facts a scraped answer loses.
Add "explain": "<domain>" to see every offering of one company with full three-valued statuses, including the ones that were excluded and why.
Documents
Trust and safety
MCP
The same surface is published as an MCP server, so an agent can plug the registry in as a tool rather than writing a client. It is a thin wrapper: every tool returns this API’s JSON untouched alongside a text rendering, so anything integrated against the shape above keeps working.
# Claude Code, local
claude mcp add itha -- node /path/to/itha/mcp/src/stdio.mjs --registry=https://itha.ai
# Claude Code, hosted
claude mcp add --transport http itha https://itha.ai/mcp
# Claude Desktop: claude_desktop_config.json
{"mcpServers": {"itha": {"command": "node",
"args": ["/path/to/itha/mcp/src/stdio.mjs"],
"env": {"ITHA_REGISTRY_URL": "https://itha.ai"}}}}
# Messages API: both halves are required
{"mcp_servers": [{"type": "url", "url": "https://itha.ai/mcp", "name": "itha"}],
"tools": [{"type": "mcp_toolset", "mcp_server_name": "itha"}]}