How it fits together
Four pieces work together:- A profile is the customer record in Minerva, created through the Profiles API.
- An IDV session is one verification attempt tied to a profile. It carries the capture flow (consent, liveness and document captures, questionnaire) and the review outcome.
- Review is the decision layer. Most sessions pass without a human; some are held for an analyst in your Minerva workspace to accept or reject.
- Webhooks tell your systems when a session changes state, so you do not have to poll.
Before you begin
- You need an application API key for your workspace. Create one from the Developers page; API Keys has the walkthrough. Keys are server-side credentials, so never ship one in a browser or a mobile app.
- You need a profile for the customer. If it does not exist yet, create it first (Step 1).
- Every endpoint in this guide uses the base URL
https://api.gominerva.com/idv/v1and authenticates withAuthorization: Api-Key <YOUR_API_KEY>.
Identity verification is rolling out across Minerva workspaces. Contact
support@gominerva.com to enable it for your workspace. The API surface may
still change while the rollout completes.
Step 1: Create the profile
Every verification session belongs to a Minerva profile. You have two options:- Create the profile on its own with
POST https://api.gominerva.com/clm/v1/profiles, then create the session yourself with the rest of this guide. See Create a profile. - Create and onboard the profile in one call with
POST https://api.gominerva.com/clm/v1/onboarding/profiles, using anonboardingblock to enable screening, identity verification, or both. See Create and screen a profile.
- Enabling IDV requires an email address on the profile and a workflow: either an explicit
workflowIdor your workspace’s default. sequenceis one ofscreening_first(the default),idv_first, orparallel.- When IDV onboarding is enabled, Minerva starts the verification session for the profile as part of the run. The rest of this guide covers the explicit flow, where your backend creates the session and delivers the invite itself.
Step 2: Create the IDV session
Create a verification session for the profile:profile_idis required. The profile must already exist in your workspace: a missing profile returns400 idv_profile_not_found, and an unavailable profiles service returns503 idv_profile_lookup_unavailable.workflowpicks a preset flow:liveness_and_id,liveness_only, orid_only. You can instead pass aworkflow_idyou configured, pass an inlinestepsmanifest, or omit all three to use your workspace’s default workflow.idempotency_keyis an optional retry key (1 to 160 characters of letters, digits, and.,_,:,-). A retry with the same key and the same request returns the original session instead of creating a second one; reusing the key for a materially different request returns409 idv_session_idempotency_conflict.
201 with the session, a one-time session_token, and token_expires_at:
session_token is the end-user capture credential for this session. It is surfaced only once, expires (15 minutes by default), and cannot be recovered or rotated; an idempotent replay returns it empty on purpose.
Step 3: Deliver the verification flow
Choose one of two delivery modes for the session you just created.Email invite
- The recipient is always the email address on the linked profile, resolved at send time. The request does not accept a recipient. A profile without an email returns
422 idv_profile_email_missing. - Success is a
202withinvited: trueandinvite_expires_at. Adelivery_stateofsentmeans the email provider durably accepted the message. - The emailed link is valid for 72 hours by default and stays reusable within that window, so a customer can reopen the email or continue on another device.
- Pass an
Idempotency-Keyheader to make email retries safe (direct links ignore it; without a header Minerva generates its own key). A replay with the same key never sends a second email; it reports the delivery’s durable state instead:202withdelivery_state: "sent"once the provider has accepted the message, or502 invite_delivery_failedotherwise. While a send is still in flight, including an ambiguous provider outcome, a different key is refused with409 idv_state_conflict; retry once it settles. After the earlier send has settled (delivered or terminally failed), a new key can replace it and email again. - Optional presentation fields:
localeandorg_name(which overrides the theme company name in the email).
Direct link
- The response is a
200withverify_urlandinvite_expires_at. Hand the link to the user immediately: redirect to it or open it in a web view. - Direct links work only with application keys. Dashboard-authenticated callers receive
403 idv_direct_invite_forbidden. - The link is single-use and expires within 15 minutes (900 seconds, and the lifetime cannot be raised).
- The one-time credential sits in the URL fragment (
#code=...), which browsers never send to servers and Minerva never logs. Treat the whole URL as a secret. - If Minerva cannot construct a secure public link, the request fails closed with
503 idv_direct_invite_unavailable.
Which mode should you use?
An integration cannot mint an arbitrary long-lived link. Treat the email
invite as the user-delivery path and the direct link as the immediate-handoff
path for a user who is ready right now.
What the customer sees
Verification runs on Minerva’s white-label page atidv.gominerva.com, styled with the theme attached to the session. The customer:
- Opens the link from the email, or arrives through your handoff.
- Reviews and accepts the consent notice.
- Completes the capture steps, for example a liveness selfie and photos of an identity document.
- Submits the session for assessment.
Step 4: Track progress
ReadGET /sessions/{sessionId} with your application key, or subscribe to webhooks and let Minerva push transitions to you (recommended for production). A session carries two independent state axes.
Flow status
Review status
The capture endpoint
GET /sessions/{sessionId}/status belongs to the hosted
verification page: it accepts only the session’s capture or invite credential,
not your application API key. Track backend progress from GET /sessions/ {sessionId}, GET /sessions?profile_id=..., or webhooks.Step 5: Cancel a session
- Cancellation is irreversible and moves the session to
canceled. - It consumes the capture token and the invite, so the link stops working for further capture.
- Re-canceling an already canceled session is a no-op, not an error.
- A session that is currently being assessed cannot be canceled: the call returns
409 idv_state_conflict(the same code covers other terminal states). - The optional
reasonis recorded internally and is never shown to the customer.
Step 6: Read results and review outcomes
Structured results
GET /sessions/{sessionId}/data returns the authorized, decrypted results for a session:
- The document record: type, issuing country and subdivision, and confidence.
- OCR field values with per-field confidence.
- Questionnaire answers, with the step and question each answer belongs to.
- Any mismatch details between the captured data and the profile.
- Every access, success or denial, is written to an audit log before the response is returned. If the audit write fails, the request fails closed with no data.
- The endpoint is available to application keys and in-scope dashboard users only. It is never reachable with a session’s capture credential.
Review
Most sessions complete without a human. A clean assessment passes automatically (automatic_pass) and the session emits idv.session.approved. When the assessment will not auto-decide, the session lands on requires_review and waits for a reviewer in your Minerva workspace.
Reviewers can escalate a session (escalation, which keeps it open) or make the terminal decision: accepted or rejected. You can also record decisions from the API:
409 idv_review_terminal, and inadmissible transitions return 409 idv_review_invalid_transition.
The outcome also flows to the profile: profile_status_updated fires with the new screening status, and when the profile has an onboarding run, profile_onboarding.completed fires with the outcome so your onboarding flow can finish. See Webhooks for the exact values.
Worked example: email invite
An end-to-end walkthrough for one customer, Alex Morgan.- Create the profile with the Profiles API:
- Create the IDV session for that profile:
- Send the invite email:
- Track progress with
GET /sessions/{sessionId}or webhooks, and read the results withGET /sessions/{sessionId}/datawhen the assessment is done.
Worked example: direct link
Use the same first two calls as the email example, then request the link back and hand it over immediately:verify_url or open it in your app’s web view right away. The link is single-use and stops working within 15 minutes, so do not queue it, email it, or store it for later.
Web and mobile integration walkthrough
The common integration looks like this: Walking through it:- The customer taps a button in your web or mobile app. The tap calls your backend, never Minerva directly.
- Your backend creates the profile (or reuses an existing one), creates the IDV session, and sends the email invite.
- The customer receives the email, opens the verification page, consents, completes the capture steps, and submits.
- Minerva assesses the session. Your backend receives IDV webhooks:
idv.session.completedwith the outcome (idv.session.approved,idv.session.requires_review, oridv.session.failed), andidv.document.capturedfor each uploaded artifact. - Update the customer’s experience: show something like “verification received, we are finishing your setup.” Never surface flags, review states, or analyst details to the customer.
- If the session was held for review, an analyst reviews it in your Minerva workspace and marks the profile accepted or rejected. That disposition closes the loop with
profile_onboarding.completed(andprofile_status_updated), your signal to continue or stop the onboarding flow.
idv kind sends every meta value as a string, so booleans arrive quoted ("true"). See Webhooks for the full event catalog, payload shapes, retry schedule, and dedupe guidance.
Errors and limits
Errors use one envelope:{"error": {"code": "...", "message": "..."}}, with Cache-Control: no-store. Common codes:
- 400: returned as
idv_profile_id_requiredoridv_profile_id_invalidwhenprofile_idis missing or malformed on session create. - 400: returned as
idv_profile_not_foundwhen the profile does not exist in the calling workspace. - 400: returned as
schema_validation_failedwhen the request body fails schema validation. - 401: returned as
missing_authenticationwhen the request carries no credentials, or asunauthorizedwhen the key is rejected. Responses never reveal whether an object exists. - 403: returned as
idv_direct_invite_forbiddenwhendelivery: "none"is requested without an application principal. - 404: returned as
idv_session_not_foundwhen the session does not exist in the calling workspace. - 409: returned as
idv_state_conflictwhen the session is not in a state that allows the action, for example canceling while the assessment runs, or a new invite uses a differentIdempotency-Keywhile a send is still in flight. - 409: returned as
idv_session_idempotency_conflictwhen an idempotency key was reused for a materially different create. - 409: returned as
idv_invite_conflictwhen the invite state changed before the request completed; retry the request. - 409: returned as
idv_review_terminalwhen a review decision was submitted for a session that is already accepted or rejected. - 409: returned as
idv_review_invalid_transitionwhen the review decision is not admissible from the session’s current review state. - 422: returned as
idv_profile_email_missingwhen an email invite was requested but the linked profile has no email address. - 502: returned as
invite_delivery_failedorinvite_delivery_retryingwhen the email provider could not confirm delivery. The invite stays valid; retry the invite call. - 503: returned as
idv_profile_lookup_unavailablewhen the profiles service was unavailable and the request failed closed. - 503: returned as
idv_direct_invite_unavailablewhen no secure public verify base is available for a direct link.
- The capture token (
session_token) lives 15 minutes by default. - Email invites live 72 hours by default; direct links at most 15 minutes.
- The sessions list returns 50 records per page by default; the workflow and theme lists return 20. Every list endpoint caps at 100 (larger values are clamped).
- Each workspace can keep up to 10 destinations by default. Enterprise customers can request more.
Security
- Keep application API keys server-side. The hosted verification page authenticates the customer with its own capture or invite credential, so your client apps never need a key.
- Validate
x-webhook-keyon every delivery before processing the body, and acknowledge quickly with a small2xxresponse. - Read verification results only through the audited
GET /sessions/{sessionId}/dataendpoint, and store what you need under your own data-protection policy. Document images and OCR text are sensitive personal data. - Never surface review states, flags, or analyst details to the customer; the customer-facing flow deliberately does not expose them.
- Use a separate application per environment, and rotate or deactivate keys when integrations change.
Related documentation
- API Keys: create an application key and configure webhooks from the Developers page.
- Webhooks: the delivery contract, payload shapes, and retry schedule.
- Screening Integration Guide: interpret screening results alongside identity verification.
- Profiles: the customer record an IDV session is tied to.