Skip to main content

Programmatic API

Core SDK for custom integrations and direct API usage

Installation

npm
npm install @aho-sdk/verify

Quick Start

Use the AhoVerify class for full control over the verification flow:

<button
  id="docs-programmatic-verify"
  class="bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700 disabled:opacity-50">
  Verify Age
</button>

<div id="docs-programmatic-status" class="mt-4 text-sm text-gray-600"></div>

<script type="module" nonce="...">
  const { AhoVerify, Claim } = window.AhoVerify;

  const btn = document.getElementById('docs-programmatic-verify');
  const status = document.getElementById('docs-programmatic-status');

  btn.addEventListener('click', async () => {
    btn.disabled = true;
    status.textContent = 'Starting verification...';

    try {
      const client = new AhoVerify({ publishableKey: 'aho_pub_xxx' });
      const result = await client.verify({
        claims: [Claim.AGE_OVER_21],
        onStateChange: (state) => {
          status.textContent = `State: ${state}`;
        }
      });

      status.textContent = result.verified ? 'Verified!' : 'Not verified';
    } catch (error) {
      status.textContent = `Error: ${error.message}`;
    } finally {
      btn.disabled = false;
    }
  });
</script>

Browser Support Detection

isSupported(): checking...

detectPlatform(): checking...

<div id="docs-browser-support" class="space-y-1 text-sm">
  <p><strong>isSupported():</strong> <span id="docs-is-supported">checking...</span></p>
  <p><strong>detectPlatform():</strong> <span id="docs-platform">checking...</span></p>
</div>

<script type="module" nonce="...">
  const { isSupported, detectPlatform } = window.AhoVerify.credentials;

  document.getElementById('docs-is-supported').textContent = isSupported?.() ?? 'SDK not loaded';
  document.getElementById('docs-platform').textContent = detectPlatform?.() ?? 'SDK not loaded';
</script>

Examples

Full control over the verification flow using the core SDK directly. Build custom UIs or integrate with existing components.

Direct API Usage

Trigger verification programmatically using the core SDK.

<button
  id="programmatic-verify"
  class="bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700 disabled:opacity-50">
  Verify Age (Programmatic)
</button>

<div id="programmatic-status" class="mt-4 text-sm text-gray-600 dark:text-gray-400"></div>
<pre id="programmatic-result" class="mt-4 bg-gray-900 text-gray-100 p-4 rounded-lg text-sm overflow-auto max-h-60 hidden"></pre>

<script type="module" nonce="...">
  const { AhoVerify, Claim } = window.AhoVerify;
  const publishableKey = 'aho_pub_xxx';

  const btn = document.getElementById('programmatic-verify');
  const status = document.getElementById('programmatic-status');
  const result = document.getElementById('programmatic-result');

  btn.addEventListener('click', async () => {
    btn.disabled = true;
    status.textContent = 'Starting verification...';
    result.classList.add('hidden');

    try {
      const client = new AhoVerify({ publishableKey: publishableKey });
      const verifyResult = await client.verify({
        claims: [Claim.AGE_OVER_21],
        onStateChange: (state) => {
          status.textContent = `State: ${state}`;
        }
      });

      status.textContent = verifyResult.verified ? 'Verified!' : 'Not verified';
      result.textContent = JSON.stringify(verifyResult, null, 2);
      result.classList.remove('hidden');
    } catch (error) {
      status.textContent = `Error: ${error.message}`;
      result.textContent = JSON.stringify({ code: error.code, message: error.message }, null, 2);
      result.classList.remove('hidden');
    } finally {
      btn.disabled = false;
    }
  });
</script>

Browser Support Detection

Check if the browser supports the Digital Credentials API.

isSupported(): checking...

detectPlatform(): checking...

<div id="browser-support" class="space-y-2">
  <p><strong>isSupported():</strong> <span id="is-supported">checking...</span></p>
  <p><strong>detectPlatform():</strong> <span id="platform">checking...</span></p>
</div>

<script type="module" nonce="...">
  const { isSupported, detectPlatform } = window.AhoVerify.credentials;

  document.getElementById('is-supported').textContent = isSupported() ? 'Yes' : 'No';
  document.getElementById('platform').textContent = detectPlatform();
</script>

State Management

Track verification state changes for custom UI feedback.

import { AhoVerify, Claim } from '@aho-sdk/verify';

const client = new AhoVerify({ publishableKey: 'aho_pub_xxx' });

const result = await client.verify({
  claims: [Claim.GIVEN_NAME, Claim.FAMILY_NAME],
  onStateChange: (state) => {
    // States: 'idle' | 'requesting' | 'pending' | 'processing' | 'complete' | 'error'
    switch (state) {
      case 'requesting':
        showSpinner();
        break;
      case 'pending':
        showWaitingForWallet();
        break;
      case 'processing':
        showVerifying();
        break;
      case 'complete':
        hideSpinner();
        break;
      case 'error':
        showError();
        break;
    }
  }
});

Error Handling

Handle different error scenarios gracefully.

import { AhoVerify, Claim, AhoError, ErrorCode } from '@aho-sdk/verify';

const client = new AhoVerify({ publishableKey: 'aho_pub_xxx' });

try {
  const result = await client.verify({
    claims: [Claim.AGE_OVER_21]
  });
  console.log('Verified:', result);
} catch (error) {
  if (error instanceof AhoError) {
    switch (error.code) {
      case ErrorCode.USER_CANCELLED:
        console.log('User cancelled the verification');
        break;
      case ErrorCode.NO_CREDENTIAL:
        console.log('No matching credential found');
        break;
      case ErrorCode.NETWORK_ERROR:
        console.log('Network error, please try again');
        break;
      case ErrorCode.INVALID_API_KEY:
        console.log('Invalid API key');
        break;
      default:
        console.error('Verification failed:', error.message);
    }
  }
}

Custom Credential Rendering

Fetch and display the rendered credential manually.

import { AhoVerify, Claim } from '@aho-sdk/verify';

const client = new AhoVerify({ publishableKey: 'aho_pub_xxx' });

const result = await client.verify({
  claims: [Claim.GIVEN_NAME, Claim.FAMILY_NAME]
});

if (result.verified && result.renderUrl) {
  // Fetch the rendered credential
  const response = await fetch(result.renderUrl);
  const data = await response.json();

  if (data.format === 'svg') {
    // Insert SVG directly into the DOM
    document.getElementById('credential-container').innerHTML = data.content;
  }
}

API Reference

AhoVerify

The core SDK class for programmatic verification.

Constructor

const client = new AhoVerify({ publishableKey: 'aho_pub_xxx' });

Config Options

Property Type Description
publishableKey * string Publishable key (aho_pub_xxx)
baseUrl string Override API base URL
nonce string CSP nonce for child components

Methods

Method Returns Description
verify(options) Promise<VerifyResult> Initiates verification flow

verify() Options

Option Type Description
claims Claim[] Array of claims to request (required)
onStateChange (state: string) => void Callback for state changes

Credential Utilities

Available via AhoVerify.credentials

Function Returns Description
credentials.isSupported() boolean Returns true if the browser supports the Digital Credentials API
credentials.detectPlatform() Platform Returns the detected platform: 'chrome', 'safari', or 'unsupported'

Claim Enum

Available claims to request:

Constant Description
Claim.GIVEN_NAME
Claim.FAMILY_NAME
Claim.BIRTH_DATE
Claim.BIRTH_YEAR
Claim.AGE_IN_YEARS
Claim.AGE_OVER_18
Claim.AGE_OVER_21
Claim.SEX
Claim.NATIONALITY
Claim.BIRTH_PLACE
... and 23 more

Event Detail Types

Event payloads accessible via event.detail:

CredentialUnsupportedDetail

Emitted when the browser doesn't support the Digital Credentials API.

Property Type Description
reason string Human-readable explanation (e.g., "Digital Credentials API not supported")
platform Platform Detected platform: 'chrome', 'safari', or 'unsupported'
apiAvailable boolean Whether the Digital Credentials API exists in the browser (false = API missing entirely)
button.addEventListener('aho:credential:unsupported', (e) => {
  const { reason, platform, apiAvailable } = e.detail;

  if (platform === 'safari' && !apiAvailable) {
    showMessage('Please use Safari on iOS 26+ or Chrome on Android');
  } else {
    showFallbackExperience();
  }
});