Use hosted onboarding when an applicant will complete personal verification on a page provided by Graph. Your server creates and tracks the onboarding. The applicant opens a link and follows the prompts. On completion, Graph returns the ID of the person it created or matched.
For integrations that collect the person's details directly, the Create Person flow is also available.
1. Start an onboarding from your server
Use https://api.useoval.com with a bearer key for the applicant’s organisation and intended environment. Live requests require an organisation enabled for live mode. If your key requires request signing, sign each API request as described in Authentication.
Send POST /entity_onboarding with a reference you can reuse if your request times out.
{
"entity_type": "person",
"reference": "applicant-0042"
}
Graph returns HTTP 202. Save data.id as the onboarding ID. The initial response can have an empty actions array and a null person_id.
{
"message": "Onboarding accepted",
"data": {
"id": "10000000-0000-4000-8000-000000000042",
"entity_type": "person",
"reference": "applicant-0042",
"status": "pending",
"status_reason": null,
"person_id": null,
"created_at": "2026-11-01T12:00:00Z",
"updated_at": "2026-11-01T12:00:00Z",
"actions": []
}
}
Retry an uncertain create with the same reference and inputs. Graph returns the existing onboarding in its current state. Changing the inputs for that reference in the same organisation and environment returns HTTP 409. Omitting the reference removes this replay protection.
2. Give the applicant the current link
Call GET /entity_onboarding/{id} with the ID from step 1. If there is no action yet, wait and fetch again, spacing out repeated requests. Once an open_url action is available and has a URL, display a Continue verification link to the applicant using the URL exactly as returned.
{
"data": {
"id": "10000000-0000-4000-8000-000000000042",
"entity_type": "person",
"reference": "applicant-0042",
"status": "action_required",
"status_reason": null,
"person_id": null,
"created_at": "2026-11-01T12:00:00Z",
"updated_at": "2026-11-01T12:01:00Z",
"actions": [
{
"id": "20000000-0000-4000-8000-000000000042",
"type": "open_url",
"status": "available",
"url": "https://example.invalid/hosted/example",
"expires_at": "2026-11-01T12:30:00Z"
}
]
}
}
The example URL is a placeholder. Treat an actual hosted URL as a secret for that applicant. Keep it out of logs, analytics, and support tickets. Only your server needs the Graph API key.
If the action is expired, its URL is null. Send POST /entity_onboarding/{id}/actions/{action_id}/refresh with the onboarding ID and the action’s own id. Use the URL returned in the updated action. If Graph returns HTTP 409, fetch the onboarding again before offering another link.
3. Wait for the person ID
Listen for Entity onboarding events, or keep fetching the onboarding. Returning from the hosted page is a cue to check its state. Wait for completed and a populated person_id before proceeding.
| Status | What your integration should do |
|---|---|
pending | Save the onboarding ID. Fetch it again while Graph prepares the next step. |
action_required | Inspect actions. Present an available link to the applicant, or refresh an expired action. |
processing | Wait for Graph to finish verification and link the person. Use webhooks or poll the same ID. |
completed | Save person_id and use it for the next API request. |
failed | Stop polling. Read status_reason when present. This onboarding is terminal. |
{
"data": {
"id": "10000000-0000-4000-8000-000000000042",
"entity_type": "person",
"reference": "applicant-0042",
"status": "completed",
"status_reason": null,
"person_id": "30000000000040008000000000000042",
"created_at": "2026-11-01T12:00:00Z",
"updated_at": "2026-11-01T12:07:00Z",
"actions": []
}
}
In this example, pass 30000000000040008000000000000042 as person_id when you request a bank account. Use the same organisation and environment. The account has its own eligibility requirements and issuance outcome. Follow Issuing a USD Account to track it.
Try it with a test key
Use the same base URL and your organisation’s test-mode key. Send this body to POST /entity_onboarding, fetch the onboarding, then open its available link in a browser. On the hosted test page, select Complete test onboarding. Opening the page alone leaves the onboarding in progress.
{
"entity_type": "person",
"reference": "test-applicant-0042",
"sandbox_scenario": "success"
}
sandbox_scenario | How to exercise it | Expected result |
|---|---|---|
success (default) | Open the available link and submit the form. | Graph returns completed and a synthetic test person ID. |
rejected | Start with a new reference, open the available link, and submit the form. | The onboarding becomes failed. No person is created. |
expired_link | Start with a new reference. Refresh the expired action, open the replacement link, and submit the form. | The replacement can complete the onboarding successfully. |
The simulator uses no real documents, provider checks, or live Identity link. A refreshed test link invalidates its previous generation. Omit sandbox_scenario from live requests.

