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

# Results and errors

> Every decision the server can return, and the typed errors the SDK raises

## The result

`onComplete(result)` fires once the server has reached its decision. That decision is authoritative.

```ts theme={null}
type Decision =
  | "approved"
  | "rejected"
  | "new_capture_requested"
  | "manual_review"
  | "pending";

interface VerificationResult {
  decision: Decision;
  status?: string;
  reason?: string;
  caseId?: string;
}
```

| Decision | What it means | What the SDK does |
| - | - | - |
| `approved` | The subject passed. | Renders a terminal success screen. |
| `rejected` | The subject did not pass. | Renders a terminal screen. |
| `new_capture_requested` | The server wants another attempt. | Shows a retry prompt and re-enters capture on confirmation. |
| `manual_review` | Queued for a human reviewer. | Renders a terminal screen. |
| `pending` | No decision yet. | Renders a terminal screen. |

<Warning>
  Only `approved` should unlock whatever the verification gates. Treat `pending` and `manual_review` as "not yet" — resolve them from your backend against the case, not from the browser.
</Warning>

### Correlating with your own records

`caseId` identifies the verification case. Store it against your user so support requests and any later status change can be reconciled.

<Note>
  Confirm the final state from your backend before granting access. A browser callback tells you what the user saw; it is not a substitute for server-side confirmation, and a client can always be tampered with.
</Note>

## Errors

`onError({ error, fatal })` and the `error` event surface failures. Two typed classes are exported for `instanceof` checks:

| Class | When | Fatal |
| - | - | - |
| `TokenExpiredError` | The session token expired. `onExpire` also fires — re-mint and call `resume(newToken)`. | No |
| `GatewayError` | Any other non-2xx response. Carries `.status` and a best-effort `.body`. | Depends |

```ts theme={null}
import { GatewayError } from "idesify/verification";

callbacks: {
  onError: ({ error, fatal }) => {
    if (error instanceof GatewayError) {
      console.warn(error.status, error.body);
    }
    if (fatal) showYourOwnFallback();
  },
}
```

The `fatal` flag is what to branch on: a non-fatal error leaves the widget mounted and usable, while a fatal one means the flow cannot continue and you should present your own fallback.

<Warning>
  Do not surface `error.body` to end users. It is diagnostic detail meant for your logs — show your own message instead, and keep the raw payload server-side.
</Warning>

## A note on what you can observe

The SDK reports flow progress so you can build a responsive UI around it. It does not report intermediate assessments, and there is nothing in the browser that predicts the outcome.

This is deliberate. Identity decisions are made server-side precisely because the browser is an environment your users control, so any signal exposed there could be manipulated. Build against `onComplete` and your backend, and the design works in your favor.
