Inyo

Server-to-Server Verification

When you already have a capture UI — or you are verifying images that were collected earlier — post them directly and get the result back in the response. No session, no widget, no customer link.


Create a Verification

Endpoint: POST /v1/verifications
Authentication: Bearer token with the verifications scope
Content-Type: multipart/form-data

curl --request POST \
  --url https://{FQDN}/v1/verifications \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form user_ref=user-123 \
  --form [email protected] \
  --form [email protected] \
  --form [email protected]

Returns 201 with the same normalized result the widget produces.

Form Fields

FieldTypeRequiredDescription
user_reftextYesYour identifier for the person being verified
front_imagefileYesFront of the document — the photo page of a passport, the front of a card
back_imagefileNoBack of the document. For US licenses and state IDs this carries the barcode
selfie_imagefileNoOmit to run document checks only — see Document-only verification
data_checktextNotrue compares extracted data against prefill
prefilltextNoA JSON string with the same schema as session prefill

Note that prefill here is a JSON string inside a multipart field, not a nested object:

  --form 'prefill={"first_name":"Ana","last_name":"Silva","date_of_birth":"1988-03-04"}' \
  --form data_check=true

Send the Back of the Card

For US driver's licenses and state IDs, the back carries a PDF417 barcode encoding the cardholder data. Inyo decodes it on receipt, and because the barcode is self-verifying — the symbology carries its own error correction — it outranks visual-zone OCR for the fields it contains. Decoding is rotation-independent, so an upside-down back still reads.

A missing, unreadable, or non-barcode back is a silent no-op: OCR values stand and no check changes. There is no downside to sending it, and a measurable accuracy gain when it decodes. Passports carry a machine-readable zone on the photo page instead, so front_image alone is sufficient for them.


Document-only Verification

Omit selfie_image to verify the document without biometrics. The document checks run — readability, format, expiry, authenticity, jurisdiction — and no face checks appear in checks[].

One consequence to plan for: a document-only verification carries no biometric score. If you have a review threshold configured, there is nothing for it to compare against, and an unmeasured verification is treated as unmeasured, not confident — so it routes to in_review rather than auto-approving. Send a selfie, or leave the review threshold unset, if you need document-only verifications decided synchronously.


in_review Is Not a Final Answer

POST /v1/verifications returns the result synchronously, but a 201 response does not guarantee a terminal decision. status can be in_review, meaning an analyst has yet to decide.

This happens when you have configured a review threshold, or when held rejections are enabled and the checks rejected the document. With neither configured, every verification comes back decided.

When it does happen:

ChannelBehavior
WebhookWith a webhook_url configured, the decided result is POSTed to it like any other result — see Result notifications
PollingGET /v1/sessions/{session_id} returns the live status and result, updated in place, with result.manual_review naming who decided and why

Use session_id from the response body as the identifier for both. No webhook is sent for the original synchronous answer — the 201 already delivered it. See Manual Review for the full picture.


Error Responses

StatusCauseHow to handle
401 / 403Missing or invalid token, or a token without the verifications scopeSee Authentication
422prefill is not valid JSON or violates the prefill schema (including document-number format)Fix the payload — the detail names the problem
422data_check=true with no prefillProvide a prefill payload to compare against
502The verification service was unavailableTransient — retry. This is an infrastructure failure, not a decline. Do not treat it as a negative outcome for the customer

Widget or Server-to-Server?

Both entry points share the same pipeline and the same result shape, and your thresholds, review routing, accepted jurisdictions, and enrichment options apply identically. Two settings are session-level by nature and have no effect here: the allowed document types and prefill.document_type locking both constrain what the widget offers a customer, so on this endpoint the document type is simply whatever the images turn out to be.

The differences that matter:

Hosted widgetServer-to-server
Capture qualityGuided, with live framing and glare feedbackYours to control
Failed captureCustomer is coached and retriesReturns a result; retrying is your decision
Result deliveryWebhook or signed redirectThe response body, plus later changes by webhook
Presentation-attack defenseSame checksSame checks, but with no live capture context to draw on
Compliance evidenceInyo retains the guided capture and optional selfie videoOnly the images you send

The retry difference is about coaching a live customer — it does not change what your configuration means or how the decision is reached.


Next Steps