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

# Run a workflow

> Present DeepIDVWorkflowView to run a verification workflow: create, run or resume a session, and what the user sees at each step.

`DeepIDVWorkflowView` runs a workflow you built in the [Admin Console](https://docs.deepidv.com/workflows/workflows.md) against one session, step by step, and reports one result when the user is done.

Supported steps: **ID verification** (one, two or three documents) and **face liveness**. A workflow with any other step fails with `.validation` before the camera opens.

## Three ways to start

> [tab] Session from your backend (recommended)
>
> Your backend creates the session with [Create workflow session](https://docs.deepidv.com/api-reference/workflow-runner/create-workflow-session.md) and passes the app its ID.
>
> ```swift theme={null}
> DeepIDVWorkflowView(client: client, sessionID: sessionID) { result in
>     // handle the result
> }
> ```
>
> The session must be new: one that has started or finished fails with `.conflict`. To continue a started session, resume it.

> [tab] Let the view create it
>
> The view creates the session from the app. The user's details are sent from the device.
>
> ```swift theme={null}
> DeepIDVWorkflowView(
>     client: client,
>     workflowID: "YOUR_WORKFLOW_ID",
>     user: WorkflowUser(
>         email: "jane.doe@example.com",
>         firstName: "Jane",
>         lastName: "Doe",
>         phone: "+14155552671",    // optional, E.164
>         externalID: "user_12345"  // optional, your own ID
>     )
> ) { result in
>     // handle the result
> }
> ```

> [tab] Resume a session
>
> Continue a session that started but didn't finish. See [Resuming](https://docs.deepidv.com/integrate/sdks/ios/workflows/resuming.md).
>
> ```swift theme={null}
> DeepIDVWorkflowView(client: client, resumingSessionID: sessionID) { result in
>     // handle the result
> }
> ```

Every initializer also takes `documentCamera:` to choose the camera for this view only. See [Camera](https://docs.deepidv.com/integrate/sdks/ios/camera.md).

### Sessions from your backend

Creating the session on your backend keeps the user's details on your server, ties the session to a signed-in user, and lets your [proxy](https://docs.deepidv.com/integrate/sdks/ios/proxy-mode.md) refuse requests for anyone else's session.

```mermaid theme={null}
sequenceDiagram
    participant App
    participant Backend as Your backend
    participant API as deepidv
    App->>Backend: start verification
    Backend->>API: POST /v1/workflows/{id}/sessions
    API-->>Backend: session_id
    Backend-->>App: session_id
    App->>App: DeepIDVWorkflowView(sessionID:)
    API-->>Backend: webhook: session.status.verified / rejected
```

## Present it full screen

The view fills the screen and runs the camera. Present it with `fullScreenCover` (SwiftUI) or a full-screen `UIHostingController` (UIKit), and close it from `onResult`.

```swift theme={null}
.fullScreenCover(isPresented: $isVerifying) {
    DeepIDVWorkflowView(client: client, sessionID: sessionID) { result in
        isVerifying = false
        // handle the result
    }
}
```

```swift UIKit theme={null}
let controller = UIHostingController(
    rootView: DeepIDVWorkflowView(client: client, sessionID: sessionID) { [weak self] result in
        self?.dismiss(animated: true)
        // handle the result
    }
)
controller.modalPresentationStyle = .fullScreen
present(controller, animated: true)
```

## What the user sees

![iPhone screen: a lock badge with 'Preparing your verification, this only takes a moment'.](https://mintcdn.com/deep-identity-inc/KR_jLd52VE3haGnp/images/ios/workflow-preparing-light.webp?fit=max\&auto=format\&n=KR_jLd52VE3haGnp\&q=85\&s=3ec18de8baa1faed49d534bf742c09be)

![iPhone screen: the captured sample ID and a selfie thumbnail with 'Verifying your identity, securely sending your photos' and a progress bar.](https://mintcdn.com/deep-identity-inc/KR_jLd52VE3haGnp/images/ios/workflow-submitting-light.webp?fit=max\&auto=format\&n=KR_jLd52VE3haGnp\&q=85\&s=b218e6e65e7b451a144e9f52db7663c7)

![iPhone screen: a retry badge with 'We couldn't read your ID', advice to use good light and avoid glare, '2 attempts left', and Try again and Cancel buttons.](https://mintcdn.com/deep-identity-inc/KR_jLd52VE3haGnp/images/ios/workflow-retry-light.webp?fit=max\&auto=format\&n=KR_jLd52VE3haGnp\&q=85\&s=86247b120ff0db97f83019f92c008248)

![iPhone screen: a paper-plane badge with 'Thanks, you're done. We've received your details.' and a Done button.](https://mintcdn.com/deep-identity-inc/KR_jLd52VE3haGnp/images/ios/workflow-thank-you-light.webp?fit=max\&auto=format\&n=KR_jLd52VE3haGnp\&q=85\&s=65539b33d52c39d71e354a704a29aa3f)

Around the steps: preparing, sending, a retry, and the closing screen.

| Moment | Screen | Notes |
| - | - | - |
| Opening | **Preparing your verification** | Fetches the workflow and starts the session. A resumed session shows **Picking up where you left off**. |
| ID verification | Document picker, then the [document camera](https://docs.deepidv.com/integrate/sdks/ios/document-capture.md), then the [selfie](https://docs.deepidv.com/integrate/sdks/ios/selfie.md) | The picker lists only the document types the workflow accepts, and is skipped when it accepts just one. Cards are captured front and back unless the workflow marks the type front-only; passports are always front-only. A second or third document repeats the picker. |
| Sending | **Verifying your identity** | Shows the ID and selfie just taken while the photos upload. |
| A check fails | Retry screen with the attempts left | The SDK retakes only what failed: the selfie, or the document with the same type, or returns to the picker if the type isn't accepted. See [Failures](https://docs.deepidv.com/integrate/sdks/ios/workflows/failures.md). |
| Face liveness | The [liveness check](https://docs.deepidv.com/integrate/sdks/ios/face-liveness.md) | |
| Done | **Thanks, you're done** | The same whatever the decision, so it never tells the user whether they passed. Closes after 3 seconds or with **Done**, then `onResult` fires. |
| Error | Error screen | Network and server errors offer **Try again**, which continues from the current step. |

To skip the closing screen and return to your app straight away, set `showsCompletionScreen` to `false` in [`DeepIDVConfig`](https://docs.deepidv.com/integrate/sdks/ios/reference/configuration).

## Handle the result

`onResult` fires exactly once, with a `Result<WorkflowRunResult, DeepIDVError>`.

```swift theme={null}
DeepIDVWorkflowView(client: client, sessionID: sessionID) { result in
    switch result {
    case .success(let run):
        if let failure = run.sessionFailure {
            // The run ended without being submitted, e.g. attempts ran out.
            showMessage(for: failure.code)
        } else {
            showSubmittedScreen()   // the decision arrives on your backend
        }
    case .failure(let error):
        switch error.kind {
        case .cancelled:
            break                    // the user closed it
        case .cameraPermissionDenied:
            showCameraHelp()
        default:
            showGenericError()
        }
    }
}
```

* `.success` means the run ended normally: submitted, or out of attempts (`sessionFailure` is set).
* `.failure` is for errors: network, permissions, cancellation, a session that can't run.

Details: [Results and the decision](https://docs.deepidv.com/integrate/sdks/ios/workflows/results.md), [Failures](https://docs.deepidv.com/integrate/sdks/ios/workflows/failures.md), [Errors](https://docs.deepidv.com/integrate/sdks/ios/reference/errors.md).

## Headless session calls

To inspect or drive a session without UI:

| Method | Does |
| - | - |
| `createWorkflowSession(workflowID:user:expiresInHours:)` | Creates a session (prefer your backend). |
| `startWorkflowSession(sessionID:)` | Starts it. |
| `resumeWorkflowSession(sessionID:)` | Returns where an unfinished session stands. |
| `fetchWorkflowState(sessionID:)` | Reads the state of any session, finished or not. |

Each returns a `WorkflowExecutionState` (or `WorkflowSession` for create) with the steps, their status, attempts left and failures.


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