---
Source: https://docs.microblink.com/blinkid/data-match
Title: Validate data match across both sides
Description: Use BlinkID's data match result to verify that fields appearing on both sides of a document agree, a useful tamper signal for double-sided documents.
---

# Validate data match across both sides

When a document is scanned on both sides, some fields appear on both the front and the back.
BlinkID cross-checks these fields and reports whether the values agree.
A `failed` data match is a useful tamper signal: it indicates that the front and the back disagree on a field that should be identical.

Data match is only meaningful for documents scanned on both sides.
For a single-sided scan there is nothing to cross-check, so `dataMatchResult` is `undefined` (web, Android) or `nil` (iOS), and the overall state is `not-performed`.

## Read the overall state

Read `result.dataMatchResult?.overallState` and branch on the verdict.
The state has three values: `success` (every cross-checked field agrees), `failed` (at least one field disagrees), and `not-performed` (no cross-check ran, for example on a single-sided scan).

<Tabs queryString="platform">
  <TabItem value="web" label="Web (TS)" default>

  ```typescript
  switch (result.dataMatchResult?.overallState) {
    case "success":
      // Front and back agree on the cross-checked fields
      break;
    case "failed":
      // At least one field disagrees; treat as a tamper signal
      break;
    case "not-performed":
    default:
      // No cross-check ran (e.g. single-sided scan)
      break;
  }
  ```

  </TabItem>
  <TabItem value="android" label="Android (Kotlin)">

  ```kotlin
  when (result.dataMatchResult?.overallState) {
      DataMatchState.Success -> {
          // Front and back agree on the cross-checked fields
      }
      DataMatchState.Failed -> {
          // At least one field disagrees; treat as a tamper signal
      }
      DataMatchState.NotPerformed, null -> {
          // No cross-check ran (e.g. single-sided scan)
      }
  }
  ```

  </TabItem>
  <TabItem value="ios" label="iOS (Swift)">

  ```swift
  switch result.dataMatchResult?.overallState {
  case .success:
      // Front and back agree on the cross-checked fields
      break
  case .failed:
      // At least one field disagrees; treat as a tamper signal
      break
  case .notPerformed, .none:
      // No cross-check ran (e.g. single-sided scan)
      break
  }
  ```

  </TabItem>
</Tabs>

The enum cases mirror the web string values: `success`, `failed`, and `not-performed`.

## Inspect individual fields

When the overall state is `failed`, inspect `statePerField` to see which specific field disagreed.
Each element has a `fieldType` and its own `state`.

The fields that can be cross-matched are `date-of-birth`, `date-of-expiry`, `document-number`, `document-additional-number`, `document-optional-additional-number`, and `personal-id-number`.

<Tabs queryString="platform">
  <TabItem value="web" label="Web (TS)" default>

  ```typescript
  const failed = result.dataMatchResult?.statePerField.filter(
    (f) => f.state === "failed",
  );
  
  failed?.forEach((f) => {
    console.log(`Field ${f.fieldType} did not match across sides`);
  });
  ```

  </TabItem>
  <TabItem value="android" label="Android (Kotlin)">

  ```kotlin
  val failed = result.dataMatchResult?.statePerField
      ?.filter { it.state == DataMatchState.Failed }
  
  failed?.forEach { f ->
      Log.d("DataMatch", "Field ${f.fieldType} did not match across sides")
  }
  ```

  </TabItem>
  <TabItem value="ios" label="iOS (Swift)">

  ```swift
  let failed = result.dataMatchResult?.statePerField
      .filter { $0.state == .failed }
  
  failed?.forEach { f in
      print("Field \(f.fieldType) did not match across sides")
  }
  ```

  </TabItem>
</Tabs>

## Related articles

- [Result reference](./result-reference.md)
- [Scan a double-sided document](./scan-double-side.md)


Last updated on Jul 24, 2026
