Quickstart
Start integrating AgeOnce in 5 minutes
Quickstart
This guide will help you integrate AgeOnce into your project in minutes.
Prerequisites
- Active account on Dashboard
- OAuth credentials (Client ID and Client Secret from Settings)
- Configured Redirect URI
Redirect URI is the URL on your server where the user will be redirected after verification.
Step 1: Get credentials
Sign up and log in to AgeOnce Dashboard
Complete checkout (choose a plan) — this creates your organization and OAuth credentials
After checkout you'll see Client ID and Client Secret once. Save them — the Client Secret will not be shown again
Go to Settings and add your Redirect URI (e.g. https://yoursite.com/callback)
Already have an account? Client ID is always visible in Settings. If you lost the Client Secret, use Regenerate Client Secret — the new secret will be shown once.
Step 2: Redirect user to verification
When a user needs to pass age verification, redirect them to AgeOnce:
https://app.ageonce.com/verify?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&state=RANDOM_STATE&age_required=18Parameters
| Parameter | Description |
|---|---|
client_id | Your Client ID from the dashboard |
redirect_uri | URL for redirect after verification |
state | Random string for CSRF protection |
age_required | Optional. Minimum age to verify (e.g. 18, 21). Default: 18 |
Step 3: Handle callback
After successful verification, the user will be redirected to your redirect_uri with the code parameter:
https://yoursite.com/callback?code=AUTHORIZATION_CODE&state=YOUR_STATEStep 4: Exchange code for token
Make a POST request to /api/oauth/token. Use HTTP Basic Auth with client_id:client_secret (Base64) and send grant_type, code, redirect_uri, and optionally state in the body:
AUTH=$(echo -n "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" | base64)
curl -X POST https://app.ageonce.com/api/oauth/token \
-H "Content-Type: application/json" \
-H "Authorization: Basic $AUTH" \
-d '{"grant_type":"authorization_code","code":"AUTHORIZATION_CODE","redirect_uri":"YOUR_REDIRECT_URI","state":"YOUR_STATE"}'const credentials = Buffer.from(
`${process.env.AGEONCE_CLIENT_ID}:${process.env.AGEONCE_CLIENT_SECRET}`
).toString('base64');
const response = await fetch('https://app.ageonce.com/api/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`,
},
body: JSON.stringify({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: process.env.AGEONCE_REDIRECT_URI,
state: stateFromCallback,
}),
});
const { age_token, transaction_id } = await response.json();import base64, os, requests
credentials = base64.b64encode(
f"{os.environ['AGEONCE_CLIENT_ID']}:{os.environ['AGEONCE_CLIENT_SECRET']}".encode()
).decode()
response = requests.post('https://app.ageonce.com/api/oauth/token',
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {credentials}'},
json={'grant_type': 'authorization_code', 'code': authorization_code,
'redirect_uri': os.environ['AGEONCE_REDIRECT_URI'], 'state': state_from_callback})
data = response.json()
age_token = data['age_token']
transaction_id = data.get('transaction_id') # Audit ID$credentials = base64_encode(getenv('AGEONCE_CLIENT_ID') . ':' . getenv('AGEONCE_CLIENT_SECRET'));
$response = file_get_contents('https://app.ageonce.com/api/oauth/token', false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nAuthorization: Basic " . $credentials,
'content' => json_encode([
'grant_type' => 'authorization_code',
'code' => $authorizationCode,
'redirect_uri' => getenv('AGEONCE_REDIRECT_URI'),
'state' => $stateFromCallback,
]),
],
]));
$data = json_decode($response, true);
$ageToken = $data['age_token'];
$transactionId = $data['transaction_id'] ?? null; // Audit IDResponse
{
"age_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 600,
"transaction_id": "550e8400-e29b-41d4-a716-446655440000"
}| Field | Description |
|---|---|
age_token | JWT token with age verification claims |
token_type | Always "Bearer" |
expires_in | Token lifetime in seconds |
transaction_id | Unique ID for this verification (Audit ID). Use for compliance, receipts, and searching in Dashboard Audit Logs. |
Step 5: Validate token
age_token is a JWT containing age information. You can:
- Validate via API — POST request to
/api/oauth/validate - Validate locally — using the public key from
/api/oauth/jwks
{
"sub": "anonymous",
"age_verified": true,
"min_age": 18,
"age_over": 18,
"verification_id": "550e8400-e29b-41d4-a716-446655440000",
"verified_at": "2026-02-11T12:00:00Z",
"client_id": "your_client_id",
"iat": 1739275200,
"exp": 1739361600,
"iss": "ageonce"
}| Claim | Description |
|---|---|
verification_id | Transaction ID — same as transaction_id from token exchange. Use for audit trail and compliance. |
Done! You can now check age_verified to grant access to age-restricted content.