# Session Webhooks

Session webhooks let you set up notifications for events that happen during any session triggered by a Flow or Workflow. You can [configure them](https://developer.incode.com/docs/configuration-webhooks-tab), along with other types of webhooks, in Dashboard.

## Learn more about webhooks

Webhooks are event notifications. They let your organization's application know when a specific event happens on the Incode platform or when a process initiated by a user is completed (also known as a callback). Your application can then take action based on the notification.

Webhooks are asynchronous (that is, the communication is only from the Incode platform to your application). You must configure them if you want to use them.

Each session webhook notifies you about a specific session event. This is different from the [Onboarding Status webhook,](https://developer.incode.com/update/docs/onboarding-status-webhook) which sends notifications at the completion of every module during a single session. Depending on the number of modules in the session Flow or Workflow, this could be more notifications than you need or want.

Session webhooks provide additional flexibility and let you tailor your notifications for specific needs.

There are six session webhooks available:

- **Session Started:** Triggered when any session triggered by a Flow or Workflow starts.
- **Session Progress:** Triggered on any `/start` endpoint call after the initial session creation. For example, when an end user resumes a session on their phone.
- **Session Failed:** Triggered when any session triggered by a Flow or Workflow fails. Sessions can fail at various points and for various reasons during a Flow or Workflow. You can view more information about failed sessions in Dashboard. Go to **Dashboard** > **Sessions** and click any session in the table to open it.
- **Session Succeeded:** Triggered when any session triggered by a Flow or Workflow succeeds.
- **Session Pending Review:** Triggered when any session triggered by a Flow or Workflow requires manual review.
- **Identity Enrolled:** Triggered the first time an Identity is created. Updates to an existing Identity do not emit this event.

***

## Key facts about session webhooks

- Each session webhook notification contains a number of common fields. These provide context and allow you to track what's happening more easily.
- Notifications come as `POST` requests to the endpoint you configured in Dashboard.
- Notification headers are passed as key/value pairs.
- Notification payloads are sent in JSON format. You must configure any internal settings to include `Accept Application/json`.
- Data is included in the first notification for which it is available.

***

## Notification payload fields

### Common fields

The fields in the following table are common to all session webhook notifications (`SESSION_STARTED`, `SESSION_PROGRESS`, `SESSION_FAILED`, `SESSION_SUCCEEDED`, and `SESSION_PENDING_REVIEW`). They are the only fields included in `SESSION_STARTED` and `SESSION_PROGRESS`.

| Field                | Type     | Description                                                                                                                                                    |
| -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_type`         | `string` | Name of the webhook providing the notification: `SESSION_STARTED`, `SESSION_PROGRESS`, `SESSION_FAILED`, `SESSION_SUCCEEDED`, or `SESSION_PENDING_REVIEW`      |
| `timestamp`          | `string` | UTC timestamp of the triggering event in ISO 8601 format                                                                                                       |
| `interviewId`        | `string` | Unique identifier for the session                                                                                                                              |
| `externalCustomerId` | `string` | Unique identifier from your system that is used for data matching                                                                                              |
| `clientId`           | `string` | Unique identifier assigned to your organization                                                                                                                |
| `configurationId`    | `string` | Unique identifier assigned to the Flow or Workflow for this session                                                                                            |
| `integrationId`      | `string` | Unique identifier assigned by Incode to the integration associated with this session. If there was no integration for the session, this field does not appear. |
| `integrationType`    | `string` | Type of integration associated with this session. If there was no integration for the session, this field does not appear.                                     |
| `loginHint`          | `string` | Displays a value entered by the end user as a login hint for this session. If no login hint was used, this field does not appear.                              |
| `devices`            | `array`  | Not included in `SESSION_STARTED` or `SESSION_PROGRESS` notifications. See [Devices array](#devices-array) for details.                                        |

### Fields available after a session starts

The next table explains fields that are only available after a session starts. These fields are included in `SESSION_FAILED`, `SESSION_SUCCEEDED`, or `SESSION_PENDING_REVIEW` notifications.

| Field              | Type     | Description                                                                                                                                                                  |
| ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onboardingStatus` | `string` | Status of the session; the value is always `ONBOARDING_FINISHED`. The term "onboarding" here applies to any session.                                                         |
| `ip`               | `string` | IP address for the end user device (legacy field, preserved for backward compatibility). Not available for fully API-integrated sessions.                                    |
| `latitude`         | `string` | Latitude at which the end user device was located during the session (legacy field, preserved for backward compatibility). Not available for fully API-integrated sessions.  |
| `longitude`        | `string` | Longitude at which the end user device was located during the session (legacy field, preserved for backward compatibility). Not available for fully API-integrated sessions. |
| `devices`          | `array`  | Structured array of device objects containing enriched device fingerprint data. Empty array (`[]`) when no device data is available. See [Devices array](#devices-array).    |

### Fields available for specific event types

The following table explains fields that appear only in specific event type notifications.

| Field            | Event type(s)                         | Type     | Description                                                                                                                                                                              |
| ---------------- | ------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `identityId`     | `SESSION_SUCCEEDED`, `SESSION_FAILED` | `string` | Unique identifier for the Identity that was matched or created for this session. Included in `SESSION_FAILED` when the failed session is tied to an existing Identity.                   |
| `failureReasons` | `SESSION_FAILED`                      | `array`  | Sorted, deduplicated array of upper-snake-case string identifiers indicating why the session failed. Replaces the legacy `failureReason` field. See [Failure reasons](#failure-reasons). |

### Devices array

The `devices` field is a structured array of device objects included in `SESSION_FAILED`, `SESSION_SUCCEEDED`, and `SESSION_PENDING_REVIEW` notifications. It replaces the flat `ip`, `latitude`, and `longitude` fields previously included. However, these fields are preserved for backward compatibility. Devices are sorted by timestamp, with the oldest first.

Each device object contains the following fields:

| Field         | Type     | Description                               |
| ------------- | -------- | ----------------------------------------- |
| `ip`          | `string` | IP address of the end user device         |
| `latitude`    | `number` | Latitude of the end user device location  |
| `longitude`   | `number` | Longitude of the end user device location |
| `browser`     | `string` | Browser used during the session           |
| `deviceModel` | `string` | Model of the end user device              |
| `deviceType`  | `string` | Type of device (for example, `mobile`)    |
| `osVersion`   | `string` | Operating system and version              |
| `hash`        | `string` | Device fingerprint hash                   |

Example:

```json
{
  "ip": "203.0.113.10",
  "latitude": 37.7749,
  "longitude": -122.4194,
  "browser": "Chrome",
  "deviceModel": "iPhone 15",
  "deviceType": "mobile",
  "osVersion": "iOS 17.5",
  "hash": "fingerprint-hash"
}
```

### Failure reasons

<Callout icon="⚠️" theme="warn">
  ### **Breaking change:** The legacy `failureReason` (singular string) field has been removed from `SESSION_FAILED` notifications and replaced by the `failureReasons` array.
</Callout>

The `failureReasons` field is included only in `SESSION_FAILED` notifications. It contains a stable, sorted, deduplicated array of identifiers indicating why the session failed.

Example:

```json
{
  "event_type": "SESSION_FAILED",
  "failureReasons": ["ID_VALIDATION", "LIVENESS"]
}
```

The following table lists all possible identifiers:

| Identifier                      | Source                                                                                                                                              |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AUTHENTICATION`                | `authentication` score field                                                                                                                        |
| `ID_VALIDATION`                 | `idValidation` score field                                                                                                                          |
| `SECOND_ID_VALIDATION`          | `secondIdValidation` score field                                                                                                                    |
| `ANTIFRAUD`                     | `antifraud` score field                                                                                                                             |
| `LIVENESS`                      | `liveness` score field                                                                                                                              |
| `DEEPSIGHT`                     | `deepsight` score field                                                                                                                             |
| `FACE_CAPTURE_ASSESSMENT`       | `faceCaptureAssessment` score field                                                                                                                 |
| `FACE_RECOGNITION`              | `faceRecognition` score field                                                                                                                       |
| `FACE_RECOGNITION_SECOND_ID`    | `faceRecognitionSecondId` score field                                                                                                               |
| `GOVERNMENT_VALIDATION`         | `governmentValidation` score field                                                                                                                  |
| `VIDEO_SELFIE`                  | `videoConference` score field                                                                                                                       |
| `PREMIUM_EXTERNAL_VERIFICATION` | `premiumExternalVerification` score field                                                                                                           |
| `CURP_VERIFICATION`             | `curpVerification` score field                                                                                                                      |
| `ID_OCR_CONFIDENCE`             | `idOcrConfidence` score field                                                                                                                       |
| `ID_OCR_CONFIDENCE_SECOND_ID`   | `idOcrConfidenceSecondId` score field                                                                                                               |
| `INCODE_WATCHLIST`              | `incodeWatchlistScore` score field                                                                                                                  |
| `DEVICE_RISK`                   | `deviceRisk` score field                                                                                                                            |
| `BEHAVIORAL_RISK`               | `behavioralRisk` score field                                                                                                                        |
| `TRUST_GRAPH`                   | `trustGraph` score field                                                                                                                            |
| `AUTOPILOT`                     | `autopilot` score field                                                                                                                             |
| `INVOICE_VALIDATION`            | `invoiceValidation` score field                                                                                                                     |
| `LINK_EXPIRED`                  | Session link expiry failure path                                                                                                                    |
| `MANUAL_REJECTED`               | Triggered when a session enters Review state and a Dashboard admin rejects the session.                                                             |
| `OTHER`                         | Fallback used when no specific failure reason can be determined. For example, when it's unclear whether a module or a condition caused the failure. |

***

## Identity Enrolled webhook

The `IDENTITY_ENROLLED` webhook fires the first time an Identity is created. It does not fire for updates to an existing Identity.

The payload for `IDENTITY_ENROLLED` uses the following shape:

| Field                  | Type     | Description                                                                                                                         |
| ---------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `eventType`            | `string` | Always `IDENTITY_ENROLLED`                                                                                                          |
| `timestamp`            | `string` | UTC timestamp of the triggering event in ISO 8601 format                                                                            |
| `identityId`           | `string` | Unique identifier for the newly created Identity (required)                                                                         |
| `interviewId`          | `string` | Unique identifier for the session associated with the Identity creation                                                             |
| `externalId`           | `string` | External identifier from the integration, if available. If not available, this field does not appear.                               |
| `externalCustomerId`   | `string` | Unique identifier from your system used for data matching. If not available, this field does not appear.                            |
| `clientId`             | `string` | Unique identifier assigned to your organization                                                                                     |
| `configurationId`      | `string` | Unique identifier assigned to the Flow or Workflow for this session                                                                 |
| `integrationReference` | `string` | Reference to the integration associated with this session. If there was no integration for the session, this field does not appear. |
| `loginHint`            | `string` | Displays a value entered by the end user as a login hint for this session. If no login hint was used, this field does not appear.   |

Example payload:

```json
{
  "eventType": "IDENTITY_ENROLLED",
  "timestamp": "2026-05-20T14:00:00Z",
  "identityId": "65f8...",
  "interviewId": "65f7...",
  "externalId": "ext-abc-123",
  "externalCustomerId": "cust-456",
  "clientId": "client-xyz",
  "configurationId": "flow-prod-onboarding",
  "integrationReference": "ref-789"
}
```

***

## Session Failed on link expiration

When a Workforce verification link expires, the platform sends a `SESSION_FAILED` webhook with `failureReasons` containing `["LINK_EXPIRED"]`. This feature is configuration-dependent. Contact your Incode representative to enable it.

***

## Error handling and retry policy

Webhooks make up to 5 attempts to deliver a notification in case of endpoint failures. You should ensure your endpoint is ready to handle retries and process duplicate notifications gracefully.

Retries will be triggered by either of these scenarios:

- A timeout is received when your endpoint is called
- A status code is returned from your service and is not either:
  - `200 OK` along with the `application/json` header, or
  - `204 No content`

The retry policy for webhooks is exponential, with an initial interval of 30 seconds and a multiplier of 2.5. The maximum number of attempts is 5. This means the maximum time a webhook can take to reach its destination is approximately 32 minutes, as illustrated in the following table.

| Retry attempt | Delay (seconds) | Delay (minutes) | Total (minutes) |
| :-----------: | --------------: | --------------: | --------------: |
|       1       |              30 |             0.5 |             0.5 |
|       2       |              75 |            1.25 |            1.75 |
|       3       |           187.5 |            3.13 |            4.88 |
|       4       |          468.75 |            7.81 |           12.69 |
|       5       |        1,171.88 |           19.53 |           32.22 |

***

## Webhook IP address list

If your organization restricts inbound traffic for your network, make sure the following IP addresses are added to your allow list.

### United States

Allow the IP addresses shown in this table for the SAAS (Production) environment.

| IP Address    | Active                 |
| ------------- | ---------------------- |
| 54.86.34.156  | Currently Active       |
| 3.142.125.52  | Currently Active       |
| 54.85.117.182 | As of February 2, 2026 |
| 3.233.40.153  | As of February 2, 2026 |

Allow this IP address for the Demo environment.

| IP Address     | Active                                                |
| -------------- | ----------------------------------------------------- |
| 34.198.171.165 | Active since October 2024 (previously 18.210.119.234) |

### Europe

Allow this IP address for both the Production and Demo environments.

| IP Address    | Active |
| ------------- | ------ |
| 18.158.116.18 | Active |

<br />
