RiseTech UnifyID API Documentation

Build secure identity verification into your applications with RiseTech Digital UnifyID's

Introduction

Integrate secure, decentralized identity verification into your applications with the RiseTech UnifyID API. Our enterprise-grade platform is built on Microsoft Entra Verified ID, allowing you to create seamless and trustworthy user experiences.

What can you do with this API?

Request User Verification

Initiate requests for users to present their digital verified credentials for seamless authentication, choosing between standard or face-check levels of security.

Validate Credentials

Securely receive and validate the authenticity of presented credentials in real-time, whether through a simple SAML assertion or a direct API response.

Issue Custom Credentials

Design and issue your own branded, verifiable credentials to users, with full control over the claims, branding, and optional KYC verification.

Getting Started

Your Quick Path to Integration:
  1. Authentication: First, learn how to get your API keys and authenticate requests.
  2. Integration Flows: Next, review the Integration Flows to choose the pattern that best fits your app.
  3. API Reference: Finally, explore the API Reference for detailed endpoint information.

Integration Flows

1. Credential Issuance Flow

Generate Access Token

The set up and verification of the use of the service

Authorization
OPTIONAL

KYC Scan

The generation of the URL or QR Code for user to perform the Document and Biometric checks

This step is optional. Skip if KYC is not required.
Generation

Create User

Create user with its personal details. The user will have a relation to its customer

Generation

Card Type

Get the list of supported Digital ID Cards and choose which card to issue

Generation

Issue Digital ID Card

1. Input user details
2. Specify the ID Card type
3. Issue the Digital ID Card
4. Send verification code using SendEmail endpoint

Generation

Receiving Results Upon Completion

Upon completion of the workflow, the server automatically sends the processed results

Results
Important Notes:
  • A customer must be created first before you can issue credentials to users
  • The KYC verification step is optional and can be skipped based on your requirements
  • All other steps are mandatory for credential issuance

2. SAML 2.0 SSO Authentication Flow

User Browser
Service Provider (SP)
RiseTech IdP (UnifyID)
1 User accesses protected resource
2 Create SAML AuthnRequest
3 Browser redirected to IdP
Receive & decode SAML Request
4 Display QR Code page
5 QR code displayed / User scans
6 Generate QR Code for UnifyID
7 Browser polls for status
8 User scans with Authenticator
Verifies credential
9 Auto-submit form to SP ACS
10 Validate SAML
Create SP session
Generate SAML Response/Assertion
User Successfully Logged In

3. Presentation Flow (Direct API Verification)

Generate Access Token
Setup and verification of service use
Verification Request
Generate URL or QR code for user to identify/verify
Verification Done
Retrieve Results - server automatically sends processed results
User Successfully Logged In
User authenticated and granted access to the system
Process Stages: Authorization → Generation → Results → Success

Authentication

All API calls require authentication using OAuth 2.0 client credentials flow.

POST
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token

Generate an access token for API authentication

curl -X POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id={your_client_id}" \
  -d "client_secret={your_client_secret}" \
  -d "scope={your_scope}/.default" \
  -d "grant_type=client_credentials"
{
  "token_type": "Bearer",
  "expires_in": 3599,
  "ext_expires_in": 3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."
}
Required Headers for API Calls:
Authorization: Bearer {access_token}
Ocp-Apim-Subscription-Key: {subscription_key}

SAML 2.0 Integration

Configure your application as a Service Provider (SP) to use UnifyID as a SAML Identity Provider (IdP). This is the simplest and most robust method for federated login.

Why Choose SAML? Your application only needs to "speak SAML" - we handle the entire UnifyID verification process internally. Perfect for third-party applications like Salesforce, Zendesk, or any SAML-compatible service.

Step 1: Configure Trust (Metadata Exchange)

1. Get Our IdP Metadata

GET
/api/saml/idp/metadata

Returns SAML 2.0 metadata XML containing:

  • IdP Entity ID
  • SSO endpoint URLs
  • Public signing certificate

2. Provide Your SP Metadata

Send us your metadata including:

  • Signing Certificate (Recommended) - For request validation
  • Decryption Certificate (Required) - For secure assertions
  • Assertion Consumer Service URLs
  • SP Entity ID

Step 2: Dynamic Authentication Levels

GET POST
/api/saml/idp/sso

SAML SSO endpoint - accepts AuthnRequest via redirect or POST binding

Parameter Type Description
SAMLRequest String Base64-encoded, deflated SAML AuthnRequest
RelayState String Optional state to maintain between SP and IdP

Authentication Context Classes

Level Context URI Use Case
Standard https://risetech.id/saml/contexts/unifyid-standard Regular authentication - UnifyID verification via mobile app
Face Check https://risetech.id/saml/contexts/unifyid-facecheck High-security operations - UnifyID verification with biometric face check
Legacy Context Support: For backward compatibility, we also support:
  • urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport → maps to standard authentication
  • urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken → maps to face check authentication
However, we strongly recommend using our custom contexts for clarity and future compatibility.

Example SAML AuthnRequest

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                    ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6"
                    Version="2.0"
                    IssueInstant="2024-01-20T11:00:00Z"
                    AssertionConsumerServiceURL="https://yourapp.com/saml/acs">
    <saml:Issuer>https://yourapp.com</saml:Issuer>
    <samlp:RequestedAuthnContext Comparison="exact">
        <saml:AuthnContextClassRef>
            https://risetech.id/saml/contexts/unifyid-standard
        </saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                    ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6"
                    Version="2.0"
                    IssueInstant="2024-01-20T11:00:00Z"
                    AssertionConsumerServiceURL="https://yourapp.com/saml/acs">
    <saml:Issuer>https://yourapp.com</saml:Issuer>
    <samlp:RequestedAuthnContext Comparison="exact">
        <saml:AuthnContextClassRef>
            https://risetech.id/saml/contexts/unifyid-facecheck
        </saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

Dynamic Authentication Use Cases

E-commerce Platform

// Regular browsing - standard auth
const authLevel = 'https://risetech.id/saml/contexts/unifyid-standard';

// Checkout or account changes - require face check
if (isCheckout || isAccountChange) {
    authLevel = 'https://risetech.id/saml/contexts/unifyid-facecheck';
}

Banking Application

// View balance - standard auth
// Transfer funds - face check required
const authLevel = transferAmount > 1000
    ? 'https://risetech.id/saml/contexts/unifyid-facecheck'
    : 'https://risetech.id/saml/contexts/unifyid-standard';

Healthcare Portal

// Viewing appointments - standard auth
// Accessing medical records - face check required
const authLevel = accessType === 'medical-records'
    ? 'https://risetech.id/saml/contexts/unifyid-facecheck'
    : 'https://risetech.id/saml/contexts/unifyid-standard';

Step 3: Handle the SAML Assertion (ACS)

After successful authentication, we redirect the user's browser back to your Assertion Consumer Service (ACS) URL via HTTP POST with the SAMLResponse.

Verifying Authentication Level

Your SP should verify that the authentication context in the response meets your security requirements:

<saml:AuthnStatement AuthnInstant="2024-01-20T11:05:00Z">
    <saml:AuthnContext>
        <saml:AuthnContextClassRef>
            https://risetech.id/saml/contexts/unifyid-facecheck
        </saml:AuthnContextClassRef>
    </saml:AuthnContext>
</saml:AuthnStatement>
SAML Response includes:
  • User claims (given_name, family_name, email, etc.)
  • The actual authentication context used (matching what was requested)
  • Session information for Single Logout support

Direct API Integration

For applications that cannot use SAML or require a deeply integrated, custom user interface, this pattern allows you to directly manage the QR code display and verification flow.

Choose Direct API if: You need embedded verification, your app doesn't support SAML, you want full UI control, or you're building mobile apps.
POST
/api/verification/verification-request

Initiate a verification request and receive a QR code

{
  "UserGUID": "BD275F05-A037-4B3E-93DC-008E5B13F3C8",
  "CustomerGUID": "BF5F8407-DBEB-45DC-8E51-B0B784D8042C",
  "faceCheck": false, // Optional: require face verification
  "isMobile": false,
  "purpose": "Log in to the Acme Inc. portal.",
  "cardTypeGuid": "3E524D30-F5F2-47F4-980E-96EE3A0A9201"
  }
}
{
  "expiry": 1754063400,                              
  "qrCode": "data:image/png;base64,...",
  "id": "09aeb332-04e2-451b-9962-30703c37fb10",
  "statusUpdateUrl": "https://{url}/api/status/request-status-stream?id={id}"
}
GET
/api/callback/request-status?id={requestId}

Poll for verification status (every 3 seconds)

{
    "status": "request_created",
    "message": "Waiting to scan QR code"
}
GET
/api/status/request-status-stream?id={requestId}

Monitor verification status using Server-Sent Events (SSE) - Alternative to polling

SSE Events: request_created → request_retrieved → presentation_verified

Implementation Example

Complete Polling Implementation

async function initiateVerification() {
    // Step 1: Create verification request
    const response = await fetch('/api/verification/verification-request', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Ocp-Apim-Subscription-Key': subscriptionKey,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            UserGUID: userGuid,
            CustomerGUID: customerGuid,
            faceCheck: requireFaceCheck,
            isMobile: false,
            purpose: "Login to corporate portal",
            cardTypeGuid: cardTypeGuid
        })
    });
    
    const { qrCode, id } = await response.json();
    
    // Step 2: Display QR Code
    displayQRCode(qrCode);
    
    // Step 3: Start polling for status
    pollVerificationStatus(id);
}

async function pollVerificationStatus(id) {
    const maxAttempts = 200; // 10 minutes (3 sec intervals)
    let attempts = 0;
    
    while (attempts < maxAttempts) {
        try {
            const response = await fetch(`/api/callback/request-status?id=${id}`, {
                headers: {
                    'Ocp-Apim-Subscription-Key': subscriptionKey
                }
            });
            
            const data = await response.json();
            
            if (data.status === 'presentation_verified') {
                // Success! Process verified user
                console.log('User verified:', data.data);
                handleVerifiedUser(data.data);
                return;
            } else if (data.status === 'presentation_error') {
                // Handle error
                console.error('Verification error:', data.message);
                handleError(data.message);
                return;
            }
            
            // Update UI with current status
            updateStatus(data.status);
            
            // Wait 3 seconds before next poll
            await new Promise(resolve => setTimeout(resolve, 3000));
            attempts++;
            
        } catch (error) {
            console.error('Polling error:', error);
            handleError('Network error');
            return;
        }
    }
    
    handleTimeout();
}

Customer Management

POST
/api/customers/createcustomer

Create a new customer organization

GET
/api/customers/getcustomer?customerGuid={guid}

Retrieve customer details by GUID

PUT
/api/customers/updatecustomer?customerGuid={guid}

Update existing customer information

User Management

POST
/api/users/createuser

Create a new user under a customer account

GET
/api/users/getuser?userGuid={guid}

Retrieve user details by GUID

PUT
/api/users/updateuser?userGuid={guid}

Update existing user information

Credentials & Cards

GET
/api/cardtypes/getactivecards

Get all active card types available for issuance

POST
/api/customcredentials/createcustomcredential?customerGuid={guid}

Create a custom credential type with branding and claims

GET
/api/customcredentials/getallcustomcredentials?customerGuid={guid}

Retrieve all custom credentials for a customer

GET
/api/credentials/getusercredentials?userGuid={guid}

Get all credentials issued to a specific user

POST
/api/credentials/revokecredential

Revoke an issued credential

KYC & Issuance Flow

GET
/api/credentials/getidscanqrcode

Generate QR code for ID document scanning

GET
/api/selfies/selfie-request

Initiate selfie capture for face verification

GET
/api/selfies/getselfie?id={selfieId}

Retrieve captured selfie image

POST
/api/credentials/issuance-request

Issue a verifiable credential to a user

{
  "UserGUID": "BD275F05-A037-4B3E-93DC-008E5B13F3C8",
  "CustomerGUID": "BF5F8407-DBEB-45DC-8E51-B0B784D8042C",
  "Claims": {
    "given_name": "John",
    "family_name": "Smith",
    "mail": "john.smith@example.com",
    "customerID": "BF5F8407-DBEB-45DC-8E51-B0B784D8042C",
    "userID": "BD275F05-A037-4B3E-93DC-008E5B13F3C8"
  },
  "IsMobile": false,
  "cardTypeGuid": "3E524D30-F5F2-47F4-980E-96EE3A0A9201",
  "purpose": "Employee credential issuance",
  "customExpirationDate": "2025-12-31",
  "photoBase64": "..."
}
POST
/api/credentials/sendemail

Send verification code via email

Best Practices

For SAML Integration

  • Always validate SAML response signatures and assertions
  • Verify authentication context matches your requirements
  • Use HTTPS for all endpoints
  • Implement proper session management after authentication
  • Store IdP metadata locally and update periodically

For Direct API Integration

  • Secure API credentials and rotate them regularly
  • Implement proper error handling for polling mechanism
  • Set reasonable timeouts (recommend 10 minutes)
  • Cache QR codes appropriately to avoid unnecessary API calls
  • Use SSE for real-time updates when possible

Dynamic Authentication Guidelines

When to Use Each Authentication Level

Authentication Level Use Cases Examples
Standard Normal operations • Regular login
• Viewing non-sensitive data
• General application access
Face Check High-security operations • High-value transactions (>$1000)
• Sensitive data access (medical records, financial data)
• Administrative functions
• Account changes (password, email, phone)
• Approval workflows
Important: Document your authentication requirements clearly for users. Consider user experience - don't overuse face check for routine tasks.

Security Best Practices

DO
  • Use environment variables for credentials
  • Implement comprehensive error handling
  • Validate all SAML responses
  • Use HTTPS for all endpoints
  • Rotate API keys quarterly
  • Set reasonable timeouts
  • Log authentication events
  • Monitor for suspicious activity
DON'T
  • Store credentials in source code
  • Log sensitive data or tokens
  • Ignore certificate validation
  • Share API keys via email/chat
  • Use production keys in dev/test
  • Skip error handling
  • Cache credentials client-side
  • Expose internal error messages

Performance Optimization

API Performance

  • Cache access tokens (respect expiry)
  • Reuse HTTP connections
  • Implement exponential backoff for retries
  • Use SSE instead of polling when possible

Timeout Recommendations

  • QR Code display: 10 minutes max
  • Polling interval: 3 seconds
  • HTTP request timeout: 30 seconds
  • Total session timeout: 30 minutes

Error Recovery

  • Implement retry logic with backoff
  • Provide clear user feedback
  • Offer alternative authentication methods
  • Log errors for debugging

SDKs & Libraries

Coming Soon

We're working on native SDKs to make integration even easier

JavaScript/TypeScript

NPM package with full TypeScript support

In Development

Python

PyPI package for Python applications

In Development

.NET/C#

NuGet package for .NET applications

In Development

Java

Maven package for Java applications

Planned

PHP

Composer package for PHP applications

Planned

Ruby

Ruby gem for Rails and Ruby apps

Planned

RiseTech Wallet

Coming Soon

A comprehensive digital wallet solution for managing your digital identity

Digital ID Cards Storage

Securely store and manage all your digital identity cards in one place

NFC Support

Tap to share your credentials using Near Field Communication technology

KYC Verification

Complete identity verification directly within the wallet application

Digital Certificates

Store and present professional certifications and achievements

Secure & Private

End-to-end encryption with biometric authentication for maximum security

Multi-Platform

Available on iOS, Android, and as a web application

Stay Updated: The RiseTech Wallet is currently under development. Follow our updates to be notified when it launches.

Support

Email Support

Get in Touch

Response within 24 hours

Documentation

docs.risetech.id

Always up-to-date

Telegram

Join our channel

Real-time support

Microsoft Teams

Join our team

Collaborative support