Creating a verification
POST /verifications names one of your workflows by workflow_key. What else it takes depends on that
workflow’s mode: a hosted workflow takes the user’s mobile, which they sign in to the journey
with, and may take a return_url; a staged workflow opens no journey, so it takes neither, and a
call that names either is refused with 400.
Creating is idempotent per subject and workflow. On a hosted workflow the same phone number in
the same workflow always resolves to the same verification; on a staged workflow the same
reference_user_id does. A retry returns the existing record as it stands, whatever its status, so a
repeat call is a safe retry rather than a way to change a verification already under way. To run the
same subject through again, reset the existing verification.
The status code says which of the two you got. 201 means the call created the verification. 200
means this subject already had one in this workflow and you are reading that record back: nothing was
created and nothing changed. Read its status before acting on it, because a record already submitted
or completed is not waiting for anyone. Where you expected a new verification, a 200 is how you find
out the same subject has reached you twice.
A create is held to the workflow’s credits and to how many verifications it may have going at once. A
workflow with no credits left refuses it with 402, and one already at its live ceiling with 409.
Only a call that would create a verification is refused: one that resolves to a record you already have
answers 200 as it always does, so a retry never turns into a payment error. See
Credits and limits.
context is facts you already know about the subject, and it is fixed for the life of the
verification: a reset preserves it, and nothing can add to it afterwards. Where a workflow has a
required step that reads one of these fields and cannot run without it, creating one without that field
is rejected with 400, and the detail names every field that was missing.
A field you do supply is held to the step that reads it. One in a shape that step cannot use is
rejected with 400 too, naming the field and the step, because a value only the journey would have
choked on is worth hearing about from the call that sent it. Fields no step reads are yours to use as
you like, and are echoed back untouched.
On a hosted workflow the response includes journey_url, the address the journey is walked at, and
return_url must match one of the URLs registered for that workflow. On a staged workflow
journey_url, mobile and return_url are all null: nobody is sent anywhere.
Which workflows you can name
GET /workflows lists the keys you can create against, with the mode, retention window and step count
of each. To see what one of them will ask for before creating anything on it, read the workflow itself
with GET /workflows/{workflow_key}. It returns every step the workflow can present, in the order they
are answered, each with the condition that gates it and an intake saying how it is answered over the
API.
A step also carries a label, which is your own name for it where your workflow is configured with
one, and the kinds of document its slots take carry theirs. A label is a name for your own records
rather than wording for a screen: nothing is addressed by it, and the key remains what names a step
everywhere. Several steps may share a label on purpose. A workflow that asks a sole proprietor, a
partner and a director each for a PAN declares three steps, because the condition gating each is
different, and one of them runs; giving all three the same label is how you read the PAN off the
record without knowing which. The wording the person being verified reads is theirs, so no step’s
intake carries it.
Custom output transformations do the same one
level down, for the fields a step publishes.
The mode, the step keys and the intake are stable. The rest is a reference view of configuration we
maintain and it changes without notice, so read it to understand a journey rather than to build
behaviour against it; Step types says more. Any one verification walks some
of those steps rather than all of them, and its record reports the ones it walked.
Versions
A change to a workflow is published as its next version, and a verification keeps the version it was created on. Versions are numbered from 1.GET /workflows and GET /workflows/{workflow_key} report
the latest version as version, and that is the version a verification created now runs. Every
verification says which version it runs in a version of its own, and so does the callback its submission
sends.
A version published after a verification was created never changes it: not what it asks for, not which
steps its record reports, not the names its outputs arrive under, and not how long it holds data. A
subject partway through a journey finishes the one they started, and a finished record reads the same
for as long as you keep it. Creating a verification for a subject who already has one answers that
record, on its own version, and is never refused for a field of context only a later version reads.
GET /workflows/{workflow_key}/versions lists every version a workflow has published, newest first,
and GET /workflows/{workflow_key}/versions/{version} reads one of them as it was published. Read the
version a verification names to see the journey it runs, and read two to see what changed between them:
a version reports its steps exactly as the workflow reports its latest one’s, so they compare field for
field. A workflow taken out of use keeps its versions readable for the verifications that ran them.
Resetting a verification is how you move it onto the latest version: the reset clears everything and
reopens the verification there, so its version moves on with it. What to do about verifications left
on an earlier version is up to you: let them finish, reset them, or purge them. Where the latest version
reads a context field the verification was not created with, the reset is refused with 400 and the
verification stays on its version; purge it and create a new one with that context instead.
Identifiers
Creating a verification whose
reference_user_id already belongs to a different user in that hosted
workflow is refused with 409, naming the verification that holds it. The same subject in a second
workflow keeps the same reference: that is a verification of its own.
Statuses
A verification has six statuses, and they mean the same thing however the documents arrived. Five of them say how the run ended; the sixth,expired, says the record is past its useful life and is kept
for your audit alone.
open covers two situations that look different from outside: a person still working through a
journey, and a staged submission being assembled or having its checks run. Both amount to the same
thing, which is that the verification is not settled yet. On a staged verification,
run_requested_at says which: null while you are still uploading, set from the moment you asked for
the checks to run.
Each ending also settles what the run cost. Reaching
completed, cancelled or expired uses one
credit of the workflow’s balance; gated and failed use none, and neither does a record still open
or submitted. credits_consumed on the record counts what it has used, over every run of it. See
What uses a credit.
A hosted journey cannot be submitted while any step is unanswered, still being checked, or unresolved
after a check that could not run. A submission you sent is submitted by the run once every step has
settled, or once the run gives up on a source it could not reach, in which case that step reads
error. Either way no step’s outcome changes between submitted and completed. Poll
GET /verifications/{verification_id} until it reads completed, cancelled, gated or failed.
To see how many of your verifications stand in each status, or to list the ones that stand in a
particular one, see Tracking verifications.
Expiry supersedes every ending
expired is not one ending among the others. Whatever a verification ended as, it expires once its
retention window runs out, or the moment you purge it:
Timestamps
Timestamps are in IST. Each ending stamps its own on the way past, and those survive expiry, so nothing about how a run ended is lost:
A verification that was never submitted, cancelled, gated or failed carries none of those endings,
which is how an abandoned journey reads:
expired with nothing before it.
last_activity_at is when the verification was last acted on, which on one nobody has touched is the
moment you created it. Read it to tell a journey that is moving from one that has stopped. Together with
expires_after_days, the window the record’s own version holds it to, it says when a verification left
untouched expires.
Ending or restarting
Reset is the one operation that clears what was collected without deleting the record’s data for good,
and it is how you run a
cancelled, completed, gated or failed verification through again. Purge is how
you delete the data before the window would.
An expired verification cannot be reset, whether it expired on the window or you purged it. Expiring
deletes the subject’s sign-in along with the rest of their data, so by the time the status reads
expired there is nobody a reopened journey could sign in. Verify that subject again by creating a new
verification.
Expiry and retention
Every workflow expires a verification after a set period of inactivity, and none of them can hold data indefinitely. How long is configured per workflow, anywhere from 1 to 120 days, so different journeys on your account can hold data for different lengths of time. Tell us what each of yours needs and we set it when we publish them; a workflow that asks for nothing in particular gets 30 days. Each verification is held for as long as the version it runs says, and reports that window on its record asexpires_after_days. A change to the window reaches the verifications created or reset after
it and never one already under way, so read a verification’s window off the verification:
expires_after_days on a workflow is its latest version’s, which a record on an earlier version may not
be held to.
Expiring is one act, not two: the data is deleted and the record is marked expired in the same moment.
Purging is the same act at the moment you ask for it.
The window is counted from last_activity_at, so it limits how long a verification may be idle
rather than how long anyone may take over it. On a hosted workflow every answer, upload and withdrawal
moves that moment forward, and a check still running against a source does not. On a staged workflow
your uploads, withdrawals and run request move it forward, and so does the run of the checks. A
verification you create and nobody touches counts as idle from the moment you created it.
What is deleted
Everything the subject provided: their answers, the values read off their documents, the files themselves, their mobile number, thecontext you supplied when creating it, and the values you sent
with the run request.
What survives
A record of what the system did, not of the person it did it to: theid, your reference_user_id,
the workflow_key and mode, every timestamp the run collected, what expired it, the callback
outcome, and what each step concluded - every step’s state and the reason codes behind it, frozen
at the moment of expiry.
So an expired record still answers “did this subject pass, and on which step did they not?” while
holding nothing about them. It reports no collected data and no documents, and asking to download its
files links nothing.
Together, reference_user_id and workflow_key are the handle on an expired record, which is why the
reference is required and unique within a workflow. Keep your own copy of anything else you need to tie
a record back to a person.
Coming back afterwards
Before the window closes, a reset reopens a verification whatever state it reached and starts the window afresh, so a subject who went quiet can be sent through again. What a reset clears stays cleared: they provide it again. After the window closes, or after a purge, verify that subject again by creating a new verification. An expired record keeps itsreference_user_id for your audit but no longer holds the
name against a live one, so create it under the same reference you used before. You get a fresh record,
and the expired one stays readable alongside it.