Skip to main content
Version: 11.3.0

Directory Image Writeback

Directory Image Writeback sends the images captured during an Affirm verification — selfies, document captures, and cropped face extracts — to a destination you control, without keeping the images in HYPR.

The write itself is performed by a Code Customization script you author, so the destination is whatever that script calls: a directory such as Microsoft Entra ID or Okta, an internal HR or records system, or any HTTP API. HYPR collects the images, hands them to your script, and records the result.

This supports privacy-by-design and data-minimization requirements. HYPR stores no copy of the images once the verification completes; the only record it keeps is a per-user timestamp used to enforce the rotation interval.

Available in 11.3

Directory Image Writeback is a new feature in HYPR 11.3, and tenant enablement is required — coordinate with your HYPR representative for activation. See the Feature Flags Reference for the corresponding flag.

How it works

  1. A requester completes a verification flow that has Directory Image Writeback enabled.
  2. HYPR gathers every image captured by the flow's Photo ID and Liveness step and Document and Biometric step.
  3. If a rotation interval is set and this user was written back within that window, HYPR skips the write and records it.
  4. Otherwise HYPR invokes your USER_DIRECTORY_IMAGE_WRITEBACK Code Customization, passing the images Base64-encoded.
  5. Your script writes them to the destination and returns an outcome. HYPR records the result in the Audit Trail.
Writeback never changes the verification outcome

A writeback that fails — because the destination is unreachable, the credentials are rejected, or the script returns a failure — is logged and audited, and the requester's verification result stands. Treat the Audit Trail as the source of truth for whether an image reached its destination.

Writing images out, and reading them in

The Image Directory section of a verification flow holds two independent settings, and it is easy to reach for the wrong one:

SettingDirectionPurpose
Custom Directory SourceReadsFetches the user's existing reference image from your directory, to compare a live selfie against. Configured with a USER_DIRECTORY_FOR_IMAGE_REPOSITORY_SOURCE customization and used by the Photo ID and Liveness Capture step. See Liveness-Only (Anchor Image)
Custom Writeback DirectoryWritesSends the images this verification captured out to your directory. The subject of this page

The two are unrelated: you can run either on its own, or both on the same flow.

Step 1 — Create the writeback customization

Create a Code Customization of type USER_DIRECTORY_IMAGE_WRITEBACK — listed as User Image Writeback Directory in the customization type list. Everything about the destination — its URL, its authentication, and the attribute the image lands in — lives in this script and its attributes. See Create a Customization.

A saved writeback customization. The code runs read-only until you select Edit Mode; Test runs it against input you supply. Attributes are managed in the panel on the right.

Step 2 — Enable it on the verification flow

A registered customization does nothing until a flow points at it. Write and test the script first — the sections below cover what it receives, the attributes it reads, and how to test it — then come back here to switch it on:

  1. Open Verification Flows and select the flow.
  2. In the left navigation pane, expand Advanced Customization and select Image Directory.
  3. Under Custom Writeback Directory, select your customization.
  4. Set the Writeback Rotation Interval, then save the flow.

Left navigation pane of a verification flow, with Image Directory selected under Advanced Customization.

The Image Directory section. Writeback draws on both the Document and Biometric Verification step and the Photo ID and Liveness Capture step, so either one produces images to send.

The other drop-down in this section

Custom Directory Source beside it is the reading half, and writeback does not need it. If you want it too and the drop-down is empty, create a User Image Directory Source customization first — see Configure a custom image repository.

Writeback Rotation Interval

The rotation interval is the minimum time before the same user's images are written again. Enter a value and choose its unit — days, weeks, months, or years.

Set it to 0 to write after every verification. With any higher value, HYPR compares the last successful writeback for that user on that flow and skips the write while the window is open, which suits a flow that users re-verify often but whose stored image only needs refreshing occasionally.

Retry behavior is set by HYPR, not per flow: a failed attempt is retried up to three times with a short pause between attempts, and a retry is triggered both by a thrown error and by a script that returns FAILURE.

What your script receives

The script's handle function is called once per verification with this input:

FieldTypeDescription
loginIdentifierStringThe requester's login identifier
workflowIdStringThe verification instance that produced the images
imagesArrayOne entry per captured image, described below

Each entry in images carries:

FieldTypeDescription
sourceTypeStringWhich step and capture the image came from — see the values below
imageBytesStringThe image, Base64-encoded
imageFormatStringImage format, for example jpeg or png
documentTypeStringThe document type reported for a document capture, for example passport or driving_licence. Omitted for selfies
isCroppedBooleantrue for a cropped face extract, false for a full-frame capture

sourceType is one of:

ValueProduced by
PHOTO_ID_AND_LIVENESS_SELFIEPhoto ID and Liveness — the selfie
PHOTO_ID_AND_LIVENESS_DOCUMENTPhoto ID and Liveness — the document
DOCUMENT_AND_BIOMETRICS_SELFIEDocument and Biometric — the selfie
DOCUMENT_AND_BIOMETRICS_DOCUMENT_FRONTDocument and Biometric — primary document, front
DOCUMENT_AND_BIOMETRICS_DOCUMENT_BACKDocument and Biometric — primary document, back
DOCUMENT_AND_BIOMETRICS_DOCUMENT_SECONDARY_FRONTDocument and Biometric — second document, front
DOCUMENT_AND_BIOMETRICS_DOCUMENT_SECONDARY_BACKDocument and Biometric — second document, back

Return { "outcome": "SUCCESS" } when every image has been written, or { "outcome": "FAILURE" } to have the attempt retried. Returning { "error": "…" } is also treated as a failure and puts your message in the audit record.

Attributes

Keep the destination's address and credentials in customization attributes rather than in the script body, so the same script can move between environments unchanged. You choose the attribute names and read them with ctx.getAttribute().

The example below uses two:

AttributeExample valuePurpose
IMAGE_WRITEBACK_ENDPOINTdirectory.example.comHost of the API that receives the images
API_TOKEN(the token issued to your integration)Bearer token presented on each request

Add whatever else your destination needs — a tenant identifier, an API version, the name of the target attribute — as further attributes. Changing an attribute takes effect on the next verification, with no edit to the script.

Adding an attribute. Key is the string you pass to ctx.getAttribute(); the value is entered as a secret.

Saved attributes are listed with their values masked, so record any credential somewhere you can retrieve it. To change one, replace the value rather than reading it back.

The two attributes this example needs, saved and masked.

Permissions

The credential in API_TOKEN — or whatever your script authenticates with — has to be allowed to write the image attribute on another user's record, because the script acts on the requester's behalf rather than as the requester. When you provision it:

  • Grant only the write scope the destination requires for that one attribute. Writeback never reads user records, so read access beyond what the write call needs is unnecessary.
  • Scope the credential to the population that goes through the flow, if your destination supports scoping.
  • Prefer a credential you can rotate independently of other integrations, and rotate it by updating the attribute.
  • Confirm your destination accepts the image size and format your flow produces before enabling writeback on a live flow.

For the exact permission or scope name, follow your directory vendor's documentation for writing a user's photo or a binary user attribute.

Example

A minimal writeback that posts each image to an endpoint and fails the attempt on any non-success response:

function handle(inputJson) {
const input = JSON.parse(inputJson);

ctx.log("FINE", "writeback for " + input.loginIdentifier + ", images=" + input.images.length);

for (const img of input.images) {
const res = ctx.httpPost(
`https://${ctx.getAttribute("IMAGE_WRITEBACK_ENDPOINT")}/users/${input.loginIdentifier}/photo`,
{
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${ctx.getAttribute("API_TOKEN")}`
},
JSON.stringify({
sourceType: img.sourceType,
imageBytes: img.imageBytes,
imageFormat: img.imageFormat,
documentType: img.documentType,
isCropped: img.isCropped
})
);

const response = JSON.parse(res);
if (response.statusCode < 200 || response.statusCode >= 300) {
return { outcome: "FAILURE" };
}
}

return { outcome: "SUCCESS" };
}

handle(ctx.getInputAsJson());

The request body and headers depend on the API you target; adapt them to your destination. For the ctx object and the runtime it executes in, see Writing Affirm Code Customizations.

Before you enable it on a live flow

Confirm the flow captures images. Writeback sends what the Photo ID and Liveness step and the Document and Biometric step produce. A flow with neither step has nothing to send, and each verification records a failure giving that reason.

Exercise the script in Test mode. Test mode surfaces errors that a live run only writes to the logs, and it confirms every attribute your code reads is present and spelled the way the script expects. See Edit and test a customization.

Send one real verification through first. Run a single verification against the flow and confirm both the destination record and the AFFIRM_WRITEBACK_SUCCESS entry in the Audit Trail before enabling writeback for everyone.

Troubleshooting

Each outcome below appears in the Audit Trail with its reason:

EntryWhat it meansWhat to do
AFFIRM_WRITEBACK_SKIPPED — within rotation windowThis user's images were written within the rotation intervalExpected. Shorten the rotation interval if you need writes more often
AFFIRM_WRITEBACK_FAILURE — no images availableThe verification produced no imagesConfirm the flow includes a capture step and that the requester completed it
AFFIRM_WRITEBACK_FAILURE — missing writeback imageOne expected capture could not be retrieved. The remaining images are still sentCheck that the step it came from completed
AFFIRM_WRITEBACK_FAILURE — code customization returned FAILUREYour script returned FAILURE, typically after a non-success response from the destinationCheck the destination's response, the token in your attributes, and the write permission on the target attribute
AFFIRM_WRITEBACK_FAILURE — with an error messageThe script threwReproduce it in Test mode; add ctx.log() calls around the failing call

Because a writeback never changes the verification outcome, none of these are visible to the requester or the approver — the Audit Trail is where you see them.

Approver-visible face comparison

When Directory Image Writeback is configured, the face-from-video extracted during the requester's liveness capture becomes visible to the approver in the Scorecard's Photo ID and Liveness section — side by side with the face extracted from the requester's submitted document.

Photo ID and Liveness panel showing the face extracted from the document (left) and the face extracted from the liveness video (right). The face-from-video render depends on Directory Image Writeback being active for the workflow.

Without Directory Image Writeback, the document face remains visible but the face-from-video does not render in the Scorecard. See What the Approver Sees for the full Scorecard flow.

Audit and observability

Every writeback decision reaches the Audit Trail:

EventRecorded when
AFFIRM_WRITEBACK_TRIGGEREDHYPR is about to hand images to the script; lists the source types being sent
AFFIRM_WRITEBACK_SUCCESSThe script reported success
AFFIRM_WRITEBACK_SKIPPEDThe write was skipped, with the reason — for example, the user is inside the rotation window
AFFIRM_WRITEBACK_FAILUREAn attempt failed, with the reason: the script returned a failure, threw an error, an expected image was missing, or no images were available

A verification with no images available to send records a failure with that reason rather than a success. See Audit Trail for the canonical event reference.

Use cases

  • Employee onboarding — capture identity documents and a selfie during onboarding verification and write them to the employee's record in your directory, with no HYPR retention
  • Periodic re-verification with a capped image refresh — re-verify quarterly while refreshing the stored image annually, using the rotation interval
  • Privacy-regulated jurisdictions — combine with short-retention settings to minimize how long images exist anywhere