VettiGuard

Build human, document and identity verification from one VettiGuard platform.

Use https://api.vettiguard.com/v1 for new integrations. Keep private credentials and final trust decisions on your backend, then choose the smallest verification surface that satisfies your workflow.

VettiGuard Developer Platform Web · backend · hosted capture · native apps
HumanDocumentsIdentityWebhooks

Start with the verification contract that matches the decision you need to make.

Document screening and identity verification are separate surfaces. You can use them independently or compose them into a governed identity journey.

Private credentials stay on trusted servers.

Use scoped API credentials where available. Legacy secrets remain accepted only where the endpoint contract documents compatibility. Never embed private credentials, direct identity-session capabilities, or native-service bearer tokens in browser/mobile bundles.

Document scopeidentity.document.verify
Identity scopeidentity.verify
Session capabilityX-VettiGuard-Identity-Session-Token
Hosted capabilityX-VettiGuard-Hosted-Token
01

Render the browser widget with a public site key.

The browser receives only the public integration identity. Your backend validates the response token before the protected action runs.

<script src="https://vettiguard.com/assets/captcha.js?v=1786480772" defer></script>

<div class="vettiguard-captcha"
     data-sitekey="YOUR_SITE_KEY"
     data-action="account-registration"></div>
02

Validate the human-verification response before the protected action.

Require success and validate the expected action, hostname and applicable score/policy contract. Transport errors and unavailable required verification must not become a bypass.

$result = $verifier->verify(
    $_POST['vettiguard-response'] ?? '',
    $_SERVER['REMOTE_ADDR'] ?? null,
    'account-registration'
);

if (!$result->isSuccess()
    || $result->action() !== 'account-registration'
    || $result->hostname() !== 'example.com') {
    http_response_code(422);
    exit('Verification failed.');
}

// Run the protected action only here.

Screen identity documents without starting a full identity session.

POST /v1/documents/verify is the one-shot server-to-server surface. It can inspect front/back evidence, extract machine-readable fields, report capture quality, and return a normalized risk decision. It does not imply government or issuer database confirmation.

Build a supported-document request

Use the capability endpoint before presenting document options in your application.

GEThttps://api.vettiguard.com/v1/documents/supported

Country profiles describe native structural/capture capabilities. They are not issuer certification.

document_authenticity
native-screening-signals
authoritative_source
not_performed unless a separately governed connector is configured
Client decision
Never infer “government verified” from native screening.

Credential compatibility: the example below uses the legacy secret request field because the existing one-shot document contract retains it for backward compatibility. Use a scoped server credential where your workspace/API contract enables it.

FRONT_BASE64="$(base64 < id-front.jpg | tr -d '\r\n')"
BACK_BASE64="$(base64 < id-back.jpg | tr -d '\r\n')"

curl -X POST https://api.vettiguard.com/v1/documents/verify \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{\
    \"secret\": \"YOUR_LEGACY_SERVER_SECRET\",\
    \"country\": \"AUS\",\
    \"document_type\": \"drivers_license\",\
    \"front_image\": \"$FRONT_BASE64\",\
    \"back_image\": \"$BACK_BASE64\",\
    \"require_portrait\": false\
  }"
{
  "success": true,
  "verification": {
    "provider": "VettiGuard Native",
    "checks": {
      "image_quality": { "status": "passed" },
      "mrz": { "status": "valid" },
      "document_authenticity": { "status": "screening_passed" },
      "authoritative_source": { "status": "not_performed" }
    },
    "risk": {
      "level": "low",
      "decision": "verify"
    },
    "assurance_boundary": {
      "document_authenticity": "native-screening-signals",
      "authoritative_source": "not-performed"
    }
  }
}
verify
Eligible native screening result

Continue only if this screening level is sufficient for your business policy.

review
Human review or stronger verification

Do not silently convert an ambiguous or unavailable check into approval.

recapture
Recoverable capture problem

Ask the user to retake the document using the returned capture guidance.

reject
Material contradiction/high risk

Respect final policy outcomes and retain only governed evidence.

Use a stateful session when document evidence must become an identity decision.

Direct sessions support document_only, standard, and high assurance. Standard/high require trusted VettiGuard facial comparison and liveness; browser/mobile “matched” booleans are never authoritative.

1Create sessionPOST /identity/verification/session
2Submit documentPOST /{id}/document
3Trusted face/livenessPOST /{id}/face
4CompletePOST /{id}/complete
5Read resultGET /{id}/result
POST https://api.vettiguard.com/v1/identity/verification/session
Accept: application/json
Content-Type: application/json
Authorization: Bearer YOUR_SCOPED_SERVER_CREDENTIAL

{
  "subject_id": "customer-4821",
  "action": "customer-onboarding",
  "assurance_level": "high",
  "country": "AUS",
  "document_type": "drivers_license",
  "consent_accepted": true,
  "consent_reference": "consent-event-7d1a"
}

Create the browser journey from your backend and let VettiGuard handle capture UX.

The create call is server-authenticated and requires explicit consent plus a non-empty consent reference. The browser receives a separate vgh_ hosted capability, not the underlying direct-session token.

Hosted journey rules

  • Hosted capability is delivered in the URL fragment
  • Fragment is removed immediately by the hosted client
  • Continuation uses X-VettiGuard-Hosted-Token
  • Client-supplied match/liveness/score fields are rejected
  • Standard/high assurance remains a backend decision
POST https://api.vettiguard.com/v1/identity/hosted/session
Authorization: Bearer YOUR_SCOPED_SERVER_CREDENTIAL
Content-Type: application/json

{
  "subject_id": "customer-4821",
  "action": "customer-onboarding",
  "assurance_level": "high",
  "consent_accepted": true,
  "consent_reference": "consent-event-7d1a",
  "country": "AUS",
  "document_type": "drivers_license",
  "parent_origin": "https://app.example.com",
  "return_url": "https://app.example.com/onboarding/complete",
  "theme": "system",
  "locale": "en-AU"
}

Identity verification is a state machine, not a Boolean.

Preserve VettiGuard states so recoverable captures can be retried and review-required cases remain pending instead of being incorrectly approved or permanently rejected.

Verified

The captured policy and required checks completed successfully.

Recapture required

Recoverable capture quality issue; request a fresh document capture.

Manual review

Keep the protected action pending while an authorised reviewer resolves the case.

Rejected

Respect a final policy rejection and do not retry indefinitely.

Consume signed lifecycle events asynchronously and idempotently.

Verify HMAC-SHA-256 using the raw request body before JSON parsing, enforce a bounded timestamp tolerance, and deduplicate deliveries before running your business action.

identity.verification.verified
identity.verification.rejected
identity.verification.review_required
identity.verification.review_resolved
identity.verification.recapture_required
identity.verification.cancelled
{unix_timestamp}.{raw_request_body}

Compare signatures in constant time and keep webhook secrets only in server-side secret storage.

Exercise document and identity states without touching production.

The simulator is deterministic and browser-local. It makes no VettiGuard API request, creates no billable verification, and never treats synthetic output as an issuer/government confirmation. Optional sample images stay in your browser and are used only for local preview metadata.

Simulation mode No API call · no billing · no evidence upload
Optional local document preview

Images are not parsed for identity data and are never sent by this simulator.

Ready
HTTP —
{
  "simulation": true,
  "status": "ready"
}

Assurance boundary: simulator responses are synthetic. Native document screening is not authoritative-source confirmation, and browser-supplied biometric claims are never a trusted identity decision.

Retry only when the failure class permits it.

Evaluate the HTTP status and the normalized VettiGuard response. Avoid retry storms, do not bypass unavailable required verification, and reuse idempotency/session semantics where documented.

StatusMeaningRecommended handling
400Invalid or unsupported input/stateFix the request; do not blindly retry.
401Credential/session capability invalidStop and rotate/re-authenticate as appropriate.
403Scope/workspace/policy restrictionDo not retry until authorization/configuration changes.
409Concurrent session state changeReload the session/result before deciding whether to retry.
429Rate limit or quotaHonor bounded backoff and quota policy.
503Required verification service unavailableFail closed to pending/review; retry with bounded backoff.

Screening is not issuer confirmation.

document_authenticity represents VettiGuard Native screening signals. Unless a separately governed authoritative connector is configured, authoritative_source remains not performed.

Keep secrets off clients.

Private site secrets, scoped server credentials, identity-session capabilities and native-service bearer tokens belong in backend configuration or secret management.

Use the dedicated API host for new integrations.

https://api.vettiguard.com/v1 is canonical. The legacy https://vettiguard.com/api/v1 base remains a compatibility path for existing integrations.

/challenge/siteverify/documents/verify/documents/supported/identity/verification/*/identity/hosted/*
Full API reference