KYC Docs Get credentials
Docs › Blink SDK › React Native

React Native

Install blink-kyc-react-native, create a session token on your backend, let the SDK run the document and liveness capture on Blink's native screens, then read the verified result from your backend. The package is a thin TypeScript bridge over the Blink Android and iOS SDKs, so the capture screens, the on-device checks and the upload are the same ones the native SDKs ship.

package blink-kyc-react-native 1.0.13 API https://kyc-api.blink-pay.net React Native 0.76+ · new architecture iOS 15.5+ · Android API 24+

00How it works

Three parties, three calls. Your client secret lives only on your backend; the phone only ever holds a short-lived session token; and the result you act on is the one your backend reads from Blink.

1 · Your backend

Create a session

POST /api/blink/session/create with your client key and secret. Returns sessionId and sessionToken.

2 · Your React Native app

Run the capture

Pass the sessionToken to BlinkKyc.present. The native screens take over, photograph the document, run the liveness check and upload to Blink.

3 · Your backend

Read the result

GET /api/blink/session/{sessionId}/result. Act on VERIFIED, REJECTED or REVIEW.

Never put the client secret in the app. Anything shipped in a JavaScript bundle can be extracted. The app asks your backend for a session token, and your backend asks Blink.

01Install the package

blink-kyc-react-native is served from the Blink artifact site, not the public npm registry. Install it from its tarball URL; npm records the URL in package.json and its checksum in package-lock.json:

terminalshell
npm install https://blink-pay.net/maven/npm/blink-kyc-react-native-1.0.13.tgz

The package is a TurboModule and needs the React Native new architecture, which is the default since 0.76. It is built and verified against React Native 0.87. There is no config plugin: Expo projects need a development build (npx expo prebuild), because Expo Go cannot load native code.

src/kyc.tstypescript
import { BlinkKyc, BlinkKycError } from 'blink-kyc-react-native';

02Android & iOS setup

Android

The module depends on the native Blink Android SDK, com.blink.kyc:blink-kyc-android, and adds its repository, https://blink-pay.net/maven/releases, to every project of your Gradle build, so a plain npx react-native run-android resolves it. If your settings.gradle locks repositories (RepositoriesMode.FAIL_ON_PROJECT_REPOS), declare it there:

android/settings.gradlegroovy
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://blink-pay.net/maven/releases") }
    }
}

Your app needs a minimum SDK of 24 (React Native's default). The camera, internet and NFC permissions, the capture activity and the hardware features are declared by the native SDK and merged into your manifest; nothing to add. Build with JDK 17 or 21.

iOS

The native Blink iOS SDK targets iOS 15.5, which is above React Native's own minimum, so set the platform in your Podfile. The pod is a static framework and works with React Native's default static linkage: use_frameworks! is not required.

ios/Podfileruby
platform :ios, '15.5'   # instead of min_ios_version_supported
prepare_react_native_project!

pod install downloads BlinkKyc.xcframework and its model bundle from the Blink artifact site into the package (once per native SDK version; if an update leaves the build without it, run pod install again) and pins the Swift dependencies the binary was built with, TensorFlowLiteSwift, NFCPassportReader and lottie-ios. Add the camera usage description to Info.plist:

ios/YourApp/Info.plistxml
<key>NSCameraUsageDescription</key>
<string>We use the camera to photograph your document and confirm your identity.</string>

Passport chip reading is off in this release. The ePassport NFC step is built into the native SDKs but disabled until the on-device reader has been tested, so no NFC usage description or entitlement is needed. A free personal Apple team can sign the app; document photo plus liveness work in full.

03Backend: create a session

Expose an endpoint on your backend that your app calls when the user starts verification. It authenticates your user, calls Blink with your client credentials, and returns only the session token and id. The backend side is identical for every SDK; the Flutter guide carries Node.js and Dart examples of the endpoint, and the Session API reference has every field.

POST https://kyc-api.blink-pay.net/api/blink/session/createhttp
curl -sX POST https://kyc-api.blink-pay.net/api/blink/session/create \
  -H 'content-type: application/json' \
  -d '{
        "clientKey":    "bkyc_live_…",
        "clientSecret": "bksec_…",
        "purpose":      "FULL_CAPTURE",
        "userRef":      "customer-8841"
      }'

→ 200
{
  "sessionId":    "[SESSION_ID]",
  "sessionToken": "bkyc_sess_…",
  "expiresAt":    "2026-09-15T18:42:10Z",
  "purpose":      "FULL_CAPTURE"
}

Store sessionId against your user — you need it to read the result. Sessions are short-lived: create one when the user taps Verify, not ahead of time. Only the token and id go to the phone.

04App: run the capture

Ask your backend for a session, hand the token to BlinkKyc.present, and await the device-side result. The native screens own the camera: document detection, auto-capture, on-device MRZ reading and the action-guided liveness check all run there, and the promise settles when the customer is done.

src/kyc.tstypescript
import { BlinkKyc, BlinkKycError } from 'blink-kyc-react-native';

const BACKEND = 'https://api.yourbank.com';

export async function startVerification(userJwt: string): Promise<void> {
  // 1. Your backend creates the Blink session (section 03).
  const res = await fetch(`${BACKEND}/kyc/sessions`, {
    method: 'POST',
    headers: { authorization: `Bearer ${userJwt}` },
  });
  const session: { sessionId: string; sessionToken: string } = await res.json();

  try {
    // 2. The native SDK runs document + liveness capture and uploads to Blink.
    const result = await BlinkKyc.present({
      sessionToken: session.sessionToken,
      issuingCountry: 'SDN',        // SDN or ARE; omit to let the session decide
      documentType: 'PASSPORT',     // omit to let the session decide
      locale: 'en',                 // or 'ar' for Blink's built-in Arabic screens
    });

    // 3. Show progress to the user, but decide nothing here —
    //    ask your backend, which reads the authoritative result (section 05).
    console.log('device copy:', result.verdict);   // 'verified' | 'rejected' | 'review'
    await fetch(`${BACKEND}/kyc/sessions/${session.sessionId}/complete`, {
      method: 'POST',
      headers: { authorization: `Bearer ${userJwt}` },
    });
  } catch (e) {
    if (e instanceof BlinkKycError) {
      // The user cancelled or a step failed. Switch on e.code, not the message.
      if (e.code === 'BLINK_CAPTURE_CANCELLED') return;   // user closed the capture
      console.warn(e.code, e.message);
    } else {
      throw e;
    }
  }
}

Configuration

BlinkKyc.present(config) takes one object. Only the token is required; everything else defaults to letting the session decide.

FieldTypeMeaning
sessionTokenstringRequired. The short-lived token from your backend. Never a client key or secret.
baseUrlstringThe Blink API base URL. Defaults to https://kyc-api.blink-pay.net.
issuingCountry'SDN' | 'ARE'The document's issuing country. Omit to let the session decide.
documentTypeBlinkDocumentType'PASSPORT', 'NATIONAL_ID', 'DRIVING_LICENCE', 'VISA' or 'VEHICLE_LICENCE'. Omit to let the session decide.
locale'en' | 'ar'The language of the capture screens. Defaults to the device locale.
rejectExpiredDocumentsbooleanStop an expired document on the device before upload. Defaults to true.
themeBlinkThemeColours, sizes, positions and images for the native screens. Omit for the built-in look. See Theme below.

The promise resolves with { verdict, detail? }, where verdict is 'verified', 'rejected' or 'review' and detail is a neutral one-line summary for your logs. It rejects with BlinkKycError, whose code is the native error code (section 06).

The session's policy wins. When the capture starts, the SDK reads the session's required steps and allowed documents from Blink. issuingCountry and documentType are hints that fill gaps — a step the session requires cannot be switched off in the app.

Theme

theme styles the native screens. Every field is optional and keeps the built-in look when left out. Colours are ARGB numbers, as in the native SDKs:

VerifyScreen.tsxtypescript
const result = await BlinkKyc.present({
  sessionToken,
  theme: {
    accent: 0xff15803d,
    brandName: 'Your Bank',
    logo: { resource: 'bank_logo' },   // Android drawable / iOS asset-catalogue name
    scrimColor: 0xff0e1e4d,            // the dimmed area outside the document frame
    scrimOpacity: 0.35,                // 0 clear … 1 opaque; 0.6 unless set
    guideSuccessColor: 0xff22c55e,
  },
});

The fields are the native BlinkTheme's, listed with what each one changes in Customisation. An image is { resource: 'name' } or { file: '/path/to/image.png' }. An invalid value rejects with BLINK_CONFIG.

Session QR codes and hosted links

If your dashboard or backend produces a session QR or hosted link (https://kyc-api.blink-pay.net/h/?t=bkyc_sess_…), read the token out of it locally and pass it as sessionToken. Parse, never open, the link: take the sessionToken, session_token or t query parameter, or the token itself when the code holds a bare bkyc_sess_… value, and only accept links for the API host you expect. Any QR scanner works; the Blink sample app uses react-native-camera-kit.

05Backend: read the result

This is the only verdict to act on. The value present returns on the phone is a convenience copy that a modified app could fake; your backend reads the real one, server to server.

GET https://kyc-api.blink-pay.net/api/blink/session/{sessionId}/resulthttp
curl -s https://kyc-api.blink-pay.net/api/blink/session/[SESSION_ID]/result \
  -H 'X-Blink-Client-Key: bkyc_live_…' \
  -H 'X-Blink-Client-Secret: bksec_…'

→ 200
{
  "sessionId":  "[SESSION_ID]",
  "status":     "COMPLETED",
  "result":     "VERIFIED",
  "resultJson": "{\"sessionId\":\"[SESSION_ID]\",\"purpose\":\"FULL_CAPTURE\",\"result\":\"VERIFIED\",\"faceScore\":0.91,\"detail\":\"…\"}"
}

Only COMPLETED carries a result; route REVIEW to a person, and re-read results from a background job for users who close the app mid-way. The Result API reference describes every field, and the Documents API is how your backend downloads the stored document scans and selfies — the SDK does not hand images back to the app.

06Errors

BlinkKyc.present rejects with a BlinkKycError. Switch on code, never on the message text.

CodeWhat to do
BLINK_CAPTURE_CANCELLEDThe user closed the capture. Not an error to report.
BLINK_CAMERA_DENIEDExplain why the camera is needed and link to Settings.
BLINK_DOCUMENT_EXPIREDThe document's expiry date has passed. The SDK told the user, sent the photograph so the session records it, and closed when they pressed the button; offer a new attempt with a new session.
DOCUMENT_UNREADABLE · LIVENESS_FAILED · …A capture step ran and Blink refused it; the code is Blink's own (see the Errors reference). Offer another attempt with a new session.
BLINK_STEP_FAILEDA step was refused without a code from Blink. Treat it like the row above.
BLINK_STEP_ALREADY_DONEThe session token was already used for that step. Create a new session.
BLINK_RESPONSEBlink rejected the session or a step — the message carries the API's code, such as BLINK_SESSION_INVALID or BLINK_QUOTA_EXCEEDED. Create a new session, or contact Blink if it repeats.
BLINK_NETWORK · BLINK_TIMEOUTConnectivity. Let the user retry.
BLINK_INTEGRITYThe app or device failed Blink's integrity checks. Do not retry automatically.
BLINK_CONFIGA bad argument: an empty token, an unknown document type or country. A programming error, not a user one.
BLINK_NO_ACTIVITY · BLINK_NO_UICalled while the app had no foreground screen to present from (Android / iOS). Call it from a mounted screen.
BLINK_ERRORAnything else; the message says what.

Blink's HTTP errors all share one shape: {"code": "…", "message": "…", "timestamp": "…"}. The full code list is in the Errors reference.

07Go-live checklist

Credentials for sandbox and production are issued under a Blink KYC integration agreement. Talk to us to get set up.