What makes integrations long is not technical
eKYC integrations usually run long not because they are hard but because their scope is vague. "We'll add verification" does not turn into a sprint plan, and no estimate is possible until it is clear which step belongs to whom.
So the place to start is not code. It is the boundary of responsibility.
What sits on your side
Three things — all preparable on day one, none requiring an infrastructure change:
- An API key. Separate keys for sandbox and production, so test traffic never mixes with the real thing.
- Placing the SDK. Installed through your package manager, it starts the verification flow from your signup screen.
- A webhook endpoint. You define where the result lands, so your flow never blocks waiting for a response.
One more decision belongs here: the acceptance thresholds. Which score is approved automatically, and which band goes to manual review? That decision stays with you, and it should — risk appetite is product knowledge.
What sits on the provider's side
The verification models, keeping document formats current, tracking sanctions and PEP lists, and scaling under traffic spikes.
The practical meaning: when a new document format is issued or a list is updated, your integration does not break. The contract surface stays fixed while the models behind it change.
Live in three steps
Get the key. You can make the first call the same day; the request below gives you the starting point:
curl -X POST https://api.osvoy.com/api/v1/verifications \
-H "Authorization: Bearer $OSVOY_SANDBOX_KEY" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "user_10428",
"document_type": "passport",
"callback_url": "https://example-company.com/webhooks/osvoy"
}'
The verification_id in the response identifies the session; reference_id is the field you use to tie it back to your own user record. Leave it out and you have no key to attach the result to on your side.
Build in the sandbox. Place the SDK, connect your webhook endpoint, and simulate both passing and failing scenarios. It is the only way to settle your thresholds before opening to real traffic.
When a verification completes, this is the body that lands on your webhook endpoint:
{
"verification_id": "vrf_7kq2ha91",
"reference_id": "user_10428",
"status": "approved",
"score": 0.96,
"checks": {
"document": "pass",
"face_match": "pass",
"liveness": "pass",
"aml": "clear"
},
"completed_at": "2026-06-16T09:41:22Z"
}
The acceptance thresholds are encoded right here — and these three lines stay on your side:
if (result.score >= 0.90) return approve(result.reference_id);
if (result.score >= 0.70) return queueForManualReview(result.reference_id);
return reject(result.reference_id);
Go live. You run the same code with the production key. Do not turn the cutover into a project of its own.
What not to skip while testing
Testing the happy path is easy. The valuable cases are the others: a rejected verification, a request that times out, a webhook endpoint that cannot be reached. Seeing how those three behave before launch is cheaper than learning it in production.



