Skip to main content
For trying the API. You play both parts: your backend, from a Jupyter notebook, and the user, in a browser tab. Every block below is a notebook cell, run in order. Nothing here is an integration pattern, just the shortest path to seeing a real record. You need a workflow whose mode is hosted and a mobile number you can receive a code on. Reach for your uat key, whose token begins uat_, so the runs below come out of a uat workflow’s credits rather than out of what you bought for real work. Whichever key you use, the keys below are placeholders for your own, and a uat workflow’s key ends -uat. The verification is real either way. There is no sandbox: your documents really are read, and really are confirmed with the bodies that issued them.
Already keep the key in your environment? Drop the assignment and the client picks it up from the kernel. Nothing but the client reads it, so a plain api_key = "your key" variable does the job just as well.
Every error comes back as {"detail": "..."}. A cell that fails raises on the response it already kept in response, so response.json()["detail"] in a new cell says what went wrong.

1. See which workflows you have

Only one environment’s workflows are listed: whichever your key is for. Pick a hosted key. A staged workflow is walked by nobody, so the journey below does not apply to it; see the other recipe. credits and runs are the two limits a verification is held to. If the workflow you picked reads 0 credits, everything below is refused with 402 until we top it up, so check this before going on. See Credits and limits.

2. Create a verification

Use a mobile number you can receive a code on, because you are about to sign in as this user.
A real integration also sends return_url, which is where the journey drops the user once they submit. It has to be one of the URLs registered for your account, so leave it out while you are just trying this: the journey ends on its own screen instead.

3. Walk the journey yourself

Open that journey_url in a browser. Enter the same mobile number, we send you a code, and you work through the steps as your user would. Leave the notebook where it is; you come back to it in step 4.
To see what a handoff does instead, mint one and paste it into a fresh browser tab. It opens the journey already signed in, so no code is asked for. It is single use, so mint another for the next tab.
Mint it before you start polling in step 4: that cell holds the kernel, so nothing else runs until it stops.

4. Watch it settle

Back in the notebook. Poll until the verification leaves open.
Run this while you are still working through the journey and you will see the counts move as each step settles. The cell holds the kernel while it polls, and stops after five minutes rather than running for ever. Still open when it stops, because you are still filling the journey in? Run it again: reading a verification changes nothing, and the last record it read is what step 5 reads.

5. Read what it found

A step that passed with a gap stood up without something optional, such as a name that matched closely without matching exactly, and is the case worth looking at by hand. A step that failed carries the reasons it did not stand up. A step in error was never checked, because a source could not be reached.

6. Go round again

Reset clears every answer and file and reopens the journey, so you can walk it again with different documents without creating a new verification.
Creating is idempotent per mobile number and workflow, so calling step 2 again returns this same verification rather than a fresh one, answering 200 instead of 201 to tell you so. Reset is how you get a clean run. A reset runs the subject through again, so it uses a credit of its own when the run it opens ends. It also draws one of the workflow’s resets where the run it cleared had not ended, which in testing is most of them. credits_consumed on the record counts every run of it, which is how a round of testing shows up:

7. Clean up

When you are done testing, purge the verification. Everything you and the user provided is deleted, and the record stays readable saying what each step concluded and that you asked for the purge.

The record you just read

A finished hosted record, from a merchant-onboarding workflow that exercises eleven of the sixteen step types. Yours differs: which steps a verification runs, and the field names inside a form step, come from the workflow configured for your integration. The envelope around them is the same for everyone.
  • The record covers the steps this user was asked for. alt-business-proof is absent: this workflow asks for it only when the GST certificate fails, and here it passed, so the journey never reached it. Reading the verification with include_not_applicable=true shows it. selfie is different: it reads declined, because it was offered and the user refused.
  • answer is what was given; outputs is what the checks established. All the GST step was given is one PDF. Its outputs are the registry-confirmed identity, which is what to write into your own systems, and they carry values only because the step passed.
  • A passed step can note gaps. identity passed while the PAN, which this workflow treats as optional, was never shared: its gaps carries digilocker-document-missing, and the outputs carry pan as null. The step published its outputs, so every field its type publishes is there; one with nothing to say is null. Branch on code, never on message: reasons and gaps both carry a stable code alongside wording written for the user’s screen.
  • A step can settle without asking the user anything. addresses presents the places the premises photos were taken at, and the one here is already on the GST registration, so the match tagged it and recognised says so. Its answer is empty because there was nothing left to ask.
Reading the result is the field-by-field reference for a step.
When you move from trying it to building against it, read Hosted, Handoff, Callbacks, which is what you use instead of polling, and Going live before your first real subject.