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

# Journey Results

> The five outcomes a journey can settle with, their reason codes, and what to do about each.

Every journey settles with a `JourneyResult`. This page is the outcome contract — what each `outcome` means, what each `reason` under it means, and what your app should do in response.

## Three guarantees

* **`start()` settles exactly once.** Every ending — including failure — arrives as a single resolved `JourneyResult`. There is nothing further to await after that.
* **`start()` never rejects.** The only two errors are thrown by `journey()` itself, synchronously, before a handle exists — because the journey never ran. See [Errors](/docs/sdk-reference/journey#errors) for both.
* **`checkResult` rides on decision outcomes only.** It's present on `success`, `pending`, and `declined`; absent on `abandoned` and `error`.

These are what make a `switch` on `outcome` safe: it will always run exactly once, it will always run, and it never needs a `catch` for the happy path. Safe to switch on is not the same as safe to stop at, though — `success` still needs its `reason` checked before you grant access, see [captured is not verified](#captured-is-not-verified) below.

With `withResult: false`, `start()` still settles exactly once with this same `JourneyResult`, but nothing is shown first — no terminal screen mounts, so rendering the outcome to the applicant is yours to do; see [Configuring a journey: Screens](/docs/embedded-flows/journey/configuration#screens) for what the option changes.

## The five outcomes

`JourneyResult` is a discriminated union keyed on `result.outcome`, with `result.reason` as the second discriminant. Branch on both.

### success

The applicant was verified — except for `captured`, which is not a verification decision at all. Check
`reason`, not just `outcome`, before granting access.

| Reason | What to do |
| - | - |
| `verified` | Grant access — the automated checks passed. |
| `verified_manually` | Grant access — a human reviewer made the call, not the automated checks. |
| `captured` | Don't grant access — the journey ran with `triggerVerificationOnSubmit: false`, so it captured and saved the applicant's data but never submitted it for verification. Verify server-side on your own schedule, then grant access based on that result. |

### pending

No decision has been made yet. Wait for a webhook or poll; do not grant access.

| Reason | What to do |
| - | - |
| `manual_review` | Wait — a human reviewer needs to look at this applicant before a decision is made. |
| `awaiting_checks` | Wait — downstream checks are still running. |
| `processing_timeout` | Wait — processing took longer than expected; do not resubmit. |

### declined

A decision was made against the applicant.

| Reason | What to do |
| - | - |
| `checks_failed` | Deny — the automated checks did not pass. |
| `declined_manually` | Deny — a human reviewer rejected the applicant. |
| `duplicate` | Deny — the applicant matches an existing profile. |
| `blocklisted` | Deny — the applicant matches a blocklist entry. |
| `fraud` | Deny — fraud signals were detected. |
| `attempts_exhausted` | Deny — the retry budget ran out. This is a decline, not an error. |
| `profile_archived` | Deny — the applicant's profile has been archived. |
| `profile_inactive` | Deny — the applicant's profile is inactive. |
| `profile_deleted` | Deny — the applicant's profile has been deleted. |

### abandoned

Nothing was decided and the applicant stopped.

| Reason | What to do |
| - | - |
| `session_interrupted` | Offer to resume — the session was interrupted before a decision was reached. |
| `user_exited` | Offer to resume — the applicant left, or your app called `stop()` or `destroy()`. |

### error

The flow could not complete. Check `recoverable` and `error.code` before deciding how to respond.

| Reason | What to do |
| - | - |
| `vendor_load_failed` | Check `recoverable` and `error.code` — the vendor SDK failed to load. |
| `vendor_offline` | Check `recoverable` and `error.code` — the vendor was unreachable. |
| `network` | Check `recoverable` and `error.code` — a network failure interrupted the flow. |
| `session_expired` | Check `recoverable` and `error.code` — the session token expired mid-flow. |
| `submit_failed` | Check `recoverable` and `error.code` — submission failed. |
| `workflow_error` | Check `recoverable` and `error.code` — the backend workflow failed. |
| `workflow_timeout` | Check `recoverable` and `error.code` — the backend workflow timed out. |
| `internal` | Check `recoverable` and `error.code` — an unexpected internal error occurred. |

## Common fields

Every `JourneyResult` carries these fields, regardless of outcome:

| Field | Description |
| - | - |
| `flow` | The `JourneyName` the journey ran. |
| `attempts: { used, max }` | Attempts consumed against `maxAttempts`. |
| `finishedAt` | ISO 8601 timestamp of when the journey settled. |
| `ref` | Identifiers gathered during the run. |

`ref.entityId` is resolved at settlement, not at construction — so even a first-time applicant, with no prior profile, has an `entityId` by the time the journey settles.

## Reading extracted data

`JourneyResult` carries the **decision**, not the applicant's data — there is no field on it for a
captured document's name, date of birth, or similar. The journey calls `individual().search()`
internally as it runs, so that data is already loaded into the individual module by the time the
journey settles. Read it from there:

```javascript theme={null}
const name = oneSdk.individual().access('name').getValue();
const dateOfBirth = oneSdk.individual().access('dateOfBirth').getValue();
```

See [Individual Module](/docs/sdk-reference/individual-module) for the full set of accessible
fields.

## Error detail

`error` results carry an `error` field shaped `{ code, message, vendor?, httpStatus?, requestId? }`. `requestId` is what support asks for when you raise an issue about a failed run.

## pending is not success

<Callout icon="triangle-exclamation" color="#FFCA16" iconType="regular">
  **`pending` is not `success`.** A `pending` journey has no decision yet. Granting access on
  `pending` grants access to an unverified applicant. Branch on `outcome` exhaustively rather than
  testing for failure.
</Callout>

## captured is not verified

<Callout icon="triangle-exclamation" color="#FFCA16" iconType="regular">
  **`success / captured` is not a verification decision.** It means the journey was configured with
  `triggerVerificationOnSubmit: false`: capture completed and the data is saved on the entity, but no
  check ever ran. Branching on `outcome === 'success'` alone will treat it as a pass — check `reason`
  and verify server-side before granting access.
</Callout>

## Reference

See [`JourneyResult`](/docs/sdk-reference/journey#journeyresult) for the exact types, including `JourneyRef` and the full reason-code table.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.