# Results

> Status is the outcome. Identity is included once a result exists. A later manual decision can change an approval.

Canonical page: https://venuego.co.uk/docs/results

## Status

| Status | Meaning |
| --- | --- |
| `created` | Waiting for the guest to open the link. |
| `in_progress` | The guest is in the face or document steps. |
| `processing` | Automated checks are running. |
| `needs_review` | A person has to approve or decline. This is not a decline. |
| `approved` | Accepted. |
| `declined` | Rejected. The guest may still have attempts left when `decision.retryableStep` is set. |
| `cancelled` | You cancelled it. |
| `expired` | The 24 hours ran out. |

`stage` is the screen the desktop watcher shows: `waiting_for_phone`, `face`, `document`, `reviewing`, then the final status. `attempt` runs from 1 to 3.

## Decision

`decision` is null until there is an outcome. A decline reason declines the check. A review flag does not. A check that errors does not approve on its own.

```json
"decision": {
  "outcome": "needs_review",
  "source": "automated",
  "reasons": [],
  "reviewFlags": [
    { "code": "layout_mismatch", "title": "Layout doesn't match the genuine document" }
  ],
  "retryableStep": null,
  "decidedAt": "2026-10-07T16:04:11.000Z"
}
```

After a person decides, `source` is `manual` and these fields are added:

- `previousOutcome` — what it was before this decision.
- `reasonCode` — the reviewer's reason. The free-text note is not included.
- `decidedBy` — `customer` or `venueora`. You do not receive the reviewer's email.

Manual approve codes: `manual_documents_verified`, `false_positive_layout`, `false_positive_template`, `false_positive_tamper`, `false_positive_recapture`, `false_positive_face`, `customer_known_in_person`, `other`.

Manual decline codes: `document_not_authentic`, `document_tampered`, `document_recaptured`, `face_mismatch`, `not_live`, `under_age`, `expired_document`, `suspected_fraud`, `other`.

## Automated decline reasons

These appear in `decision.reasons[].code` when the checks decline. `retryableStep` is `face`, `document`, or null when the guest cannot try again.

| Code | Retry |
| --- | --- |
| `face_not_live` | face |
| `face_mismatch` | face |
| `document_unreadable` | document |
| `mrz_invalid` | document |
| `barcode_missing` | document |
| `data_mismatch` | document |
| `document_expired` | document |
| `id_not_held` | document |
| `under_age` | none |
| `synthetic_media` | none |
| `document_not_authentic` | none |
| `declined_after_review` | none |
| `processing_error` | face |

## Review flags

These do not decline. Status becomes `needs_review`.

| Code | Why it waited |
| --- | --- |
| `layout_mismatch` | The layout does not match the genuine document. |
| `template_mismatch` | The printed design differs from genuine examples. |
| `possible_tampering` | Signs of a replaced photo, duplicated areas, or edited text. |
| `possible_recapture` | Signs of a photo of a screen or a print. |
| `provenance_unavailable` | The AI-image check could not run. |
| `automated_checks_incomplete` | The checks did not finish after several tries. |
| `authenticity_incomplete` | The document could not be straightened, or an authenticity check failed to run. |
| `face_compare_unavailable` | The face comparison did not complete. |
| `barcode_partial_match` | The licence front only partly matches the barcode. |
| `licence_dates_conflict` | More than one date of birth was read from the licence. |
| `held_document_unconfirmed` | The number on the held document could not be read. |
| `apparent_age_mismatch` | The face looks younger than the minimum age. Estimated age is never itself a decline. |

## Identity

`identity` is null until a result is stored. Fields can still be null when a value could not be read. `dateOfBirth` is `YYYY-MM-DD`. `age` is the age in whole years at decision time. `issuingCountry` is `GB`, `IE`, or `US` when known.

```json
"identity": {
  "firstName": "Alex",
  "lastName": "Morgan",
  "fullName": "Alex Morgan",
  "dateOfBirth": "1998-04-12",
  "age": 28,
  "sex": "F",
  "nationality": "GBR",
  "documentNumber": "123456789",
  "issuingCountry": "GB",
  "issuingRegion": null,
  "expiryDate": "2030-04-11",
  "issueDate": "2020-04-12",
  "address": null
}
```

`documentType` is `passport` or `driving_licence`. ID images and the extracted identity are deleted after 30 days, unless the check is still `needs_review`. A manual decision starts that clock again. The outcome, reason codes, and checks stay.

<p class="notice">A clear automated approval is not a government database match. A good real-time face swap, a lookalike with a genuine document, or a forged card whose number matches the forged name and date of birth can still pass the automated declines. Authenticity checks then raise review flags rather than decline.</p>
