> ## Documentation Index
> Fetch the complete documentation index at: https://docs.souldi.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Search by Image

> Pass a reference image URL and find the garments in your catalog that look most like it, ranked by relevance.

Have a photo of a look you want to match? Point image search at a **public**
garment image URL and it returns the visually closest items in your catalog,
ranked by [relevance](/api/search#how-relevance-works) — exactly like text search.
Each result is a garment `id` and `url` you can pass into
[Generation](/api/generation).

<Note>
  This endpoint needs **only your tenant key** — send `x-api-key` and nothing else,
  with no `Authorization: Bearer` token. `BASE_URL` is the Souldi API base URL, `https://api.souldi.io`.
  See the [authentication model](/api/overview#authentication-model).
</Note>

## Search by image

<ParamField path="POST /search/image-search" />

Finds garments in your catalog that are **visually similar** to a reference image
you provide. Results are ranked by [`z_score`](/api/search#how-relevance-works),
exactly like text search.

**Required headers**

| Header         | Value                       |
| -------------- | --------------------------- |
| `x-api-key`    | Your publishable tenant key |
| `Content-Type` | `application/json`          |

**Query parameter**

<ParamField query="query" type="string" required>
  A **public** URL of the reference garment image, passed in the **URL query
  string** (not the JSON body). For example
  `?query=https://shop.example.com/inspo.jpg`.
</ParamField>

**Body parameters**

<ParamField body="top_n" type="integer" default="3">
  Maximum number of garments to return. Range `1`–`10`.
</ParamField>

<ParamField body="min_z_score" type="number" default="1.0">
  Relevance floor in standard deviations above the query's mean. Range `-5.0`–`5.0`.
  See [How relevance works](/api/search#how-relevance-works).
</ParamField>

<ParamField body="pool_size" type="integer" default="50">
  Size of the candidate pool that defines the `z_score` baseline. Range `1`–`200`.
</ParamField>

<Warning>
  The reference image URL must be **publicly reachable** — Souldi fetches it
  server-side to compare against your catalog. URLs behind authentication or on
  private networks will fail.
</Warning>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "$BASE_URL/search/image-search?query=https://shop.example.com/inspo.jpg" \
    -H "x-api-key: $SOULDI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "top_n": 3,
      "min_z_score": 1.0,
      "pool_size": 50
    }'
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    query: "https://shop.example.com/inspo.jpg",
  });

  const res = await fetch(`${BASE_URL}/search/image-search?${params}`, {
    method: "POST",
    headers: {
      "x-api-key": SOULDI_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      top_n: 3,
      min_z_score: 1.0,
      pool_size: 50,
    }),
  });

  const { garments } = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.post(
      f"{BASE_URL}/search/image-search",
      params={"query": "https://shop.example.com/inspo.jpg"},
      headers={"x-api-key": SOULDI_API_KEY},
      json={"top_n": 3, "min_z_score": 1.0, "pool_size": 50},
  )
  garments = res.json()["garments"]
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "garments": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "url": "https://shop.example.com/garments/red-linen-dress.jpg",
        "z_score": 2.91
      }
    ]
  }
  ```
</ResponseExample>

**Response fields**

<ResponseField name="garments" type="object[]">
  The matching garments, ordered most-relevant first. May be **empty** if nothing
  clears `min_z_score`.
</ResponseField>

<ResponseField name="garments[].id" type="string">
  The garment's unique ID. Use it to reference the garment elsewhere.
</ResponseField>

<ResponseField name="garments[].url" type="string">
  The garment image URL — pass this into
  [`POST /try-on/generate`](/api/generation#create-a-job) to try it on.
</ResponseField>

<ResponseField name="garments[].z_score" type="number">
  The relevance score for this query. See
  [How relevance works](/api/search#how-relevance-works).
</ResponseField>

<Tip>
  The response shape is identical to [text search](/api/search-text): a `garments`
  array of `{ id, url, z_score }`. For the shared status codes and the
  empty-result case, see [Errors](/api/search#errors).
</Tip>

## Next steps

<CardGroup cols={3}>
  <Card title="Search by text" icon="font" href="/api/search-text">
    Use a natural-language query when you don't have a reference image.
  </Card>

  <Card title="Search by attributes" icon="filter" href="/api/search-attributes">
    Switch to exact faceted filters across ten garment attributes.
  </Card>

  <Card title="Try a garment on" icon="wand-magic-sparkles" href="/api/generation">
    Pass a result `url` to `POST /try-on/generate` to render it on your user.
  </Card>
</CardGroup>
