---
title: "Moving off Session Restarts"
url: "https://developer.incode.com/general-reference/moving-off-session-restarts/"
section: "general-reference"
group: "Migrations and Deprecations"
version: "v1.1"
status: "live"
---
# Migration Guide: Moving Off Session Restarts

The ability to call `omni/start` again on a session that already exists, referred to as a **restart**, is being retired. If your integration does this, you need to migrate to one of the replacement paths below before the enforcement date.

## At a glance

| | |
|---|---|
| **Enforcement date** | 30 September 2026 |
| **What's changing** | Restarting a session by calling `omni/start` API or SDK again with an existing `interviewId` or `externalId` |
| **Who's affected** | Any integration that calls `omni/start` with an `interviewId` or `externalId` that already exists |
| **How to check** | Search your integration for call sites where `omni/start` is passed an existing `interviewId` or `externalId`. For each one, work through [Find Your scenario](#find-your-scenario) to identify why. |
| **Grace period** | None. See [Enforcement](#enforcement). |

## What is changing

| | What it is | Status |
|---|---|---|
| **Restart** | Calling `omni/start` API or SDK again with the `interviewId` or `externalId` of an existing session. Begins the flow from the top. | Being retired |
| **Continue** | Calling `/omni/session/continue` to pick the same session back up where it left off. | The supported path going forward |

The 48-hour rule governs **session resume** only. A session can be resumed via [`/omni/session/continue`](/api-reference/session-continue/) within 48 hours of the `omni/start` call that created it, up to twice. Resuming does not extend the window, and once it closes a new session is required. The 48 hours do not apply when a session is only being read using an admin token; there is no limit on session age in that case.

### Enforcement

The enforcement date is **30 September 2026**. There is no reset at that date and no grace period: the 48 hours are measured from each session's own `omni/start` call, so a session created more than 48 hours before enforcement cannot be resumed once enforcement begins.

After the enforcement date, a restart on a session outside its 48-hour window returns HTTP 400:

| Code | Message | Meaning |
|---|---|---|
| 400 | `maximum session lifetime exceeded` | The session is too old to restart. |
| 400 | `maximum session inactivity exceeded` | The session has not been updated recently enough to restart. |



The [`/omni/session/continue`](/api-reference/session-continue/) endpoint returns a distinct response for each rejection case.

## Find your scenario

Work through these in order. The first match is your scenario. An integration may fall into more than one, in which case handle each separately.

| # | Applies when | Replacement |
|---|---|---|
| [1](#scenario-1-reading-session-data) | A session is restarted only to obtain a token in order to read its data (scores, OCR, images) | Use an **admin token** with the `interviewId` as a query parameter. No session opened. |
| [2](#scenario-2-resuming-an-interrupted-session) | A real user drops off and returns within a couple of days to finish | Call `/omni/session/continue` to pick up the same session |
| [3](#scenario-3-step-up-and-additional-checks) | An old session is reopened to run an extra check or collect another document (a signature, a proof of address, a tier upgrade) | Start a **new session** referencing the original via `identityId` |
| [4](#scenario-4-repeating-a-completed-onboarding) | The user completed onboarding, and the finished session is restarted later to run it again | Create a **new session** for each attempt |
| — | None of the above | Contact your Incode CS representative or reach out using the customer portal. |

## Scenario 1: Reading session data

**Applies when:** the integration calls `omni/start` again purely to mint a token, then uses that token to read data. The restart is a side effect of needing a token, not something the flow requires.

**What to do instead:** authenticate with an **admin token** and pass the session's `interviewId` explicitly. No session is opened.

**Prerequisites**:
- Provision an admin user: A dashboard user with the **Admin** role is required on the specific instance being called. The admin token is issued in exchange for that user's email and password. If the account is removed or its password changes, the integration stops working.



- Obtain and refresh the admin token.

:::note
Available today. Required by 30 September 2026.
:::

### The endpoints you'll call

The admin token goes in the **`X-Incode-Hardware-Id`** header, not `Authorization: Bearer`. The session is identified by `interviewId` as a **query parameter**, which is what allows an existing session to be read without opening it.

```bash
curl -X GET 'https://<api-base>/omni/get/ocr-data?id=<interviewId>' \
  --header 'x-api-key: <API_KEY>' \
  --header 'x-incode-hardware-id: <ADMIN_TOKEN>' \
  --header 'api-version: 1.0'
```

| Data required | Call |
|---|---|
| OCR data | [`GET /omni/get/ocr-data?id=<interviewId>`](/api-reference/get-ocr-data/) |
| Scores | [`GET /omni/get/score?id=<interviewId>`](/api-reference/get-score/)|
| Device info | [`GET /omni/get/device-info?id=<interviewId>`](/api-reference/get-device-info/)|
| Images | [`POST /omni/get/images/v2?id=<interviewId>`](/api-reference/get-images-v2/) |
| Session events | [`GET /omni/interview-events?interviewId=<interviewId>`](/api-reference/getevents/)|
| Video selfie download URL | [`GET /omni/generateVideoSelfieDownloadUrl?interviewId=<interviewId>`](/api-reference/generatevideoselfiedownloadurl/)|
| Authentication attempts | [`POST /omni/authentications/external/search`](/api-reference/authentications-external-search/)|
| Custom fields | [`GET /omni/get/custom-fields`](/api-reference/get-custom-fields/)|

**Images.** Use `POST /omni/get/images/v2`, documented at [`get-images-v2`](/api-reference/get-images-v2/) as "Fetch image links". It returns pre-signed download URLs valid for one hour. The v1 path `POST /omni/get/images` returns base64 instead, and responses over 10MB fail at the API gateway. New integrations should use v2.

**Session age.** There is no age restriction on reads made with an admin token. A session from any point in the past can be read, provided its `interviewId` is known.

Log in to obtain a token:

```bash
curl -X POST 'https://<api-base>/executive/log-in' \
  --header 'api-version: 1.0' \
  --header 'Content-Type: application/json' \
  --data '{ "email": "<admin user email>", "password": "<password>" }'
```

The response contains `token` (the admin token, a JWT), plus `refreshToken` and `incodeRefreshToken`. Reference: [`executive/log-in`](/api-reference/executive-log-in/).

One admin token works across all sessions. Store it and reuse it rather than calling `/executive/log-in` for each request. The token expires after **24 hours** by default. Store the expiry alongside the token and request a new one before it lapses, rather than waiting for a call to fail. Refresh via `POST /executive/refresh`, passing the refresh token in the `X-Incode-Hardware-Id` header. The `incodeRefreshToken` is single-use and is invalidated on logout.



:::warning
An admin token together with the API key can read any session in the organization, including personal data. Store the token, the API key, and the admin user's credentials according to your own security policy.
:::

### After migration: remove the old path

Remove any code path that calls `omni/start` with an existing `interviewId` or `externalId` in order to obtain a token for reading.

Storing a session token is not an alternative. The session token TTL is configurable and currently defaults to 90 days; that default is being reduced to 20 minutes.

## Scenario 2: Resuming an interrupted session

**Applies when:** a real user abandons a flow partway and the session is restarted so they can pick up where they left off.

**What to do instead:** call `/omni/session/continue` to obtain a fresh token for the same session. Available within 48 hours of the `omni/start` call that created the session, up to two times.

### What the change looks like

1. **Call `/omni/session/continue` to obtain a new session token**. The session token is scoped to that single session and is passed in the `X-Incode-Hardware-Id` header, the same as the token returned by `omni/start`.
2. **Resume the user at the right step**. If you want the user to pick up exactly where they left off, you need your own record of how far they progressed.
3. **Handle rejection**. A `continue` call fails when either the 48 hours have elapsed or the session has already been continued twice. On rejection, start a new session.

`/omni/start` continues to accept its current behavior during the migration period, so the switch does not have to be made in a single step. For the request and response contract, see the [API reference](/api-reference/start/).

## Scenario 3: Step-up and additional checks

**Applies when:** an existing or completed session is reopened to run an extra verification step or collect another document: a signature, a proof of address, a tier upgrade, or a renewed terms acceptance.

**What to do instead:** start a new session, begin it with authentication against the existing identity, and reference the original via `identityId` so both remain associated under one identity.

### A. Step-ups involving a signature (including NOM-151, AES, or QES)

Development is underway to let a new session retrieve the signature and OCR data from the identity. Endpoint details will follow.

### B. Step-ups that do not involve a signature

Examples include collecting a proof of address months after onboarding or upgrading an account tier.

These are not covered by the 30 September date. Existing behavior continues to work, and guidance will be provided separately.

## Scenario 4: Repeating a completed onboarding

**Applies when:** a user completed onboarding successfully, and days, weeks, or months later the finished session is restarted rather than a new one created. The session was not interrupted partway; it completed.

**What to do instead:** create a new session for each attempt.