Skip to main content

Run your first verification

This guide creates an individual application against an explicit published workflow, opens the hosted journey, and shows how your backend learns the result.

Before you begin

You need:

  • a free Assayra tenant and administrator account (create one without a card);
  • a published Individual KYC workflow;
  • an API key with workflows:read, applications:read and applications:write; and
  • an HTTPS webhook endpoint for production integrations.

Create keys inside Client Admin Portal → Developers. The secret is shown once; Assayra stores only a one-way hash and a visible prefix.

Before selecting a module for live use, read the public release contract:

curl 'https://verify.example.com/v1/capabilities'

Only capabilities where liveEligible is true, and whose supportedScope matches your tenant, country, document, device and deployment region, may be used in a live journey. The bounded Live trial lets you validate real capture and owned-engine execution; it does not certify broad country coverage or automated approval.

1. Find a published workflow

curl 'https://verify.example.com/v1/workflows' \
-H 'Authorization: Bearer pl_sandbox_REPLACE_ME'

Select a workflow where applicationType is individual and status is published. Do not select “the newest” in application code: store the approved workflow ID in your own environment configuration so policy changes are deliberate.

2. Create the application

curl -X POST 'https://verify.example.com/v1/applications' \
-H 'Authorization: Bearer pl_sandbox_REPLACE_ME' \
-H 'Idempotency-Key: 018f65c6-7ee2-7a84-9f3c-3ee29a70dc8b' \
-H 'Content-Type: application/json' \
-d '{
"type": "individual",
"workflowId": "wf_individual_published_id",
"externalReference": "customer_845901",
"recipientEmail": "amara@example.test",
"sendEmail": true,
"person": {
"givenName": "Amara",
"familyName": "Vale",
"dateOfBirth": "1992-06-14",
"nationality": "SG",
"email": "amara@example.test"
}
}'

The response includes the application and its durable invitation:

{
"application": {
"id": "app_…",
"status": "collecting",
"externalReference": "customer_845901"
},
"applicantPath": "/verify/opaque-single-use-token",
"expiresAt": "2026-07-28T10:00:00.000Z",
"invitation": {
"id": "inv_…",
"applicantUrl": "https://verify.example.com/verify/opaque-single-use-token",
"status": "sent",
"emailConfigured": true
}
}

Use the returned absolute invitation.applicantUrl. Never construct or guess the token yourself.

3. Present the journey

Redirect the applicant to invitation.applicantUrl, display it as a QR handoff, or mount it through an SDK:

import { mountAssayraHostedVerification } from "@assayra/sdk-web";

mountAssayraHostedVerification({
container: document.querySelector("#assayra-verification")!,
verificationUrl: invitation.applicantUrl,
onComplete(event) {
// Treat this as a UI notification. Reconcile final state server-to-server.
console.info(event.reference, event.status);
},
});

The hosted journey follows the pinned workflow. A custom frontend can change presentation, but it cannot skip protected capture, consent, evidence or server-side policy gates.

4. Receive the event

Subscribe to application.submitted and application.decided. Assayra signs the exact request body with HMAC-SHA256 and includes a timestamp and delivery ID. Verify the signature before parsing or acting on the event.

{
"id": "evt_…",
"type": "application.decided",
"createdAt": "2026-07-21T10:06:22.781Z",
"data": {
"applicationId": "app_…",
"externalReference": "customer_845901",
"status": "approved"
}
}

5. Reconcile final state

curl 'https://verify.example.com/v1/applications/app_…' \
-H 'Authorization: Bearer pl_sandbox_REPLACE_ME'

Use this authenticated response—not a browser callback—as your source of truth. Map Assayra’s status model to your own account lifecycle.

Next steps