Skip to main content

The full path

1

Verify connectivity and credentials

A 200 confirms the base URL and api-key are correct. A 401 means an invalid key or the wrong environment. Check the status code, not the body: version numbers change and are not part of your contract.
2

Prepare the image

Capture or receive a JPEG, resize it to the recommended dimensions, and encode it as base64 with no prefix.
3

Call POST /inference

A single JSON body with image, info, and logAnonymity.
4

Apply the decision rule

status === 200 && spoofing === false approves. Everything else does not.

Image requirements

Between 224 × 224 and 640 × 480 there is no error — but there is less detection. Several analysis layers need resolution to work. A small image passes validation, gets processed, and returns 200 with fewer layers looking at it. This is the most expensive silent failure in this integration: you will not see it in your logs, you will see it in your fraud numbers.
If your mobile app already captures at higher resolution, resize on the server before sending. Sending 4,000 × 3,000 pixels does not improve detection; it only multiplies response time and payload size.

Encoding to base64

On Linux, -w 0 suppresses the line breaks base64 inserts every 76 characters. Without that flag the string arrives split and the service cannot decode it.

Request body

Always send a non-empty info with an identifier that lets you reconstruct the case: a case number, an onboarding session id, whatever your business uses. It comes back in the response and is what ties a VU transaction to a user in your system when something needs investigating.

The info field in the response

This is where most integrations break. info is not always the same type: Resolve it in one place and never read info directly:
In Java, type info as Object, never as String. This is the number-one cause of integration failures: the mapping works through every test — where info comes back as a string — and explodes in production the first time a case carries diagnostics and info arrives as an object. The same applies to any strict deserializer.

Timeouts and retries

Never retry a response with spoofing: true. It is a verdict, not an error. Retrying until you get a different result turns your antifraud control into a false-approval generator.

Before going to production

An integration is ready when you can answer yes to all of these:
  1. The decision is written in the positive: status === 200 && spoofing === false.
  2. No branch decides on errorCode, values, confidence, or info.
  3. info is read through a single resolver that handles object, string, and null.
  4. In typed languages, info is declared as a dynamic type or Object.
  5. imageQuality and its subfields are read as optional; no key is assumed present.
  6. Images are sent at 640 × 480 with JPEG quality ≥ 95.
  7. A pre-check discards images smaller than 224 × 224 before spending a call.
  8. base64 is generated with no data: prefix and no line breaks.
  9. The timeout is set to 30 s.
  10. Retries are capped at 2 and limited to 499 and non-deterministic 500s.
  11. Every transaction id is logged, along with the environment and a timestamp.
  12. The api-key lives only in the backend, in a secret manager, not in source.
  13. The team knows that 422 No Face Detected is a capture problem and 422 Bad request is a code problem.

Responses

Next: what every response field means and how to read the diagnostics.
Last modified on September 9, 2026