Skip to main content

UX flow

Overview

This guide covers the complete user experience journey for AgeKey integration, including when to present users with the ability to Create, Use, and Upgrade AgeKeys. Understanding the full flow helps you design a seamless experience that guides users through age verification while offering AgeKey as a convenient option.


Who hosts each part of the experience?

AgeKey integration involves two distinct sets of user interfaces. Knowing which side owns each screen is the most important thing to internalize before you design the rest of your flow.

Hosted by your app (you build and style these screens):

  • The initial verification method picker (showing AgeKey alongside your other verification methods such as ID scan, credit card, and facial estimation)
  • Any non-AgeKey verification UI (typically rendered by your verification vendor inside your app)
  • Error and retry UI when a non-AgeKey verification fails
  • The "Offer AgeKey upgrade" prompt shown when a Use AgeKey result doesn't meet the requested age thresholds
  • The "Offer Create or Upgrade AgeKey" prompt shown after a successful non-AgeKey verification
  • The final "Grant access" or restricted-content screen

Hosted by AgeKey on agekey.org (handled for you):

  • The "Use AgeKey or Create AgeKey" dialog (rendered by AgeKey when you pass can_create=true on the Use AgeKey request)
  • The passkey authentication UI used to prove an existing AgeKey
  • The passkey creation UI used when creating a new AgeKey, including upgrades

Whenever you redirect a user to a URL on agekey.org, AgeKey takes over the UI for that step. When the user finishes (or abandons) the step, AgeKey redirects the browser back to the redirect_uri you configured and your app resumes control. Your responsibility ends at the redirect to AgeKey and resumes when the user lands back on your redirect_uri.


User journey overview

The AgeKey user experience is a unified flow that begins by presenting users with multiple verification options:

  1. Initial options (your app): Users see verification options including AgeKey, ID scan, credit card, facial estimation, and other methods
  2. If user chooses AgeKey (AgeKey-hosted): They're redirected to agekey.org and presented with "Use AgeKey" or "Create AgeKey" options
    • Use AgeKey: User authenticates with their existing passkey on AgeKey. Results are returned to your redirect_uri. If age thresholds aren't met, your app offers an upgrade
    • Create AgeKey: AgeKey redirects the user back to your redirect_uri with create_requested=true. Your app performs a non-AgeKey verification, then redirects back to AgeKey to create the passkey
  3. If user chooses traditional verification (your app): Your app performs a non-AgeKey verification. If successful, your app offers to Create or Upgrade AgeKey before redirecting to AgeKey for passkey creation or upgrade

All paths converge to the same outcome: your app grants access to the requested content.


When to present each flow

1. Use AgeKey flow

When to present:

  • User selects AgeKey from the initial verification options in your app
  • User has potentially created an AgeKey on a previous visit

User experience:

  1. (Your app) User selects AgeKey from the verification options you display
  2. (Your app) You redirect the user to agekey.org with can_create=true
  3. (AgeKey-hosted) User sees the "Use AgeKey or Create AgeKey" dialog and chooses "Use AgeKey"
  4. (AgeKey-hosted) User authenticates with their passkey
  5. (AgeKey-hosted) AgeKey evaluates the user's age against your requested thresholds and redirects back to your redirect_uri with a signed id_token
  6. (Your app) If thresholds are met, grant access; if not, your app offers an AgeKey upgrade

Implementation: See the Use AgeKey guide for detailed implementation steps.

Best Practice

Present AgeKey as one of the initial verification options in your own UI. AgeKey itself shows the "Use AgeKey or Create AgeKey" dialog after the redirect when you pass can_create=true, so users who picked AgeKey by mistake have an easy way to create one without restarting.

2. Create AgeKey flow

When to present:

  • User selects AgeKey from your initial options, sees the AgeKey-hosted Use-or-Create dialog, and chooses "Create AgeKey" (AgeKey redirects back to your app with create_requested=true)
  • OR user completes non-AgeKey verification successfully in your app, then chooses "Create" from the Create-or-Upgrade prompt you display

User experience:

  1. Path 1 (from AgeKey selection): (Your app) offers AgeKey → (AgeKey-hosted) dialog → user chooses "Create AgeKey" → (your app) receives create_requested=true and runs a non-AgeKey verification → (your app) redirects to AgeKey to create the passkey → (AgeKey-hosted) user creates passkey → (your app) receives the redirect back and grants access
  2. Path 2 (from traditional verification): (Your app) runs a non-AgeKey verification → (your app) offers "Create or Upgrade" → user chooses "Create" → (your app) redirects to AgeKey to create the passkey → (AgeKey-hosted) user creates passkey → (your app) receives the redirect back and grants access

Implementation: See the Create AgeKey guide for detailed implementation steps.

Best Practice
  • Always make AgeKey creation optional; never force users to create one
  • The "Create or Upgrade" prompt is rendered by your app, not by AgeKey; design it to clearly explain the benefit
  • The actual passkey creation UI is hosted by AgeKey, so you don't need to design it yourself

3. Upgrade AgeKey flow

When to present:

  • User used an AgeKey but the returned age thresholds aren't met, so your app shows an "Offer Upgrade" prompt
  • OR user completes non-AgeKey verification successfully in your app, then chooses "Upgrade" from your Create-or-Upgrade prompt

User experience:

  1. Path 1 (from Use AgeKey): (AgeKey-hosted) user authenticates → (your app) receives the id_token, sees thresholds aren't met, and offers an upgrade → (your app) runs additional verification → (your app) redirects to AgeKey to upgrade the passkey → (AgeKey-hosted) user authenticates passkey to attach the new signal → (your app) receives redirect back and grants access
  2. Path 2 (from traditional verification): (Your app) runs a non-AgeKey verification → (your app) offers "Create or Upgrade" → user chooses "Upgrade" → (your app) redirects to AgeKey → (AgeKey-hosted) user authenticates passkey → (your app) receives redirect back and grants access

Implementation: See the Upgrade AgeKey guide for detailed implementation steps.

Best Practice
  • The "Offer Upgrade" prompt is hosted by your app; only show it when thresholds actually aren't met or when the user has just completed a non-AgeKey verification
  • Make the upgrade optional; users can always decline and continue with traditional verification

Complete flow decision tree

The following diagram illustrates the complete unified user experience flow. Boxes are color-coded by who owns each screen:

  • Blue: your app hosts the UI (you build and style it)
  • Purple: AgeKey hosts the UI at agekey.org (handled for you; user is redirected back to your redirect_uri when done)
  • Green: terminal success state in your app
  • Gray diamonds: decision points

User experience best practices

1. Progressive disclosure

Don't overwhelm users with all options at once. Present flows contextually:

  • Initial screen (your app): Show verification options, including AgeKey, ID scan, and credit card, so users can choose
  • After selecting AgeKey (AgeKey-hosted): AgeKey shows both "Use AgeKey" and "Create AgeKey" options automatically when you pass can_create=true (no UI work required from you)
  • After traditional verification (your app): Offer both "Create" and "Upgrade" options to maximize user choice
  • After Use AgeKey fails thresholds (your app): Offer upgrade option with fallback to traditional verification

2. Clear messaging

Use clear, benefit-focused language:

  • ✅ "Verify with AgeKey - Fast and secure"
  • ✅ "Save as AgeKey for faster verification next time"
  • ✅ "Upgrade your AgeKey to access this content"
  • ❌ "Create AgeKey" (without context)
  • ❌ "Upgrade AgeKey" (without explaining why)

3. Graceful fallbacks

Always provide alternatives:

  • If AgeKey creation fails → User can continue without it
  • If AgeKey verification fails → Offer traditional verification
  • If upgrade is declined → Allow traditional verification

4. Error handling

Handle errors gracefully:

  • Network failures → Retry option
  • Expired tokens → Regenerate and retry
  • User cancellation → Return to previous step
  • Verification failures → Clear error messages with next steps

Next steps

Now that you understand the complete UX flow:

  1. Review individual guides for detailed implementation:

  2. Plan your implementation using the decision tree in the preceding section

  3. Test thoroughly with different user scenarios

  4. Monitor and iterate based on user feedback

For mobile app integration, see the Mobile Apps guide for platform-specific considerations.