# Result images

A recognition returns the pictures it cut out of the image it was sent. The
document itself, the holder's photograph, the signature and a few more. Every
one of them is a `data:` URL in the response body.

They are returned by the call that produced them and **never stored**, so a
scan read back later through `GET /v1/scans/{id}` carries no images at all.

## The seven slots

| Key | What it is |
|---|---|
| `document_crop` | The document cut out of the uploaded picture and deskewed |
| `main_photo` | The holder's photograph as printed |
| `rear` | The rear side, when one is in the frame |
| `signature` | The signature strip |
| `watermark_face` | The faint second copy of the holder's face printed into the page as a security feature |
| `barcode` | The barcode region |
| `chip` | The chip symbol |

Every slot is present as a key, and a slot with nothing in it is `null`.

`watermark_face` is a different picture from `main_photo`. It is the one a
verifier compares against it.

`main_photo` is `null` when the request sent `return_portrait: false`. The
other six slots are unaffected by that option.

## The height caps

Every crop is scaled down by height, proportionally.

| Slot | Cap |
|---|---|
| `document_crop` | 250 px |
| Every other slot | 100 px |

The document crop is the one a person actually looks at, so it gets the larger
box. Everything else is an illustration beside the extracted fields.

Two rules apply to all of them:

- **Proportional.** Only the height is set; the width follows.
- **Never upwards.** A crop already inside its cap is published at the size the
  recognition produced it.

A slot with no cap of its own takes the 100 px default rather than being
published uncapped. That includes any crop a future recognition adds.

## What the re-encode does

| Rule | What happens |
|---|---|
| Format | The source format is kept. A PNG is written back as PNG; everything else is written as JPEG |
| JPEG quality | Fixed at 90 |
| Metadata | Dropped entirely |
| Orientation tag | Not applied |

**Every metadata block is dropped**: EXIF, ICC and the rest. No camera model,
no timestamp and no GPS tag survives into a published crop.

The format is kept because a consumer sniffing the bytes would otherwise see a
different one from the picture it asked for. The JPEG quality is fixed because
the quantization quality of a source JPEG is not recoverable. It is set high
enough that the loss is not the visible change, rather than guessed at.

The orientation tag is deliberately not applied. A crop is published as the
stored pixel grid, so its dimensions are the ones the caps above produce rather
than a rotated pair.

## Image processing never fails a scan

A recognition that has already been paid for is never turned into a failure.
An image library disliking one of the crops it was given does not change that.

Every failure answers with the original bytes instead:

- an undecodable blob;
- a format the encoder will not write back;
- a source with no readable size.

A merely warning-worthy source — a truncated scan line, a bad marker — still
produces a picture rather than an exception.

Such a failure is not reported anywhere and does not appear in the response. It
says nothing an operator can act on, and the image itself is never logged.

## Size, and what to expect in a body

A crop capped at 250 px in height is a few kilobytes of JPEG; the 100 px ones
are smaller. Seven of them add tens of kilobytes to a response, as base64 inside
JSON.

A caller that does not need them can send `return_portrait: false`, which drops
the largest of the personal ones. The other six have no per-slot switch. They
are what the recognition produced.

## What a stored scan keeps instead

No crop is stored, so `GET /v1/scans/{id}` answers with all seven slots
`null`.

A scan that was retained keeps a **thumbnail of at most 96 px**, generated from
the bytes the caller uploaded rather than from any crop. It is readable in the
dashboard and not through this API. A scan created with `retain_hours: 0` keeps
nothing at all, thumbnail included.

The reasons behind that split are on
[data retention and privacy](/concepts/data-retention-and-privacy).
