Overview

API integration provides complete control over the user verification experience through custom UIs and direct API calls. Choose this approach when you need full customization of the user journey.
When to use API Integration:
  • Need complete UI customization
  • Building native mobile applications
  • Require specific flow control logic
  • Want to handle multiple providers differently

Prerequisites

Implementation Steps

Step 1: Create Verification Session

Start a verification session with your chosen provider:
curl -X POST https://sandbox.connect.hopae.com/api/v1/verifications \
  -u "CLIENT_ID:CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "providerId": "bankidse"
  }'

Step 2: Handle Flow Response

The API response varies by verification flow type:
Response
{
  "verificationId": "eec15acab80b472bb20160d5751b8b40",
  "status": "initiated",
  "providerId": "bankidse",
  "flowType": "qr",
  "flowDetails": {
    "qrData": "bankidse:///?token=7c40b5c1-..."
  },
  "expiresAt": "2024-07-30T10:05:00.000Z"
}
Implementation:
  1. Generate QR code from flowDetails.qrData
  2. Display QR code to user
  3. Poll for verification status
Example
// Generate QR code
const qrCode = await QRCode.toDataURL(response.flowDetails.qrData);

// Display in UI
document.getElementById('qr-code').src = qrCode;

Step 3: Poll for Status

For QR Code and Push flows, poll the verification status:
const pollVerification = async (verificationId) => {
  const pollInterval = setInterval(async () => {
    try {
      const response = await fetch(`https://sandbox.connect.hopae.com/api/v1/verifications/${verificationId}`, {
        headers: {
          Authorization: `Basic ${btoa(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
        },
      });

      const data = await response.json();

      switch (data.status) {
        case "completed":
          clearInterval(pollInterval);
          handleSuccess(data.verifiedAttributes);
          break;
        case "failed":
        case "expired":
          clearInterval(pollInterval);
          handleError(data);
          break;
        // Continue polling for 'initiated' status
      }
    } catch (error) {
      clearInterval(pollInterval);
      handleError(error);
    }
  }, 3000); // Poll every 3 seconds

  // Set timeout for maximum polling duration
  setTimeout(() => {
    clearInterval(pollInterval);
    handleTimeout();
  }, 300000); // 5 minutes timeout
};

Step 4: Handle Completion

Process the verified user attributes:
Successful Verification Response
{
  "verificationId": "eec15acab80b472bb20160d5751b8b40",
  "status": "completed",
  "providerId": "bankidse",
  "verifiedAttributes": {
    "sub": "pairwise-user-identifier",
    "name": "Anders Eriksson",
    "given_name": "Anders",
    "family_name": "Eriksson",
    "birthdate": "1985-07-12",
    "email": "anders.eriksson@example.com",
    "eid": "bankidse",
    "provider_id": "198507124567"
  },
  "verifiedAt": "2024-07-30T10:01:30.000Z"
}

Error Handling

ErrorDescriptionAction
300001Session not foundVerify session ID is correct
300003Invalid status transitionSession already completed
400002Provider not enabledEnable provider in dashboard
400005Provider unavailableTry again later or use fallback

Error Code Reference

View complete error codes and handling strategies

Best Practices

Comparison with Webview

Consider Webview Integration First: The Webview integration handles all flow complexities automatically and is recommended unless you specifically need: - Complete UI customization - Native mobile app integration - Custom flow logic

Next Steps