---
title: "Look Up a Single Image"
description: "Send one image to XI Parallax and learn whether it is registered, plus your own registration and manifests when the match is yours."
published: 2026-09-21T23:43:41.538853+00:00
updated: 2026-09-21T23:43:41.538853+00:00
tags: ["lookup", "parallax", "rest"]
url: https://xiobjects.com/docs/xio/parallax/look-up-single-image
source: XI Objects
---

<!-- xion:doctype xion+markdown -->
<!-- xion:metadata
{
  "version": "1.0",
  "content_type": "application/xion\u002Bmarkdown",
  "source_type": "xi-content/doc",
  "generator": "xio-content-publisher/1.0.0",
  "generated": "2026-09-21T23:42:03.2686330\u002B00:00",
  "encoding": "utf-8",
  "render_intent": "markdown",
  "title": "Look Up a Single Image",
  "slug": "xio/parallax/look-up-single-image",
  "copyright": "\u00A9 2026 XI Objects Inc"
}
-->

# Look Up a Single Image

`POST /lookup` answers one question about one image: is it registered.

## The request

`multipart/form-data` carrying exactly one image file part and nothing else.

```bash
curl -sS -X POST "$BASE/lookup" \
  -H "Authorization: Bearer $TOKEN" \
  -F "image=@query.png;type=image/png"
```

The part name carries no meaning on this route. Any file part is the query image.

There are no other inputs. No top-K, no threshold, no options object, no query-string parameter, no second form field. A request carrying any of them is refused before the image is read.

The image is bounded by the same per-image and per-request size caps a registration image is, and its content type must be one the deployment accepts.

## The verdict

`200 OK`.

| Field | Type | Description |
|-------|------|-------------|
| `matched` | `bool` | `true` when any account holds a live registration for this image. |
| `candidates` | `array` | Only your own matching registrations. Empty when the match is not yours, and empty when there is no match. |

Each candidate:

| Field | Type | Description |
|-------|------|-------------|
| `registrationId` | `uuid` | Your registration for this image. |
| `manifests` | `array` | The manifests you registered with it, exactly as registered. Each is `{ type, form, payload }`. |

### Your own image

```json
{
  "matched": true,
  "candidates": [
    {
      "registrationId": "6f0d4d6e-9a0b-4c2e-9b1a-2d3c4e5f6a7b",
      "manifests": [
        { "type": "xi-manifest", "form": "json", "payload": { "owner": "me" } }
      ]
    }
  ]
}
```

### Someone else's image

```json
{
  "matched": true,
  "candidates": []
}
```

The image is registered. Nothing about whose registration it is, what it is called, or what manifests it carries is returned. `matched: true` with an empty `candidates` array is the whole answer.

### Nobody's image

```json
{
  "matched": false,
  "candidates": []
}
```

## No score, no ranking

There is no score, rank or similarity value anywhere in the response, and no way to ask for one. The answer is binary. `candidates` is the set of your own registrations the match resolved to, not a ranked list.

## Timing

A look-up run immediately after a registration can answer `matched: false` for a short window, until the registration has propagated. Retry with a short backoff rather than treating the first answer as final.

A registration you have [taken down](/docs/xio/parallax/take-down) stops matching. A later look-up of those bytes answers `matched: false` with no candidates.

## What it costs

One look-up from your look-up grant, per call that produces a verdict. A call refused before a verdict costs nothing. See [Quotas and stats](/docs/xio/parallax/quotas-and-stats).

## Refusals

| Status | Title | `detail` |
|--------|-------|----------|
| `400` | `Malformed request` | `POST /lookup accepts no query-string parameters.` |
| `400` | `Malformed request` | `POST /lookup requires exactly one well-formed multipart image file part.` |
| `400` | `Malformed request` | `POST /lookup requires a well-formed multipart body.` |
| `400` | `Malformed request` | `POST /lookup accepts exactly one image file part and no other part.` |
| `400` | `Malformed request` | `POST /lookup requires exactly one image file part.` |
| `413` | `Request too large` | `The request exceeds the configured per-request upload size cap.` |
| `413` | `Image too large` | `The image exceeds the configured per-image size cap.` |
| `422` | `Image could not be checked` | The engine would not check this image, or the image could not be stored for look-up. No verdict was produced and nothing was charged. Retry. |
| `429` | `Quota exceeded` | Your look-up grant does not cover this call. Carries `registrationRemaining` and `lookupRemaining`. |
| `503` | `Engine not configured` | The deployment has no engine wired. |

## Your pixels

The query image's bytes are held only for as long as the engine needs to answer. They are then deleted and their absence is verified. See [Custody and privacy](/docs/xio/parallax/custody-and-privacy).

## Many images at once

Use the look-up slot conversation. See [Look up in batches](/docs/xio/parallax/look-up-in-batches).
<!-- xion:trust
{
  "v": 1,
  "canon_v": 1,
  "ctx": "xiobjects.com/content",
  "hash_blake3_hex": "426cb138c965546945100a9623baf2a409f94e2639f5b478dd1cda645571c8ea",
  "hash_sha256_hex": null,
  "sig_alg": "ed25519",
  "sig_b64": "_17mzUJ-guTOvCZgnUA5-GvTbzyHXk93VtURqg0FfUXHS2R7539mVsbHEE-8EXfNbtx5kGk8L30bLPAzjMFrDA",
  "pubkey_b64": "VrV0rqYGnIqutEwPTr11jfrjH9wmtkOlL68wL0W6ed0",
  "x509_chain_pem": [
    "-----BEGIN CERTIFICATE-----\nMIIB9DCCAaagAwIBAgIQbmGqXUijS3XuRUHDuVME8jAFBgMrZXAwLjEsMCoGA1UE\nAwwjWEkgT2JqZWN0cyBJbmMgQ29udHJvbCBJbnRlcm1lZGlhdGUwHhcNMjYwOTIx\nMjMzNjU1WhcNMjYxMDIxMjMzNjU1WjBLMR4wHAYDVQQDDBV4aW8tY29udGVudC1w\ndWJsaXNoZXIxFzAVBgNVBAoMDlhJIE9iamVjdHMgSW5jMRAwDgYDVQQLDAdDb250\nZW50MCowBQYDK2VwAyEAVrV0rqYGnIqutEwPTr11jfrjH9wmtkOlL68wL0W6ed2j\ngbwwgbkwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI\nKwYBBQUHAyQwZQYDVR0jBF4wXIAUOym3mFmw/qs1fgKrujCkxhrTk7KhLqQsMCox\nKDAmBgNVBAMMH0luc3RpdHV0ZSBvZiBQcm92ZW5hbmNlIFJvb3QgQ0GCFFJgN/ix\nQn72H6h3T5lEr9f8lJQFMB0GA1UdDgQWBBTnptRqwN8T\u002B5J0zUSRl65iscaPUzAF\nBgMrZXADQQBTzG1wSuUk70ymEN3Mj6XxsS1c5egjDoy\u002BW/V2kko5c2a1Cs7c/kiD\n6H2y9z1DNSH5qjzLZcm9JKPN0mjCy8MO\n-----END CERTIFICATE-----\n",
    "-----BEGIN CERTIFICATE-----\nMIIByDCCAXqgAwIBAgIUUmA3\u002BLFCfvYfqHdPmUSv1/yUlAUwBQYDK2VwMCoxKDAm\nBgNVBAMMH0luc3RpdHV0ZSBvZiBQcm92ZW5hbmNlIFJvb3QgQ0EwHhcNMjUxMTAy\nMDMxNzEyWhcNMzAxMTAxMDMxNzEyWjAuMSwwKgYDVQQDDCNYSSBPYmplY3RzIElu\nYyBDb250cm9sIEludGVybWVkaWF0ZTAqMAUGAytlcAMhAFSS/pggSRmTcAMko7uc\nATH8OHgxVymd5mBFlPXbJkgio4GtMIGqMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQ7KbeYWbD\u002BqzV\u002BAqu6MKTGGtOTsjBlBgNV\nHSMEXjBcgBQAZRTDswSVORu\u002BkUOKX6WvrOvmQKEupCwwKjEoMCYGA1UEAwwfSW5z\ndGl0dXRlIG9mIFByb3ZlbmFuY2UgUm9vdCBDQYIUJqoJlpiSFg\u002B7W5IJLMrLttgR\nQp4wBQYDK2VwA0EA5FOht7YOsVRPp/FOKMQ\u002B3Mo9JxrvGR3ylKWAWNm6OUV7N3DB\nI9cD62wU5I0d0EKDBy0CX9DnoqUyxv5yguraAA==\n-----END CERTIFICATE-----\n",
    "-----BEGIN CERTIFICATE-----\nMIIBaTCCARugAwIBAgIUJqoJlpiSFg\u002B7W5IJLMrLttgRQp4wBQYDK2VwMCoxKDAm\nBgNVBAMMH0luc3RpdHV0ZSBvZiBQcm92ZW5hbmNlIFJvb3QgQ0EwHhcNMjUxMTAy\nMDMwNTEyWhcNMzUxMDMxMDMwNTEyWjAqMSgwJgYDVQQDDB9JbnN0aXR1dGUgb2Yg\nUHJvdmVuYW5jZSBSb290IENBMCowBQYDK2VwAyEAEWNZl\u002Br3IC7\u002BgBh90Yo1kWk1\npZCVzVuFdFT7qBBU8W2jUzBRMB0GA1UdDgQWBBQAZRTDswSVORu\u002BkUOKX6WvrOvm\nQDAfBgNVHSMEGDAWgBQAZRTDswSVORu\u002BkUOKX6WvrOvmQDAPBgNVHRMBAf8EBTAD\nAQH/MAUGAytlcANBAO6QeydOFNrN75qNyftggYudsxMyl4w9qWkSdZ6hlhrRcbSr\niG9Si0kbrIJOwYB/LTBU0RM4Rl\u002Bo9PM3Qp0mPwo=\n-----END CERTIFICATE-----\n"
  ],
  "key_id": "_A4EpsXvfBfVEGu5deK65yN4EjBJsUpgkdoS25zPEFk",
  "created_at": "2026-09-21T23:42:03Z"
}
-->