allgram Digital ID - Enterprise-Grade Identity Verification Platform

Build secure, verifiable, and blockchain-based digital identity solutions with our comprehensive Digital ID API. From personal verification to enterprise identity management, from QR-code sharing to secure contact exchange.

allgram Digital ID provides enterprise-level security, GDPR compliance, and seamless integration with popular platforms. Perfect for businesses, developers, and organizations requiring professional identity verification solutions.

Blockchain Security

AES-256, P2P, GDPR compliant

QR Code Exchange

Instant contact sharing, encrypted data

Developer Friendly

REST API, SDKs, comprehensive docs

  • Quick Start Guide
  • Node.js
    Server-side implementation with Express.js, Digital ID creation, and comprehensive API integration

  • Swift
    iOS native development with UIKit/SwiftUI, QR code scanning, and secure Digital ID management

  • Kotlin
    Android development with Jetpack Compose, Digital ID verification, and blockchain integration

  • Additional Resources
    Security, compliance, API reference, and community support

  • Digital ID Services
    Explore enterprise features, pricing, and integration options
  • Licensing
    Commercial licenses, compliance, and enterprise agreements
  • Full Documentation
    Complete API reference, tutorials, and best practices

Node.js Integration

Build robust Digital ID applications with Node.js and Express.js. Our comprehensive API provides identity verification, QR code generation, and enterprise-grade security features. Perfect for building scalable backend services and Digital ID management systems.

  • Full API Support: Complete REST API with Digital ID creation and verification
  • Enterprise Security: AES-256 encryption, blockchain storage, GDPR compliant
  • QR Code Generation: Encrypted QR codes for secure contact sharing
  • Scalable Architecture: Built for high-load production environments
Explore Digital ID Services

// allgram Digital ID Node.js Integration Example
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');
const QRCode = require('qrcode');

class allgramDigitalIDClient {
    constructor(apiKey, baseUrl = 'https://api.allgram.best') {
        this.apiKey = apiKey;
        this.baseUrl = baseUrl;
        this.digitalIDs = new Map();
    }

    // Create Digital ID verification request
    async createDigitalIDRequest(userData) {
        try {
            const response = await axios.post(`${this.baseUrl}/account/v1/did/create/`, {
                first_name: userData.firstName,
                last_name: userData.lastName,
                third_name: userData.thirdName,
                gender: userData.gender,
                place_of_birth: userData.placeOfBirth,
                nationality: userData.nationality,
                date_of_birth: userData.dateOfBirth,
                address: userData.address,
                real_photo: userData.photoBase64,
                document_number: userData.documentNumber,
                files: {
                    imgs: userData.additionalFiles
                }
            }, {
                headers: {
                    'Authorization': `Bearer ${this.apiKey}`,
                    'Content-Type': 'application/json'
                }
            });

            if (response.status === 200) {
                console.log('✅ Digital ID request created successfully');
                return response.data;
            }
        } catch (error) {
            console.error('Failed to create Digital ID request:', error.response?.data || error.message);
            throw error;
        }
    }

    // Get Digital ID information
    async getDigitalIDInfo() {
        try {
            const response = await axios.get(`${this.baseUrl}/account/v1/did/`, {
                headers: {
                    'Authorization': `Bearer ${this.apiKey}`,
                    'Content-Type': 'application/json'
                }
            });

            if (response.status === 200) {
                const digitalID = response.data.data[0];
                this.digitalIDs.set(digitalID.id, digitalID);
                return digitalID;
            }
        } catch (error) {
            console.error('Failed to get Digital ID info:', error.response?.data || error.message);
            throw error;
        }
    }

    // Get public encryption key
    async getPublicKey() {
        try {
            const response = await axios.get(`${this.baseUrl}/utils/v1/public-key/`);

            if (response.status === 200) {
                return response.data;
            }
        } catch (error) {
            console.error('Failed to get public key:', error.response?.data || error.message);
            throw error;
        }
    }

    // Generate encrypted QR code
    async generateEncryptedQRCode(digitalIDData) {
        try {
            // Get current public key
            const keyData = await this.getPublicKey();

            // Prepare QR code data structure
            const qrData = {
                qr_code_data_real: {
                    id: digitalIDData.id,
                    username: digitalIDData.username,
                    first_name: digitalIDData.first_name,
                    last_name: digitalIDData.last_name,
                    third_name: digitalIDData.third_name,
                    date_of_birth: digitalIDData.date_of_birth,
                    gender: digitalIDData.gender,
                    nationality: digitalIDData.nationality
                },
                qr_code_data_contact: {
                    main_email: digitalIDData.main_email,
                    main_phone: digitalIDData.main_phone
                },
                qr_code_data_chat: {
                    is_allowed_direct_chats: true,
                    data: 'Digital ID contact sharing enabled'
                },
                qr_code_data_events: [],
                qr_code_data_work: []
            };

            // Encrypt data with AES-256
            const encryptedData = this.encryptWithAES(JSON.stringify(qrData), keyData.key);

            // Generate QR code
            const qrCodeDataURL = await QRCode.toDataURL(encryptedData);

            return {
                encryptedData,
                qrCodeDataURL,
                keyTimestamp: keyData.timestamp_start
            };
        } catch (error) {
            console.error('Failed to generate encrypted QR code:', error);
            throw error;
        }
    }

    // AES-256 encryption
    encryptWithAES(data, key) {
        const algorithm = 'aes-256-cbc';
        const iv = crypto.randomBytes(16);
        const cipher = crypto.createCipher(algorithm, key);

        let encrypted = cipher.update(data, 'utf8', 'hex');
        encrypted += cipher.final('hex');

        return `U2FsdGVkX1${iv.toString('hex')}${encrypted}`;
    }

    // Decrypt Digital ID data
    decryptDigitalIDData(encryptedData, key) {
        try {
            // Extract IV and encrypted content
            const ivHex = encryptedData.substring(12, 44);
            const encryptedContent = encryptedData.substring(44);

            const iv = Buffer.from(ivHex, 'hex');
            const decipher = crypto.createDecipher('aes-256-cbc', key);

            let decrypted = decipher.update(encryptedContent, 'hex', 'utf8');
            decrypted += decipher.final('utf8');

            return JSON.parse(decrypted);
        } catch (error) {
            console.error('Failed to decrypt Digital ID data:', error);
            throw error;
        }
    }

    // Process scanned QR code
    async processScannedQRCode(qrCodeData) {
        try {
            // Check if it's a Digital ID QR code
            if (qrCodeData.startsWith('U2FsdGVkX1')) {
                const keyData = await this.getPublicKey();
                const decryptedData = this.decryptDigitalIDData(qrCodeData, keyData.key);

                // Add to contacts
                await this.addContactFromDigitalID(decryptedData);

                return {
                    type: 'digital_id',
                    data: decryptedData,
                    success: true
                };
            }

            return {
                type: 'unknown',
                data: null,
                success: false
            };
        } catch (error) {
            console.error('Failed to process scanned QR code:', error);
            throw error;
        }
    }

    // Add contact from Digital ID
    async addContactFromDigitalID(digitalIDData) {
        const contact = {
            username: digitalIDData.qr_code_data_real.username,
            firstName: digitalIDData.qr_code_data_real.first_name,
            lastName: digitalIDData.qr_code_data_real.last_name,
            thirdName: digitalIDData.qr_code_data_real.third_name,
            email: digitalIDData.qr_code_data_contact.main_email,
            phone: digitalIDData.qr_code_data_contact.main_phone,
            hasDigitalID: true,
            isVerified: true,
            digitalIDData: digitalIDData
        };

        // Here you would typically save to your database
        console.log('✅ Contact added from Digital ID:', contact.firstName, contact.lastName);
        return contact;
    }
}

// Usage example
const digitalIDClient = new allgramDigitalIDClient('your-api-key-here');

// Create Digital ID request
const userData = {
    firstName: 'John',
    lastName: 'Doe',
    thirdName: 'Smith',
    gender: 'male',
    placeOfBirth: 'New York',
    nationality: 'US',
    dateOfBirth: '1990-01-01',
    address: '123 Main St, New York, NY',
    photoBase64: 'base64_encoded_photo_data',
    documentNumber: 'US123456789',
    additionalFiles: []
};

// Initialize Digital ID
digitalIDClient.createDigitalIDRequest(userData)
    .then(result => {
        console.log('Digital ID request created:', result);
    })
    .catch(error => {
        console.error('Failed to create Digital ID request:', error);
    });
                                    

Key Features & Benefits

Our Node.js integration provides enterprise-grade Digital ID capabilities with minimal setup. Built on proven technologies like Express.js and crypto, it offers exceptional performance and reliability for production applications.

  • Digital ID Creation: Complete verification request workflow
  • Security First: AES-256 encryption with industry-standard algorithms
  • QR Code Generation: Encrypted QR codes for secure contact sharing
  • Scalability: Designed for high-concurrency applications
View Licensing Options

Swift iOS Integration

Build native iOS Digital ID applications with Swift and SwiftUI. Our iOS SDK provides seamless integration with UIKit and SwiftUI, QR code scanning, and secure Digital ID management. Perfect for creating professional iOS identity verification applications with modern design patterns.

  • Native iOS Support: Full SwiftUI and UIKit compatibility
  • QR Code Scanning: Camera-based QR code detection and processing
  • Secure Digital ID: Military-grade encryption for sensitive identity data
  • Modern Architecture: MVVM, Combine, and async/await support
Explore Digital ID Services

// allgram Digital ID Swift iOS Integration Example
import SwiftUI
import Combine
import CryptoKit
import AVFoundation

// MARK: - Digital ID Models
struct DigitalID: Codable, Identifiable {
    let id: String
    let username: String
    let firstName: String
    let lastName: String
    let thirdName: String
    let realPhoto: String
    let dateOfBirth: String
    let gender: String
    let nationality: String
    let placeOfBirth: String
    let address: String
    let documentNumber: String
    let status: Int
    let createdAt: String
    let approvedAt: String?

    enum CodingKeys: String, CodingKey {
        case id
        case username
        case firstName = "first_name"
        case lastName = "last_name"
        case thirdName = "third_name"
        case realPhoto = "real_photo"
        case dateOfBirth = "date_of_birth"
        case gender
        case nationality
        case placeOfBirth = "place_of_birth"
        case address
        case documentNumber = "document_number"
        case status
        case createdAt = "created_at"
        case approvedAt = "approved_at"
    }
}

struct QRCodeData: Codable {
    let qrCodeDataReal: QRCodeDataReal
    let qrCodeDataContact: QRCodeDataContact
    let qrCodeDataChat: QRCodeDataChat
    let qrCodeDataEvents: [String]
    let qrCodeDataWork: [String]

    enum CodingKeys: String, CodingKey {
        case qrCodeDataReal = "qr_code_data_real"
        case qrCodeDataContact = "qr_code_data_contact"
        case qrCodeDataChat = "qr_code_data_chat"
        case qrCodeDataEvents = "qr_code_data_events"
        case qrCodeDataWork = "qr_code_data_work"
    }
}

struct QRCodeDataReal: Codable {
    let id: String
    let username: String
    let firstName: String
    let lastName: String
    let thirdName: String
    let dateOfBirth: String
    let gender: String
    let nationality: String

    enum CodingKeys: String, CodingKey {
        case id
        case username
        case firstName = "first_name"
        case lastName = "last_name"
        case thirdName = "third_name"
        case dateOfBirth = "date_of_birth"
        case gender
        case nationality
    }
}

struct QRCodeDataContact: Codable {
    let mainEmail: String?
    let mainPhone: String?

    enum CodingKeys: String, CodingKey {
        case mainEmail = "main_email"
        case mainPhone = "main_phone"
    }
}

struct QRCodeDataChat: Codable {
    let isAllowedDirectChats: Bool
    let data: String

    enum CodingKeys: String, CodingKey {
        case isAllowedDirectChats = "is_allowed_direct_chats"
        case data
    }
}

// MARK: - Digital ID Service
class allgramDigitalIDService: ObservableObject {
    @Published var digitalID: DigitalID?
    @Published var isConnected = false
    @Published var isLoading = false

    private var cancellables = Set<AnyCancellable>()
    private let baseURL = "https://api.allgram.best"
    private let apiKey: String

    init(apiKey: String) {
        self.apiKey = apiKey
    }

    // MARK: - Digital ID Management
    func createDigitalIDRequest(userData: [String: Any]) async throws -> DigitalID {
        let url = URL(string: "\(baseURL)/account/v1/did/create/")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        request.httpBody = try JSONSerialization.data(withJSONObject: userData)

        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              httpResponse.statusCode == 200 else {
            throw DigitalIDError.serverError
        }

        let digitalID = try JSONDecoder().decode(DigitalID.self, from: data)

        DispatchQueue.main.async {
            self.digitalID = digitalID
        }

        return digitalID
    }

    func getDigitalIDInfo() async throws -> DigitalID {
        let url = URL(string: "\(baseURL)/account/v1/did/")!
        var request = URLRequest(url: url)
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              httpResponse.statusCode == 200 else {
            throw DigitalIDError.serverError
        }

        let responseData = try JSONDecoder().decode(DigitalIDResponse.self, from: data)
        let digitalID = responseData.data[0]

        DispatchQueue.main.async {
            self.digitalID = digitalID
        }

        return digitalID
    }

    // MARK: - Public Key Management
    func getPublicKey() async throws -> PublicKeyData {
        let url = URL(string: "\(baseURL)/utils/v1/public-key/")!
        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              httpResponse.statusCode == 200 else {
            throw DigitalIDError.serverError
        }

        return try JSONDecoder().decode(PublicKeyData.self, from: data)
    }

    // MARK: - QR Code Generation
    func generateEncryptedQRCode(digitalID: DigitalID) async throws -> String {
        let keyData = try await getPublicKey()

        let qrData = QRCodeData(
            qrCodeDataReal: QRCodeDataReal(
                id: digitalID.id,
                username: digitalID.username,
                firstName: digitalID.firstName,
                lastName: digitalID.lastName,
                thirdName: digitalID.thirdName,
                dateOfBirth: digitalID.dateOfBirth,
                gender: digitalID.gender,
                nationality: digitalID.nationality
            ),
            qrCodeDataContact: QRCodeDataContact(
                mainEmail: nil,
                mainPhone: nil
            ),
            qrCodeDataChat: QRCodeDataChat(
                isAllowedDirectChats: true,
                data: "Digital ID contact sharing enabled"
            ),
            qrCodeDataEvents: [],
            qrCodeDataWork: []
        )

        let jsonData = try JSONEncoder().encode(qrData)
        let jsonString = String(data: jsonData, encoding: .utf8)!

        return encryptWithAES(jsonString, key: keyData.key)
    }

    // MARK: - Encryption
    private func encryptWithAES(_ data: String, key: String) -> String {
        let keyData = key.data(using: .utf8)!
        let dataToEncrypt = data.data(using: .utf8)!

        let key = SymmetricKey(data: keyData)
        let sealedBox = try! AES.GCM.seal(dataToEncrypt, using: key)

        let encryptedData = sealedBox.combined!
        return "U2FsdGVkX1" + encryptedData.base64EncodedString()
    }

    // MARK: - QR Code Scanning
    func processScannedQRCode(_ qrCodeData: String) async throws -> QRCodeData? {
        guard qrCodeData.startsWith("U2FsdGVkX1") else {
            return nil
        }

        let keyData = try await getPublicKey()
        let decryptedData = try decryptWithAES(qrCodeData, key: keyData.key)

        return try JSONDecoder().decode(QRCodeData.self, from: decryptedData)
    }

    private func decryptWithAES(_ encryptedData: String, key: String) throws -> Data {
        let keyData = key.data(using: .utf8)!
        let encryptedData = Data(base64Encoded: String(encryptedData.dropFirst(12)))!

        let key = SymmetricKey(data: keyData)
        let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)

        return try AES.GCM.open(sealedBox, using: key)
    }
}

// MARK: - Response Models
struct DigitalIDResponse: Codable {
    let data: [DigitalID]
}

struct PublicKeyData: Codable {
    let key: String
    let timestampStart: String
    let timestampEnd: String

    enum CodingKeys: String, CodingKey {
        case key
        case timestampStart = "timestamp_start"
        case timestampEnd = "timestamp_end"
    }
}

// MARK: - Error Handling
enum DigitalIDError: Error, LocalizedError {
    case serverError
    case networkError
    case authenticationError
    case encryptionError

    var errorDescription: String? {
        switch self {
        case .serverError:
            return "Server error occurred"
        case .networkError:
            return "Network connection failed"
        case .authenticationError:
            return "Authentication failed"
        case .encryptionError:
            return "Encryption/decryption failed"
        }
    }
}

// MARK: - SwiftUI Views
struct DigitalIDView: View {
    @StateObject private var digitalIDService = allgramDigitalIDService(apiKey: "your-api-key")
    @State private var showingQRScanner = false
    @State private var scannedData: QRCodeData?

    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                if let digitalID = digitalIDService.digitalID {
                    DigitalIDCard(digitalID: digitalID)
                } else {
                    CreateDigitalIDButton(digitalIDService: digitalIDService)
                }

                if let scannedData = scannedData {
                    ScannedDataView(data: scannedData)
                }

                Button("Scan QR Code") {
                    showingQRScanner = true
                }
                .buttonStyle(.borderedProminent)
            }
            .navigationTitle("Digital ID")
            .sheet(isPresented: $showingQRScanner) {
                QRScannerView { qrCode in
                    Task {
                        do {
                            scannedData = try await digitalIDService.processScannedQRCode(qrCode)
                        } catch {
                            print("Failed to process QR code: \(error)")
                        }
                    }
                }
            }
        }
    }
}

struct DigitalIDCard: View {
    let digitalID: DigitalID

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                AsyncImage(url: URL(string: digitalID.realPhoto)) { image in
                    image.resizable()
                } placeholder: {
                    Image(systemName: "person.circle.fill")
                        .foregroundColor(.gray)
                }
                .frame(width: 60, height: 60)
                .clipShape(Circle())

                VStack(alignment: .leading) {
                    Text("\(digitalID.firstName) \(digitalID.lastName)")
                        .font(.title2)
                        .fontWeight(.bold)

                    Text("Verified Identity")
                        .font(.caption)
                        .foregroundColor(.green)
                        .padding(.horizontal, 8)
                        .padding(.vertical, 4)
                        .background(Color.green.opacity(0.2))
                        .cornerRadius(4)
                }
                Spacer()
            }

            Divider()

            VStack(alignment: .leading, spacing: 8) {
                InfoRow(label: "Username", value: digitalID.username)
                InfoRow(label: "Date of Birth", value: digitalID.dateOfBirth)
                InfoRow(label: "Nationality", value: digitalID.nationality)
                InfoRow(label: "Status", value: statusText(digitalID.status))
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(radius: 2)
    }

    private func statusText(_ status: Int) -> String {
        switch status {
        case 0: return "Processing"
        case 1: return "Approved"
        case 2: return "Rejected"
        default: return "Unknown"
        }
    }
}

struct InfoRow: View {
    let label: String
    let value: String

    var body: some View {
        HStack {
            Text(label)
                .foregroundColor(.secondary)
            Spacer()
            Text(value)
                .fontWeight(.medium)
        }
    }
}

struct CreateDigitalIDButton: View {
    let digitalIDService: allgramDigitalIDService

    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "person.badge.plus")
                .font(.system(size: 48))
                .foregroundColor(.blue)

            Text("Create Digital ID")
                .font(.title2)
                .fontWeight(.semibold)

            Text("Verify your identity and get a secure Digital ID for contact sharing")
                .multilineTextAlignment(.center)
                .foregroundColor(.secondary)

            Button("Get Started") {
                // Show Digital ID creation form
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(radius: 2)
    }
}
                                    

iOS Development Features

Our Swift SDK leverages the latest iOS technologies including SwiftUI, Combine, and async/await. Built with modern iOS development patterns, it provides a seamless developer experience while maintaining high performance and security standards.

  • SwiftUI Integration: Native SwiftUI components and data binding
  • Combine Framework: Reactive programming with publishers and subscribers
  • Async/Await: Modern concurrency for better performance
  • Security: CryptoKit integration for encryption operations
View Licensing Options

Kotlin Android Integration

Build powerful Android Digital ID applications with Kotlin and Jetpack Compose. Our Android SDK provides seamless integration with modern Android development tools, QR code scanning, and blockchain-based identity verification. Perfect for creating professional Android Digital ID applications.

  • Jetpack Compose: Modern declarative UI toolkit
  • QR Code Integration: Camera-based scanning and processing
  • Blockchain Security: Secure Digital ID verification and storage
  • Android Architecture: MVVM, Repository pattern, and Coroutines
Explore Digital ID Services

// allgram Digital ID Kotlin Android Integration Example
package com.allgram.digitalid

import android.util.Log
import androidx.compose.runtime.*
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec

// MARK: - Data Models
data class DigitalID(
    val id: String,
    val username: String,
    val firstName: String,
    val lastName: String,
    val thirdName: String,
    val realPhoto: String,
    val dateOfBirth: String,
    val gender: String,
    val nationality: String,
    val placeOfBirth: String,
    val address: String,
    val documentNumber: String,
    val status: Int,
    val createdAt: String,
    val approvedAt: String?
)

data class QRCodeData(
    val qrCodeDataReal: QRCodeDataReal,
    val qrCodeDataContact: QRCodeDataContact,
    val qrCodeDataChat: QRCodeDataChat,
    val qrCodeDataEvents: List<String>,
    val qrCodeDataWork: List<String>
)

data class QRCodeDataReal(
    val id: String,
    val username: String,
    val firstName: String,
    val lastName: String,
    val thirdName: String,
    val dateOfBirth: String,
    val gender: String,
    val nationality: String
)

data class QRCodeDataContact(
    val mainEmail: String?,
    val mainPhone: String?
)

data class QRCodeDataChat(
    val isAllowedDirectChats: Boolean,
    val data: String
)

// MARK: - Digital ID Service
class allgramDigitalIDService(
    private val apiKey: String,
    private val baseUrl: String = "https://api.allgram.best"
) {
    private val client = OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()

    // MARK: - Digital ID Management
    suspend fun createDigitalIDRequest(userData: Map<String, Any>): Result<DigitalID> = withContext(Dispatchers.IO) {
        try {
            val requestBody = JSONObject().apply {
                put("first_name", userData["firstName"])
                put("last_name", userData["lastName"])
                put("third_name", userData["thirdName"])
                put("gender", userData["gender"])
                put("place_of_birth", userData["placeOfBirth"])
                put("nationality", userData["nationality"])
                put("date_of_birth", userData["dateOfBirth"])
                put("address", userData["address"])
                put("real_photo", userData["photoBase64"])
                put("document_number", userData["documentNumber"])
                put("files", JSONObject().apply {
                    put("imgs", JSONArray())
                })
            }.toString()

            val request = Request.Builder()
                .url("$baseUrl/account/v1/did/create/")
                .post(requestBody.toRequestBody("application/json".toMediaType()))
                .addHeader("Authorization", "Bearer $apiKey")
                .build()

            val response = client.newCall(request).execute()

            if (response.isSuccessful) {
                val responseBody = response.body?.string()
                val digitalIDJson = JSONObject(responseBody ?: "")

                val digitalID = DigitalID(
                    id = digitalIDJson.getString("id"),
                    username = digitalIDJson.getString("username"),
                    firstName = digitalIDJson.getString("first_name"),
                    lastName = digitalIDJson.getString("last_name"),
                    thirdName = digitalIDJson.optString("third_name", ""),
                    realPhoto = digitalIDJson.getString("real_photo"),
                    dateOfBirth = digitalIDJson.getString("date_of_birth"),
                    gender = digitalIDJson.getString("gender"),
                    nationality = digitalIDJson.getString("nationality"),
                    placeOfBirth = digitalIDJson.getString("place_of_birth"),
                    address = digitalIDJson.getString("address"),
                    documentNumber = digitalIDJson.getString("document_number"),
                    status = digitalIDJson.getInt("status"),
                    createdAt = digitalIDJson.getString("created_at"),
                    approvedAt = digitalIDJson.optString("approved_at", null)
                )

                Log.d("allgramDigitalID", "✅ Digital ID request created: ${digitalID.firstName} ${digitalID.lastName}")
                Result.success(digitalID)
            } else {
                Log.e("allgramDigitalID", "Failed to create Digital ID: ${response.code}")
                Result.failure(Exception("Server error: ${response.code}"))
            }
        } catch (e: Exception) {
            Log.e("allgramDigitalID", "Exception creating Digital ID", e)
            Result.failure(e)
        }
    }

    suspend fun getDigitalIDInfo(): Result<DigitalID> = withContext(Dispatchers.IO) {
        try {
            val request = Request.Builder()
                .url("$baseUrl/account/v1/did/")
                .addHeader("Authorization", "Bearer $apiKey")
                .build()

            val response = client.newCall(request).execute()

            if (response.isSuccessful) {
                val responseBody = response.body?.string()
                val responseJson = JSONObject(responseBody ?: "")
                val digitalIDArray = responseJson.getJSONArray("data")
                val digitalIDJson = digitalIDArray.getJSONObject(0)

                val digitalID = DigitalID(
                    id = digitalIDJson.getString("id"),
                    username = digitalIDJson.getString("username"),
                    firstName = digitalIDJson.getString("first_name"),
                    lastName = digitalIDJson.getString("last_name"),
                    thirdName = digitalIDJson.optString("third_name", ""),
                    realPhoto = digitalIDJson.getString("real_photo"),
                    dateOfBirth = digitalIDJson.getString("date_of_birth"),
                    gender = digitalIDJson.getString("gender"),
                    nationality = digitalIDJson.getString("nationality"),
                    placeOfBirth = digitalIDJson.getString("place_of_birth"),
                    address = digitalIDJson.getString("address"),
                    documentNumber = digitalIDJson.getString("document_number"),
                    status = digitalIDJson.getInt("status"),
                    createdAt = digitalIDJson.getString("created_at"),
                    approvedAt = digitalIDJson.optString("approved_at", null)
                )

                Result.success(digitalID)
            } else {
                Log.e("allgramDigitalID", "Failed to get Digital ID: ${response.code}")
                Result.failure(Exception("Server error: ${response.code}"))
            }
        } catch (e: Exception) {
            Log.e("allgramDigitalID", "Exception getting Digital ID", e)
            Result.failure(e)
        }
    }

    // MARK: - Public Key Management
    suspend fun getPublicKey(): Result<PublicKeyData> = withContext(Dispatchers.IO) {
        try {
            val request = Request.Builder()
                .url("$baseUrl/utils/v1/public-key/")
                .build()

            val response = client.newCall(request).execute()

            if (response.isSuccessful) {
                val responseBody = response.body?.string()
                val keyJson = JSONObject(responseBody ?: "")

                val publicKeyData = PublicKeyData(
                    key = keyJson.getString("key"),
                    timestampStart = keyJson.getString("timestamp_start"),
                    timestampEnd = keyJson.getString("timestamp_end")
                )

                Result.success(publicKeyData)
            } else {
                Log.e("allgramDigitalID", "Failed to get public key: ${response.code}")
                Result.failure(Exception("Server error: ${response.code}"))
            }
        } catch (e: Exception) {
            Log.e("allgramDigitalID", "Exception getting public key", e)
            Result.failure(e)
        }
    }

    // MARK: - QR Code Generation
    suspend fun generateEncryptedQRCode(digitalID: DigitalID): Result<String> = withContext(Dispatchers.IO) {
        try {
            val keyResult = getPublicKey()
            if (keyResult.isFailure) {
                return Result.failure(keyResult.exceptionOrNull() ?: Exception("Failed to get public key"))
            }

            val keyData = keyResult.getOrNull()!!

            val qrData = QRCodeData(
                qrCodeDataReal = QRCodeDataReal(
                    id = digitalID.id,
                    username = digitalID.username,
                    firstName = digitalID.firstName,
                    lastName = digitalID.lastName,
                    thirdName = digitalID.thirdName,
                    dateOfBirth = digitalID.dateOfBirth,
                    gender = digitalID.gender,
                    nationality = digitalID.nationality
                ),
                qrCodeDataContact = QRCodeDataContact(
                    mainEmail = null,
                    mainPhone = null
                ),
                qrCodeDataChat = QRCodeDataChat(
                    isAllowedDirectChats = true,
                    data = "Digital ID contact sharing enabled"
                ),
                qrCodeDataEvents = emptyList(),
                qrCodeDataWork = emptyList()
            )

            val jsonData = JSONObject().apply {
                put("qr_code_data_real", JSONObject().apply {
                    put("id", qrData.qrCodeDataReal.id)
                    put("username", qrData.qrCodeDataReal.username)
                    put("first_name", qrData.qrCodeDataReal.firstName)
                    put("last_name", qrData.qrCodeDataReal.lastName)
                    put("third_name", qrData.qrCodeDataReal.thirdName)
                    put("date_of_birth", qrData.qrCodeDataReal.dateOfBirth)
                    put("gender", qrData.qrCodeDataReal.gender)
                    put("nationality", qrData.qrCodeDataReal.nationality)
                })
                put("qr_code_data_contact", JSONObject().apply {
                    put("main_email", JSONObject.NULL)
                    put("main_phone", JSONObject.NULL)
                })
                put("qr_code_data_chat", JSONObject().apply {
                    put("is_allowed_direct_chats", qrData.qrCodeDataChat.isAllowedDirectChats)
                    put("data", qrData.qrCodeDataChat.data)
                })
                put("qr_code_data_events", JSONArray())
                put("qr_code_data_work", JSONArray())
            }.toString()

            val encryptedData = encryptWithAES(jsonData, keyData.key)
            Result.success(encryptedData)
        } catch (e: Exception) {
            Log.e("allgramDigitalID", "Exception generating QR code", e)
            Result.failure(e)
        }
    }

    // MARK: - Encryption
    private fun encryptWithAES(data: String, key: String): String {
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        val secretKey = SecretKeySpec(key.toByteArray(), "AES")
        val iv = ByteArray(12).apply {
            java.security.SecureRandom().nextBytes(this)
        }
        val gcmSpec = GCMParameterSpec(128, iv)

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec)
        val encrypted = cipher.doFinal(data.toByteArray())

        val combined = iv + encrypted
        return "U2FsdGVkX1" + android.util.Base64.encodeToString(combined, android.util.Base64.NO_WRAP)
    }

    // MARK: - QR Code Processing
    suspend fun processScannedQRCode(qrCodeData: String): Result<QRCodeData?> = withContext(Dispatchers.IO) {
        try {
            if (!qrCodeData.startsWith("U2FsdGVkX1")) {
                return Result.success(null)
            }

            val keyResult = getPublicKey()
            if (keyResult.isFailure) {
                return Result.failure(keyResult.exceptionOrNull() ?: Exception("Failed to get public key"))
            }

            val keyData = keyResult.getOrNull()!!
            val decryptedData = decryptWithAES(qrCodeData, keyData.key)

            val jsonObject = JSONObject(decryptedData)
            val qrCodeData = parseQRCodeData(jsonObject)

            Result.success(qrCodeData)
        } catch (e: Exception) {
            Log.e("allgramDigitalID", "Exception processing QR code", e)
            Result.failure(e)
        }
    }

    private fun decryptWithAES(encryptedData: String, key: String): String {
        val encryptedBytes = android.util.Base64.decode(encryptedData.substring(12), android.util.Base64.NO_WRAP)
        val iv = encryptedBytes.sliceArray(0..11)
        val encrypted = encryptedBytes.sliceArray(12 until encryptedBytes.size)

        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        val secretKey = SecretKeySpec(key.toByteArray(), "AES")
        val gcmSpec = GCMParameterSpec(128, iv)

        cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec)
        val decrypted = cipher.doFinal(encrypted)

        return String(decrypted)
    }

    private fun parseQRCodeData(json: JSONObject): QRCodeData {
        val realData = json.getJSONObject("qr_code_data_real")
        val contactData = json.getJSONObject("qr_code_data_contact")
        val chatData = json.getJSONObject("qr_code_data_chat")
        val eventsArray = json.getJSONArray("qr_code_data_events")
        val workArray = json.getJSONArray("qr_code_data_work")

        return QRCodeData(
            qrCodeDataReal = QRCodeDataReal(
                id = realData.getString("id"),
                username = realData.getString("username"),
                firstName = realData.getString("first_name"),
                lastName = realData.getString("last_name"),
                thirdName = realData.optString("third_name", ""),
                dateOfBirth = realData.getString("date_of_birth"),
                gender = realData.getString("gender"),
                nationality = realData.getString("nationality")
            ),
            qrCodeDataContact = QRCodeDataContact(
                mainEmail = contactData.optString("main_email", null),
                mainPhone = contactData.optString("main_phone", null)
            ),
            qrCodeDataChat = QRCodeDataChat(
                isAllowedDirectChats = chatData.getBoolean("is_allowed_direct_chats"),
                data = chatData.getString("data")
            ),
            qrCodeDataEvents = List(eventsArray.length()) { i -> eventsArray.getString(i) },
            qrCodeDataWork = List(workArray.length()) { i -> workArray.getString(i) }
        )
    }
}

// MARK: - Response Models
data class PublicKeyData(
    val key: String,
    val timestampStart: String,
    val timestampEnd: String
)

// MARK: - ViewModel
class DigitalIDViewModel(
    private val digitalIDService: allgramDigitalIDService
) : ViewModel() {

    private val _digitalID = MutableStateFlow<DigitalID?>(null)
    val digitalID: StateFlow<DigitalID?> = _digitalID.asStateFlow()

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()

    private val _scannedData = MutableStateFlow<QRCodeData?>(null)
    val scannedData: StateFlow<QRCodeData?> = _scannedData.asStateFlow()

    init {
        loadDigitalID()
    }

    private fun loadDigitalID() {
        viewModelScope.launch {
            _isLoading.value = true
            try {
                val result = digitalIDService.getDigitalIDInfo()
                result.onSuccess { digitalID ->
                    _digitalID.value = digitalID
                }.onFailure { error ->
                    Log.e("DigitalIDViewModel", "Failed to load Digital ID", error)
                }
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun createDigitalIDRequest(userData: Map<String, Any>) {
        viewModelScope.launch {
            _isLoading.value = true
            try {
                val result = digitalIDService.createDigitalIDRequest(userData)
                result.onSuccess { digitalID ->
                    _digitalID.value = digitalID
                }.onFailure { error ->
                    Log.e("DigitalIDViewModel", "Failed to create Digital ID", error)
                }
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun processScannedQRCode(qrCodeData: String) {
        viewModelScope.launch {
            try {
                val result = digitalIDService.processScannedQRCode(qrCodeData)
                result.onSuccess { data ->
                    _scannedData.value = data
                }.onFailure { error ->
                    Log.e("DigitalIDViewModel", "Failed to process QR code", error)
                }
            } catch (e: Exception) {
                Log.e("DigitalIDViewModel", "Exception processing QR code", e)
            }
        }
    }
}

// MARK: - Compose UI
@Composable
fun DigitalIDScreen(
    viewModel: DigitalIDViewModel = viewModel { DigitalIDViewModel(allgramDigitalIDService("your-api-key")) }
) {
    val digitalID by viewModel.digitalID.collectAsState()
    val isLoading by viewModel.isLoading.collectAsState()
    val scannedData by viewModel.scannedData.collectAsState()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        if (isLoading) {
            CircularProgressIndicator(
                modifier = Modifier.align(Alignment.CenterHorizontally)
            )
        } else if (digitalID != null) {
            DigitalIDCard(digitalID = digitalID!!)
        } else {
            CreateDigitalIDButton(
                onCreateRequest = { userData ->
                    viewModel.createDigitalIDRequest(userData)
                }
            )
        }

        if (scannedData != null) {
            ScannedDataCard(data = scannedData!!)
        }

        Button(
            onClick = { /* Launch QR scanner */ },
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 16.dp)
        ) {
            Icon(
                imageVector = Icons.Default.QrCodeScanner,
                contentDescription = "Scan QR Code"
            )
            Spacer(modifier = Modifier.width(8.dp))
            Text("Scan QR Code")
        }
    }
}

@Composable
fun DigitalIDCard(digitalID: DigitalID) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
    ) {
        Column(
            modifier = Modifier.padding(16.dp)
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                verticalAlignment = Alignment.CenterVertically
            ) {
                AsyncImage(
                    model = digitalID.realPhoto,
                    contentDescription = "Profile Photo",
                    modifier = Modifier
                        .size(60.dp)
                        .clip(CircleShape)
                )

                Spacer(modifier = Modifier.width(16.dp))

                Column {
                    Text(
                        text = "${digitalID.firstName} ${digitalID.lastName}",
                        style = MaterialTheme.typography.h6
                    )
                    Text(
                        text = "Verified Identity",
                        style = MaterialTheme.typography.caption,
                        color = Color.Green
                    )
                }
            }

            Spacer(modifier = Modifier.height(16.dp))

            InfoRow(label = "Username", value = digitalID.username)
            InfoRow(label = "Date of Birth", value = digitalID.dateOfBirth)
            InfoRow(label = "Nationality", value = digitalID.nationality)
            InfoRow(label = "Status", value = getStatusText(digitalID.status))
        }
    }
}

@Composable
fun InfoRow(label: String, value: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 4.dp),
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(
            text = label,
            style = MaterialTheme.typography.body2,
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
        )
        Text(
            text = value,
            style = MaterialTheme.typography.body2,
            fontWeight = FontWeight.Medium
        )
    }
}

private fun getStatusText(status: Int): String {
    return when (status) {
        0 -> "Processing"
        1 -> "Approved"
        2 -> "Rejected"
        else -> "Unknown"
    }
}
                                    

Android Development Features

Our Kotlin SDK leverages the latest Android technologies including Jetpack Compose, Coroutines, and modern Android architecture patterns. Built with performance and developer experience in mind, it provides a robust foundation for building scalable Digital ID applications.

  • Jetpack Compose: Modern declarative UI with Material Design 3
  • Coroutines: Asynchronous programming with structured concurrency
  • MVVM Architecture: Clean architecture with Repository pattern
  • Security: Built-in encryption and secure communication
View Licensing Options

Additional Resources & Next Steps

Ready to take your Digital ID integration to the next level? Explore our comprehensive resources and advanced features to build enterprise-grade identity verification applications with allgram.

Security & Compliance

Learn about our enterprise security features, GDPR compliance, and blockchain-based verification.

Learn More →

Performance Optimization

Discover advanced techniques for optimizing Digital ID performance and scalability.

Learn More →

API Reference

Complete API documentation with examples, error codes, and best practices.

View Docs →

Community Support

Join our developer community for support, updates, and collaboration.

Join Community →