Programmatic API
Core SDK for custom integrations and direct API usage
Installation
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();
}
});