image-product-match

POST /api/v1/image-product-match 1 credits/call catalog vision

Identify a product from a photo. Reads the style code off the box or tag first and looks that up; falls back to reverse-image search when there is no legible label. Returns the matched product with its style code and evidence, or matched=false with the candidates it would not guess between. Built to refuse rather than pick a lookalike.

Sign in + create an API key on the keys page to authenticate calls.

curl -X POST https://api.fulcrumgo.com/api/v1/image-product-match \
  -H "Authorization: Bearer mcpsk_<your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
  "image_url": "",
  "image_base64": "",
  "read_label": true,
  "model": "claude-opus-5"
}'

Add this server to Claude Desktop's claude_desktop_config.json. The endpoint becomes a callable tool inside Claude. See the MCP setup guide for the full walk-through.

{
  "mcpServers": {
    "this-api": {
      "url": "https://api.fulcrumgo.com/mcp",
      "transport": "http",
      "auth": {
        "type": "bearer",
        "token": "mcpsk_<your_api_key>"
      }
    }
  }
}

Inside Claude this endpoint surfaces as the tool image-product-match.

Standard requests — no custom SDK needed. pip install requests first.

import requests

r = requests.post(
    "https://api.fulcrumgo.com/api/v1/image-product-match",
    headers={"Authorization": "Bearer mcpsk_<your_api_key>"},
    json={
  "image_url": "",
  "image_base64": "",
  "read_label": true,
  "model": "claude-opus-5"
},
)
r.raise_for_status()
print(r.json())

Plain fetch. Works in Node 18+, Deno, Bun, and any modern browser.

const r = await fetch("https://api.fulcrumgo.com/api/v1/image-product-match", {
  method: "POST",
  headers: {
    "Authorization": "Bearer mcpsk_<your_api_key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "image_url": "",
  "image_base64": "",
  "read_label": true,
  "model": "claude-opus-5"
}),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);
console.log(await r.json());

Input

Field Type Required Default Description
image_url string optional Public URL of the photo. Use this or image_base64.
image_base64 string optional Photo bytes, base64. Use for a photo that isn't online yet (a Telegram upload). Stored at a public URL for one hour so the provider can fetch it, then deleted.
read_label boolean optional True Try to read a style code off a box or tag before falling back to reverse-image search. Turn off only for a photo with no packaging in it, to skip one vision call.
model string optional claude-opus-5 Vision model used to read the label.

Output

Field Type Required Default Description
matched boolean required True only when independent sources agree. False means no confident answer — show `candidates` and let a human pick. Never treat candidates as the answer when this is false.
confidence string required high | medium | low | none.
reason string required Why this was or wasn't called a match.
style_code string optional Manufacturer code, when corroborated.
best any | null optional Set when matched.
View nested fields (4)
Field Type Req Description
title string no
link string no
source string no Site the match was found on.
image_url string no Full-size image of the candidate.
candidates array<any> optional Everything considered, best first. Present either way.
variant_conflicts array<string> optional Variant words the sources disagree on (men's / kids' / toddler). Ask before ordering or listing, even on a match.
image_searched string optional URL actually looked up.
method string optional label = identified from a printed style code, the strongest. label_description = the box's description line was legible but its code was not. reverse_image = identified by what it looks like, the weakest.
label any | null optional What was read off the packaging, when there was any.
View nested fields (7)
Field Type Req Description
style_code string no Code as printed, spacing and all.
brand string no
description string no Description line(s) on the label.
size string no
sizes_visible array<string> no Every size read across all labels — a stack of boxes is a size run.
unreadable boolean no A label was there but its code could not be read. Reshoot it closer.
loose_item_differs string no Set when a loose product in the photo looks different from the labelled box behind it. The label may describe a different item.

Try it

Fires a real POST /api/v1/image-product-match from your browser. Charges 1 credit per call against your account.

Sign in to use Try it. You'll need an API key from the keys page to authenticate the call.