MediaLayer

Use case

Image similarity API for marketplace fraud detection

Use cases6 min read

Marketplaces face a steady drip of copied product photos, recycled listings, and coordinated seller fraud. This article walks through using POST /image/match to surface those listings at scale — with code in cURL, Python, and Node.

What sellers actually do to evade detection

If you're guarding a marketplace, you've already seen these moves: download a competing seller's hero image, watermark it, recompress it, mirror it, swap the background, paste it on a new template. Each of those changes flips a content hash but not the perceived image.

An effective dedupe layer has to be invariant to those edits. That's what /image/match is built for: a perceptual similarity score, not an exact-match check.

The endpoint

Two URLs in, structured envelope out. matched_segments is empty for image responses; the score and confidence are what drive the decision.

RESPONSE · /IMAGE/MATCH
{
  "match": true,
  "confidence": "high",
  "similarity_score": 0.94,
  "processing_time_ms": 38,
  "media_type": "image",
  "matched_segments": []
}

cURL — quick test

CURL
curl -X POST https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match \
  -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY" \
  -H "x-rapidapi-host: medialayer-image-audio-video-matching-api.p.rapidapi.com" \
  -H "Content-Type: application/json" \
  -d '{
    "source_url": "https://cdn.example.com/listing-12345.jpg",
    "target_url": "https://cdn.example.com/catalog-ref-987.jpg"
  }'

Python — listing-creation gate

The simplest production pattern: when a seller submits a new listing, compare its hero image to a small reference catalog of known products and known-banned images. If the score crosses a threshold, route to manual review.

PYTHON · LISTING GATE
import requests

API_URL = "https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match"
HEADERS = {
    "x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
    "x-rapidapi-host": "medialayer-image-audio-video-matching-api.p.rapidapi.com",
    "Content-Type": "application/json",
}

def gate_listing(listing_image_url: str, references: list[str]) -> str:
    """Return one of: 'auto-block', 'review', 'pass'."""
    for ref_url in references:
        r = requests.post(
            API_URL,
            json={"source_url": listing_image_url, "target_url": ref_url},
            headers=HEADERS,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()
        score = data["similarity_score"]

        if score >= 0.97:
            return "auto-block"   # near-identical image
        if score >= 0.85:
            return "review"       # near-duplicate, send to T&S queue

    return "pass"

Node.js — fan-out with a concurrency cap

Most marketplaces don't compare against a single reference image — they fan out to a curated set. Bound concurrency so a single listing doesn't burst against your RapidAPI plan's per-second limit.

TYPESCRIPT · BOUNDED FAN-OUT
const API_URL =
  "https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match";
const HEADERS = {
  "x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
  "x-rapidapi-host": "medialayer-image-audio-video-matching-api.p.rapidapi.com",
  "Content-Type": "application/json",
};

async function matchOne(source: string, target: string) {
  const res = await fetch(API_URL, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({ source_url: source, target_url: target }),
  });
  if (!res.ok) throw new Error(`MediaLayer ${res.status}`);
  return res.json() as Promise<{ similarity_score: number }>;
}

async function topMatch(listing: string, references: string[]) {
  // Bound to 4 concurrent calls. Tune to your plan.
  const queue = [...references];
  let best = 0;
  await Promise.all(
    Array.from({ length: 4 }).map(async () => {
      while (queue.length) {
        const ref = queue.shift()!;
        const { similarity_score } = await matchOne(listing, ref);
        if (similarity_score > best) best = similarity_score;
      }
    }),
  );
  return best;
}

Pairwise won't scale forever

If your reference catalog is in the low thousands, the public API and a fan-out pattern works fine. Past that, pairwise calls per listing become wasteful and slow — you're doing N comparisons to find a top match.

That's where the Enterprise media search surface fits: ingest your reference media into a similarity index, run one-to-many lookups on every new listing, and get top-K matches with scores in a single call. Same matching primitives, different access pattern.

Trust & safety considerations

  • Cluster, don't score in isolationGroup listings whose images match at a high threshold; resolve the cluster as one decision. Reviewers stop seeing 40 copies of the same flagged image.
  • Keep the key server-sidex-rapidapi-key never belongs in a mobile or web bundle — proxy through your backend.
  • Stay inside size capsImage uploads are capped at 15 MB per request. Resize at upload time so the matching pipeline doesn't reject hero images.
  • Treat URLs as untrustedURL validation rejects private, loopback, and cloud-metadata addresses up front — useful when seller-supplied URLs occasionally point at internal staging buckets.

Ready to wire it in?

Subscribe on RapidAPI to call the public API on your own key, or talk to MediaLayer AI Labs about enterprise direct API access.