Skip to main content

Identity Verification with sajn ID

Use sajn ID to verify customer identities using Swedish BankID before granting access to services or completing transactions.

Overview

sajn ID provides two verification methods:
  • SSN-based: Verifies identity AND Swedish personal number
  • Name-based: Verifies identity and name match without requiring SSN

Quick Start

Create and send a verification request:
curl -X POST https://app.sajn.se/api/v1/sajn-id \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "John Doe",
    "email": "john@example.com",
    "channel": "EMAIL",
    "sendImmediately": true
  }'
The user receives an email with a verification link and completes BankID authentication.

Use Cases

Customer Onboarding

Verify identity during account creation:
{
  "fullName": "John Doe",
  "ssn": "197001011234",
  "email": "john@example.com",
  "channel": "EMAIL",
  "reference": "customer_signup_2024_001",
  "note": "New customer registration",
  "sendImmediately": true
}

Age Verification

Verify someone is 18+ without collecting SSN:
{
  "fullName": "Jane Smith",
  "email": "jane@example.com",
  "channel": "EMAIL",
  "reference": "age_verification",
  "note": "18+ age check for alcohol purchase",
  "sendImmediately": true
}

Pre-Contract Verification

Verify identity before allowing document signing:
{
  "fullName": "John Doe",
  "ssn": "197001011234",
  "email": "john@example.com",
  "channel": "EMAIL",
  "contactId": "contact_123",
  "reference": "pre_contract_verification",
  "note": "ID check before loan agreement",
  "sendImmediately": true
}

SSN-Based vs Name-Based

When to Use SSN-Based

Use SSN-based verification when you:
  • Need to verify the exact person (e.g., financial services)
  • Are legally required to collect and verify SSN
  • Need to match against government databases
{
  "fullName": "John Doe",
  "ssn": "197001011234",
  "email": "john@example.com",
  "channel": "EMAIL"
}

When to Use Name-Based

Use name-based verification when you:
  • Only need to verify identity, not specific SSN
  • Want to respect privacy (GDPR-friendly)
  • Just need age verification
{
  "fullName": "John Doe",
  "email": "john@example.com",
  "channel": "EMAIL"
}

Verification Flow

  1. Create verification via API
  2. User receives link via email or SMS
  3. User clicks link and opens verification page
  4. User authenticates with BankID app
  5. Verification completes and you receive webhook notification
  6. Retrieve results via API

Checking Verification Status

Poll for status updates:
GET /api/v1/sajn-id/{verificationId}
Response when pending:
{
  "id": "verify_123",
  "status": "SENT",
  "fullName": "John Doe",
  "email": "john@example.com",
  "usedAt": null
}
Response when completed:
{
  "id": "verify_123",
  "status": "VERIFIED",
  "fullName": "John Doe",
  "email": "john@example.com",
  "usedAt": "2024-01-15T10:30:00Z",
  "data": {
    "completionData": {
      "user": {
        "personalNumber": "197001011234",
        "name": "John Doe",
        "givenName": "John",
        "surname": "Doe"
      }
    }
  }
}

Webhook Integration

Receive real-time notifications:
{
  "event": "SAJN_ID_VERIFIED",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "verificationId": "verify_123",
    "fullName": "John Doe",
    "status": "VERIFIED",
    "reference": "customer_signup_2024_001"
  }
}

Linking to Contacts

Link verifications to existing contacts for audit trail:
{
  "fullName": "John Doe",
  "email": "john@example.com",
  "channel": "EMAIL",
  "contactId": "contact_123"
}
This creates a permanent record in the contact’s history.

Implementation Example

Complete verification workflow:
// Step 1: Create verification
const verification = await fetch('https://app.sajn.se/api/v1/sajn-id', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fullName: 'John Doe',
    email: 'john@example.com',
    channel: 'EMAIL',
    reference: 'signup_123',
    sendImmediately: true
  })
}).then(r => r.json());

// Step 2: Poll for completion (or use webhooks)
const checkStatus = async (verificationId) => {
  const status = await fetch(
    `https://app.sajn.se/api/v1/sajn-id/${verificationId}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  ).then(r => r.json());

  if (status.status === 'VERIFIED') {
    // Verification successful
    console.log('Verified:', status.data);
    return true;
  } else if (status.status === 'FAILED' || status.status === 'EXPIRED') {
    // Verification failed
    console.log('Failed:', status.failureReason);
    return false;
  }

  // Still pending, check again later
  return null;
};

Security & Privacy

SSNs are encrypted at rest and only accessible to authorized users.
Verification tokens are single-use and expire after completion or timeout.
Complete audit trail tracks every step of the verification process.
Name-based verification minimizes personal data collection per GDPR principles.

Best Practices

Clear Purpose

Use the note field to document why verification is needed for compliance.

Reference IDs

Always include a reference to link verification to your workflow.

Minimal Data

Use name-based verification when SSN isn’t legally required.

Webhooks

Use webhooks instead of polling for better user experience.

Troubleshooting

Verification Not Received

  • Check spam/junk folders
  • Verify email/phone is correct
  • Check verification wasn’t already used
  • Look for delivery failures in dashboard

BankID Failed

Common reasons:
  • User canceled authentication
  • BankID app not responding
  • Wrong personal number provided
  • BankID account issues
The user can retry by clicking the link again.

Name Mismatch

If name-based verification fails due to mismatch:
  • Double-check spelling in request
  • Ask user for their exact registered name
  • Consider SSN-based verification for certainty

Next Steps

I