Avatars

FaceSign uses AI-powered avatars to create natural, conversational verification experiences. These virtual assistants guide users through the verification process with human-like interactions, making the experience more engaging and less intimidating than traditional forms.

How avatars work

FaceSign avatars are AI-powered virtual assistants that:

  • Guide users through each step of the verification process
  • Adapt their conversation based on the verification modules you've configured
  • Speak multiple languages and adjust their communication style accordingly
  • Provide real-time feedback and help users complete verification successfully
  • Detect emotions and engagement to provide a more personalized experience

Avatar object

  • Name
    id
    Type
    string
    Description

    Unique identifier for the avatar.

  • Name
    name
    Type
    string
    Description

    Human-readable name of the avatar.

  • Name
    gender
    Type
    string
    Description

    Avatar gender: male, female, or unknown.

  • Name
    imageUrl
    Type
    string
    Description

    URL to the avatar's profile image for display in your interface.


GET/avatars

Get available avatars

Returns a list of all available AI avatars that can be used in verification sessions. Choose an avatar that best fits your brand and target audience.

Request

GET
/avatars
curl https://api.facesign.ai/avatars \
  -H "Authorization: Bearer fs_live_..."

Response

{
  "avatars": [
    {
      "id": "avatar_sarah_professional",
      "name": "Sarah",
      "gender": "female",
      "imageUrl": "https://cdn.facesign.ai/avatars/sarah_professional.jpg"
    },
    {
      "id": "avatar_james_friendly",
      "name": "James",
      "gender": "male", 
      "imageUrl": "https://cdn.facesign.ai/avatars/james_friendly.jpg"
    },
    {
      "id": "avatar_maria_bilingual",
      "name": "Maria",
      "gender": "female",
      "imageUrl": "https://cdn.facesign.ai/avatars/maria_bilingual.jpg"
    },
    {
      "id": "avatar_alex_neutral",
      "name": "Alex",
      "gender": "unknown",
      "imageUrl": "https://cdn.facesign.ai/avatars/alex_neutral.jpg"
    }
  ]
}

Choosing the right avatar

Consider your audience

Different avatars work better for different use cases and audiences:

Avatar selection by use case

const AVATAR_RECOMMENDATIONS = {
  financial_services: {
    avatarId: 'avatar_sarah_professional',
    description: 'Professional, trustworthy appearance for banking and financial apps'
  },
  healthcare: {
    avatarId: 'avatar_james_caring',
    description: 'Warm, empathetic avatar for medical verification'
  },
  gaming: {
    avatarId: 'avatar_alex_casual',
    description: 'Casual, friendly avatar for gaming platforms'
  },
  enterprise: {
    avatarId: 'avatar_david_corporate',
    description: 'Business-appropriate avatar for B2B applications'
  },
  international: {
    avatarId: 'avatar_maria_bilingual',
    description: 'Multicultural avatar for global applications'
  }
};

function selectAvatarForUseCase(useCase: string) {
  return AVATAR_RECOMMENDATIONS[useCase] || AVATAR_RECOMMENDATIONS.enterprise;
}

Dynamic avatar selection

You can dynamically select avatars based on user preferences or demographics:

Dynamic avatar selection

async function selectPersonalizedAvatar(userId: string) {
  // Get available avatars
  const { avatars } = await client.avatars.list();
  
  // Get user preferences
  const user = await db.users.findUnique({ where: { id: userId } });
  
  // Filter avatars based on user preferences
  let preferredAvatars = avatars;
  
  if (user.preferredAvatarGender) {
    preferredAvatars = avatars.filter(avatar => 
      avatar.gender === user.preferredAvatarGender || avatar.gender === 'unknown'
    );
  }
  
  // Default to first available avatar if no preferences match
  return preferredAvatars[0] || avatars[0];
}

async function createPersonalizedSession(userId: string) {
  const selectedAvatar = await selectPersonalizedAvatar(userId);
  
  const { session, clientSecret } = await client.sessions.create({
    clientReferenceId: userId,
    avatarId: selectedAvatar.id,
    modules: [{ type: 'identityVerification' }]
  });
  
  return { session, clientSecret };
}

Avatar customization

Custom phrases

Customize how your avatar greets and concludes the verification:

Custom avatar phrases

const { session, clientSecret } = await client.sessions.create({
  clientReferenceId: 'user_123',
  avatarId: 'avatar_sarah_professional',
  initialPhrase: `Hi there! I'm Sarah, and I'll be helping you verify your identity today. This process should only take a few minutes.`,
  finalPhrase: `Perfect! Your verification is complete. Thank you for taking the time to secure your account.`,
  modules: [{ type: 'identityVerification' }]
});

Brand-specific customization

Adapt the avatar's messaging to match your brand:

Brand-specific avatar setup

const BRAND_AVATAR_CONFIG = {
  banking: {
    initialPhrase: "Welcome to SecureBank! I'm here to help verify your identity securely and efficiently.",
    finalPhrase: "Your identity verification is complete. Your account security is our top priority.",
    tone: 'professional'
  },
  healthcare: {
    initialPhrase: "Hello! I'm here to help verify your identity for your healthcare account. Your privacy is completely protected.",
    finalPhrase: "Thank you for completing your verification. Your health information remains secure.",
    tone: 'caring'
  },
  ecommerce: {
    initialPhrase: "Hi! Let's quickly verify your identity so you can start shopping with confidence.",
    finalPhrase: "All set! You're now verified and ready to explore our latest products.",
    tone: 'friendly'
  }
};

function createBrandedSession(userId: string, brand: string) {
  const config = BRAND_AVATAR_CONFIG[brand] || BRAND_AVATAR_CONFIG.banking;
  
  return client.sessions.create({
    clientReferenceId: userId,
    avatarId: getAvatarForBrand(brand),
    initialPhrase: config.initialPhrase,
    finalPhrase: config.finalPhrase,
    modules: [{ type: 'identityVerification' }]
  });
}

Avatar selection UI

Let users choose their avatar

Provide an avatar selection interface before starting verification:

Avatar selection component

import React, { useState, useEffect } from 'react';

interface Avatar {
  id: string;
  name: string;
  gender: string;
  imageUrl: string;
}

function AvatarSelector({ onAvatarSelect }: { onAvatarSelect: (avatar: Avatar) => void }) {
  const [avatars, setAvatars] = useState<Avatar[]>([]);
  const [selectedAvatar, setSelectedAvatar] = useState<Avatar | null>(null);
  
  useEffect(() => {
    // Fetch available avatars
    fetch('/api/avatars')
      .then(res => res.json())
      .then(data => {
        setAvatars(data.avatars);
        setSelectedAvatar(data.avatars[0]); // Default to first avatar
      });
  }, []);
  
  const handleAvatarSelect = (avatar: Avatar) => {
    setSelectedAvatar(avatar);
    onAvatarSelect(avatar);
  };
  
  return (
    <div className="avatar-selector">
      <h3>Choose your verification assistant:</h3>
      <div className="avatar-grid">
        {avatars.map(avatar => (
          <div 
            key={avatar.id}
            className={`avatar-card ${selectedAvatar?.id === avatar.id ? 'selected' : ''}`}
            onClick={() => handleAvatarSelect(avatar)}
          >
            <img 
              src={avatar.imageUrl} 
              alt={avatar.name}
              className="avatar-image"
            />
            <div className="avatar-info">
              <h4>{avatar.name}</h4>
              <p className="avatar-description">
                {getAvatarDescription(avatar)}
              </p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function getAvatarDescription(avatar: Avatar): string {
  const descriptions = {
    'avatar_sarah_professional': 'Professional and trustworthy',
    'avatar_james_friendly': 'Warm and approachable',
    'avatar_maria_bilingual': 'Great for international users',
    'avatar_alex_neutral': 'Friendly and inclusive'
  };
  
  return descriptions[avatar.id] || 'Helpful verification assistant';
}

function VerificationSetup() {
  const [selectedAvatar, setSelectedAvatar] = useState<Avatar | null>(null);
  
  const startVerification = async () => {
    if (!selectedAvatar) return;
    
    const response = await fetch('/api/create-session', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        avatarId: selectedAvatar.id
      })
    });
    
    const { clientSecret } = await response.json();
    
    // Start verification with selected avatar
    const facesign = new FaceSign({ clientSecret });
    await facesign.mount('#verification-container');
  };
  
  return (
    <div>
      <AvatarSelector onAvatarSelect={setSelectedAvatar} />
      <button 
        onClick={startVerification}
        disabled={!selectedAvatar}
        className="start-verification-btn"
      >
        Start Verification with {selectedAvatar?.name}
      </button>
      <div id="verification-container"></div>
    </div>
  );
}

Preview avatar interactions

Show users what to expect from their chosen avatar:

Avatar preview component

function AvatarPreview({ avatar }: { avatar: Avatar }) {
  return (
    <div className="avatar-preview">
      <div className="avatar-preview-header">
        <img src={avatar.imageUrl} alt={avatar.name} />
        <h4>Meet {avatar.name}</h4>
      </div>
      
      <div className="preview-conversation">
        <div className="avatar-message">
          <p>Hi! I'm {avatar.name}. I'll guide you through the verification process step by step.</p>
        </div>
        <div className="avatar-message">
          <p>Don't worry - I'll make sure everything goes smoothly and answer any questions you have.</p>
        </div>
        <div className="user-message">
          <p>Sounds good! Let's get started.</p>
        </div>
        <div className="avatar-message">
          <p>Perfect! Let's begin with verifying your identity...</p>
        </div>
      </div>
      
      <div className="preview-features">
        <h5>What {avatar.name} can help with:</h5>
        <ul>
          <li>Guide you through document scanning</li>
          <li>Help with facial recognition</li>
          <li>Answer questions about the process</li>
          <li>Provide encouragement and support</li>
        </ul>
      </div>
    </div>
  );
}

Best practices

1. Match avatar to brand personality

Choose avatars that align with your brand's personality and values:

Brand-avatar alignment

const BRAND_AVATAR_MAPPING = {
  // Professional, trustworthy brands
  financial: ['avatar_sarah_professional', 'avatar_david_corporate'],
  
  // Friendly, approachable brands
  consumer: ['avatar_james_friendly', 'avatar_emma_casual'],
  
  // Healthcare and sensitive applications
  healthcare: ['avatar_dr_williams_caring', 'avatar_nurse_compassionate'],
  
  // International or diverse audiences
  global: ['avatar_maria_bilingual', 'avatar_alex_neutral', 'avatar_sam_international']
};

function getRecommendedAvatars(brandCategory: string): string[] {
  return BRAND_AVATAR_MAPPING[brandCategory] || BRAND_AVATAR_MAPPING.consumer;
}

2. Consider cultural sensitivity

Be mindful of cultural preferences when selecting avatars for different markets:

Cultural avatar considerations

const REGIONAL_AVATAR_PREFERENCES = {
  'north-america': {
    preferred: ['avatar_sarah_professional', 'avatar_james_friendly'],
    culturalNote: 'Professional but approachable avatars work well'
  },
  'europe': {
    preferred: ['avatar_emma_european', 'avatar_alex_neutral'],
    culturalNote: 'Neutral, inclusive avatars for diverse populations'
  },
  'asia-pacific': {
    preferred: ['avatar_yuki_respectful', 'avatar_sam_international'],
    culturalNote: 'Respectful, formal communication style preferred'
  },
  'latin-america': {
    preferred: ['avatar_maria_bilingual', 'avatar_carlos_warm'],
    culturalNote: 'Warm, personal interaction style resonates well'
  }
};

function selectCulturallyAppropriateAvatar(region: string, availableAvatars: Avatar[]) {
  const preferences = REGIONAL_AVATAR_PREFERENCES[region];
  
  if (preferences) {
    // Find the first preferred avatar that's available
    for (const preferredId of preferences.preferred) {
      const avatar = availableAvatars.find(a => a.id === preferredId);
      if (avatar) return avatar;
    }
  }
  
  // Fallback to neutral avatar
  return availableAvatars.find(a => a.gender === 'unknown') || availableAvatars[0];
}

3. Test avatar effectiveness

Monitor how different avatars perform with your users:

Avatar performance tracking

interface AvatarMetrics {
  avatarId: string;
  completionRate: number;
  userSatisfaction: number;
  averageSessionTime: number;
  retryRate: number;
}

async function trackAvatarPerformance(sessionId: string, avatarId: string, outcome: 'completed' | 'cancelled') {
  await analytics.track('avatar_session_outcome', {
    sessionId,
    avatarId,
    outcome,
    timestamp: new Date()
  });
}

async function getAvatarMetrics(timeframe: string): Promise<AvatarMetrics[]> {
  return await analytics.query(`
    SELECT 
      avatar_id,
      AVG(completion_rate) as completion_rate,
      AVG(user_satisfaction) as user_satisfaction,
      AVG(session_duration) as average_session_time,
      AVG(retry_rate) as retry_rate
    FROM avatar_performance 
    WHERE created_at >= ?
    GROUP BY avatar_id
  `, [timeframe]);
}

// Use metrics to optimize avatar selection
async function selectOptimalAvatar(userSegment: string): Promise<string> {
  const metrics = await getAvatarMetrics('30d');
  
  // Find avatar with highest completion rate for this user segment
  const bestPerformer = metrics
    .filter(m => m.completionRate > 0.8) // Minimum threshold
    .sort((a, b) => b.completionRate - a.completionRate)[0];
  
  return bestPerformer?.avatarId || 'avatar_default';
}

4. Cache avatar data

Cache avatar information to improve performance:

Avatar caching

let cachedAvatars: Avatar[] | null = null;
let cacheTimestamp = 0;
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour

async function getAvailableAvatars(): Promise<Avatar[]> {
  const now = Date.now();
  
  // Return cached version if still valid
  if (cachedAvatars && (now - cacheTimestamp) < CACHE_DURATION) {
    return cachedAvatars;
  }
  
  // Fetch fresh data
  const { avatars } = await client.avatars.list();
  cachedAvatars = avatars;
  cacheTimestamp = now;
  
  return avatars;
}

Next steps

  • Sessions - Learn how to create sessions with avatar configuration
  • Languages - Configure multi-language support for your avatars
  • Modules - Understand how avatars adapt to different verification modules