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:readandapplications: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.