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

# Scan lifecycle

> Photo intake, background analysis, and the polling contract.

```mermaid theme={null}
stateDiagram-v2
  [*] --> awaiting_upload: start_skin_scan (no photo)
  [*] --> queued: start_skin_scan (photo)
  awaiting_upload --> queued: person uploads on the Skan page
  queued --> processing
  processing --> completed
  processing --> failed
  completed --> deleted: delete_skin_scan
  completed --> expired: after seven days
```

## Photo intake

There are two ways in. `start_skin_scan` returns immediately either way; analysis runs in the background.

|                     | Direct                                               | Upload link                             |
| ------------------- | ---------------------------------------------------- | --------------------------------------- |
| Call                | `start_skin_scan` with `photo` and `consent`         | `start_skin_scan` without `photo`       |
| Returns             | `status: queued`, `upload_url: null`                 | `status: awaiting_upload`, `upload_url` |
| Consent recorded as | `agent_attested`                                     | `person_on_skan_page`                   |
| Photo limits        | JPEG or PNG, at most 5 MB decoded and 8 megapixels   | Resized in the person's browser         |
| Works on            | Hosts that give the model the image **file's bytes** | Every host                              |

**Choosing a path.** Most assistant hosts show the model an attached image without exposing its bytes. A model cannot reconstruct base64 from an image it can only see, so use the link unless your host passes the file itself.

**Direct path requirements.** Before sending `consent`, the agent must have:

1. told the person the photo goes to Skan and its analysis provider and is deleted within an hour,
2. confirmed they are 18 or older, and
3. confirmed the photo is of their own face.

The server records this as an agent attestation, not as the person's own consent. A deployment can require the link for everyone, in which case a direct call returns `consent_page_required`.

**Photo errors:**

* `invalid_image`: the bytes aren't a readable JPEG or PNG.
* `invalid_image_dimensions`: over 8 megapixels.
* `payload_too_large`: over 5 MB.

Each points the agent to the upload link.

## Polling

Call `get_skin_scan` and follow the response:

| Field                    | Meaning                                                                                                                                                                |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `next_action`            | `upload_photo`: give the person the link. `check_again`: poll later. `show_result`: stop and present `result`. `stop`: end automatic checks and follow `instructions`. |
| `retry_after_seconds`    | Wait at least this long before the next check                                                                                                                          |
| `max_auto_checks`        | Total automatic checks allowed for this scan in a conversation. Count across responses; don't reset it.                                                                |
| `processing_deadline_at` | Epoch ms. After it, `next_action` becomes `stop`: end automatic checks and let the person check back later. The server keeps reconciling the scan in the background.   |
| `expires_at`             | Epoch ms after which the token stops working (seven days)                                                                                                              |

A scan typically completes a few seconds after the photo arrives. Other tools can be called while it processes. Never start a second scan to check on the first.

## Result

When `status` is `completed`, `result.scores` is a list of `{ title, progress }` pairs, for example `wrinkles`, `redness`, `pores`, `eye_bags`, `pigmentation`, `acne` and `sagging`.

`progress` is the provider's raw 0–100 value. It is not a percentage, a health rating or a ranking, and different metrics are not on a shared scale. Keep `result.limitations` attached when presenting scores.

## Deletion

`delete_skin_scan` revokes the token at once and schedules cleanup at the analysis provider. After that, `get_skin_scan` and `delete_skin_scan` return `not_found`. A result the person saved to their Skan account is managed in the app, not here.
