Octogen Platform API

More Like This — now from an image

The same endpoint that finds similar products for a URL or UUID now accepts an image. Send a photo — a product shot, a look you want to match — and get similar products from your catalogs. Every example below is a real request with live results from production.

POSThttps://api.octogen.ai/v1/products/more-like-this

The third source identifier

source takes exactly one of url, uuid, or — new — image. The image itself is exactly one of b64 (base64 bytes) or url (fetched server-side from any public HTTPS host — retailer product-image URLs work directly). Everything else about the request — catalog, limit, include_facets, exclude_facets, embedding-column overrides, debug — works as it does for product sources.

GuardBehavior
8 MB decoded capLarger payloads return 413. The pipeline downscales to 768px internally, so send a client-side-downscaled image (~1024px JPEG) — it's faster for you and identical in quality.
price_preferenceMust be "any" for image sources (400 otherwise) — there is no source product to be price-relative to.
cursorSupported. The cursor embeds the relaxation round that produced the page, so continuations re-run the exact converged query — deterministic within the 24h generation-cache window. Measured: page 2 in 0.52s.
image.url fetchAny public HTTPS image host — send retailer product-image URLs directly. Hardened fetch: HTTPS-only, no redirects, DNS + connected-peer public-address checks, size-capped while streaming.

How an image becomes results — the resolution ladder

Rung 1 · Catalog image phase 3

If the submitted bytes hash-match an indexed product image, the request becomes a product-source MLT — near-instant. Phase 1 ships the feasibility counter; the shortcut lands if real traffic shows exact matches.

Rung 2 · Seen before live

A repeat image hits the cached generated query and runs search-only — measured 0.25s in production (vs 7.15s cold for the same image). Client integrations re-send identical images constantly, so this is where most real traffic lands. The response reports resolution: "cached_image_query".

Rung 3 · Cold live

A multimodal parse reads the image, the shared query processors build facets, and the search runs with zero-result facet relaxation. 5–8s typical, ~11s when relaxation rounds run. The response's resolution field always says which rung served you.

Live demos — production, real responses

Catalog-scoped, no relaxation needed

"catalogs": ["jcrew"]

The lean query a jewelry image generates matches directly — no relaxation. Scoping with the catalogs allowlist works exactly as it does for product sources.

query image
gold hoop earrings · 4 items in 4.3s
{
  "source": {
    "image": {
      "b64": "<base64 image bytes>" // or "url" on allowlisted hosts
    }
  },
  "catalogs": ["jcrew"],
  "limit": 6,
  "debug": true
}
wall 4.3sresolution image_query_generationsourceImage.hash bmpZmWXW0C7DUV0T8xPsRA==

Generated retrieval text: “Gold-tone minimalist hoop earrings, medium-thick round tube design, polished metal finish.”

Round-1 relaxation: the logo brand softens

relaxationRounds: 1

The model reads the visible logo and generates an exact brand_name: Emporio Armani filter. Your granted catalogs may not carry the brand, so the exact filter would pin the result set to zero — round 1 drops the inferred brand facets and recovers the search. A brand_name you pass yourself in include_facets is never dropped. Honest caveat: these results match on category and silhouette but not the minimalist look — logo styling is exactly the kind of visual signal text-derived retrieval carries weakly. Image-embedding retrieval/ranking is on the roadmap for cases like this.

query image
white leather sneakers · 4 items in 7.5s
{
  "source": {
    "image": {
      "b64": "<base64 image bytes>" // or "url" on allowlisted hosts
    }
  },
  "limit": 6,
  "debug": true
}
wall 7.5sresolution image_query_generationsourceImage.hash sVqdJmMDHYvFE3AHe8silA==relaxationRounds 1dropped: brand_name

Generated retrieval text: “Emporio Armani white leather low-top sneakers with lace-up closure, rounded toe, and signature eagle logo detail on the side.”

Round-2 relaxation: attributes soften too

relaxationRounds: 2

Dress images generate rich attribute facets (neckline, pattern, dress style, length…). When the full conjunction over-constrains, round 2 additionally releases the attribute tier — the retrieval text still carries every detail, so results stay on-look while the hard filters relax.

query image
floral wrap dress · 6 items in 11.3s
{
  "source": {
    "image": {
      "b64": "<base64 image bytes>" // or "url" on allowlisted hosts
    }
  },
  "limit": 6,
  "debug": true
}
wall 11.3sresolution image_query_generationsourceImage.hash PXPiseTHwq8qh52hW9oPFQ==relaxationRounds 2dropped: brand_name, neckline, opacity_level, pattern…

Generated retrieval text: “Blue floral print midi wrap dress with long sheer sleeves, V-neckline, and ruffled trim detailing.”

Round-3 relaxation: last-resort visual tier

relaxationRounds: 3

The deepest cascade: inferred brand, then attributes, then color and deep category levels. Top-level category, gender, and age-group facets are never dropped — recovery broadens the query without changing what kind of product comes back.

query image
leather hobo bag · 6 items in 6.9s
{
  "source": {
    "image": {
      "b64": "<base64 image bytes>" // or "url" on allowlisted hosts
    }
  },
  "limit": 6,
  "debug": true
}
wall 6.9sresolution image_query_generationsourceImage.hash iX4+Kq+yd0V/05VV/niUnw==relaxationRounds 3dropped: brand_name, carry_options, graphic_type, hardware_finish…

Generated retrieval text: “Brunello Cucinelli grey pebbled leather hobo bag with a single adjustable shoulder strap, minimalist structured silhouette, and subtle logo branding.”

Notes for integrators