Back
DOCS
OverviewQuick StartEmbed WidgetEventsAPI ReferenceStatus PollingDocumentsRetentionBYOSExamples
OverviewQuick StartEmbed WidgetEventsAPI ReferenceStatus PollingDocumentsRetentionBYOSExamples
OverviewQuick StartEmbed WidgetEventsAPI ReferenceStatus PollingDocumentsRetentionBYOSExamples
  1. Home
  2. Docs
  3. Status Polling

Status Polling

After receiving the ae:complete event from the widget, poll the verification status from your backend server. Never expose your secret key (sk_verify_) in browser code.

Why Poll from the Backend?

The status and verified endpoints require a secret key (sk_verify_) which provides full API access including personal data (date of birth, document country). This key must never be sent to the browser. Your backend acts as a proxy between the browser and the AgeEvidence API.

Recommended Cadence

Use a progressive polling strategy to balance responsiveness with API efficiency:

  • First 2 minutes: Poll every 5 seconds. This catches age_only auto-decisions and fast admin reviews.
  • After 2 minutes: Poll every 30 seconds. Most manual reviews take 1-5 minutes.
  • After 10 minutes: Stop polling and notify the user that review is in progress. Allow them to check back later.

Status Values

StatusTerminalDescription
pendingNoVerification submitted, waiting for admin review.
under_reviewNoAn admin has opened the verification and is reviewing it.
approvedYesVerification passed. Grant the user access.
rejectedYesVerification failed. Deny access.
resubmit_requiredYesUser needs to resubmit (e.g. blurry ID, incomplete liveness). Show the widget again.

Stop polling when you receive a terminal status (approved, rejected, or resubmit_required).

Quick Check vs Full Status

Two endpoints are available depending on how much information you need:

  • Quick check: GET /v1/verify/:externalId/verified returns { verified: boolean }. Use this when you only need a pass/fail answer.
  • Full status: GET /v1/verify/:externalId/status returns detailed information including DOB, estimated age, document country, and expiry date.

Backend Polling Example

A complete Node.js/Express example with progressive backoff:

const AGEEVIDENCE_API = 'https://ageevidence.com';
const SECRET_KEY = process.env.AGEEVIDENCE_SECRET_KEY; // sk_verify_...

// Proxy endpoint for your frontend
app.get('/api/check-verification', async (req, res) => {
  const { externalId } = req.query;

  const response = await fetch(
    `${AGEEVIDENCE_API}/v1/verify/${externalId}/status`,
    {
      headers: { 'X-API-Key': SECRET_KEY },
    }
  );

  if (!response.ok) {
    return res.status(response.status).json({ error: 'Failed to check status' });
  }

  const data = await response.json();
  res.json(data);
});

// Quick boolean check endpoint
app.get('/api/is-verified', async (req, res) => {
  const { externalId } = req.query;

  const response = await fetch(
    `${AGEEVIDENCE_API}/v1/verify/${externalId}/verified`,
    {
      headers: { 'X-API-Key': SECRET_KEY },
    }
  );

  if (!response.ok) {
    return res.status(response.status).json({ error: 'Failed to check status' });
  }

  const data = await response.json();
  res.json(data);
});

Frontend Polling with Backoff

Call your own backend proxy (not the AgeEvidence API directly) from the browser:

async function pollVerificationStatus(externalId) {
  const startTime = Date.now();
  const TWO_MINUTES = 2 * 60 * 1000;
  const TEN_MINUTES = 10 * 60 * 1000;

  while (true) {
    const elapsed = Date.now() - startTime;

    // Stop after 10 minutes
    if (elapsed > TEN_MINUTES) {
      showMessage('Review in progress. Check back later.');
      return;
    }

    const res = await fetch(`/api/check-verification?externalId=${externalId}`);
    const { data } = await res.json();

    if (data.status === 'approved') {
      onVerificationApproved(data);
      return;
    }

    if (data.status === 'rejected' || data.status === 'resubmit_required') {
      onVerificationFailed(data);
      return;
    }

    // Progressive backoff: 5s for first 2 min, then 30s
    const delay = elapsed < TWO_MINUTES ? 5000 : 30000;
    await new Promise(resolve => setTimeout(resolve, delay));
  }
}
© 2026 AgeEvidence. All rights reserved.
DocsPricingPrivacyTermsContact