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.
A code customization script that you write performs the write, so the destination is whatever that script calls: a directory such as Microsoft Entra ID or Okta, an internal records system, or any HTTP API. HYPR collects the images, hands them to your script and records the result.
Writeback delivers the images to a destination your organization controls, where your own retention rules apply. For how HYPR processes and retains biometric data, see the HYPR Affirm Biometric Data Policy and Consent.
For Document and Biometric Verification, the flow's data retention setting controls how long that step's data is stored after a session completes. See Biometric Data and the Privacy Notice.
Directory Image Writeback is new in HYPR 11.3. Contact your HYPR representative to enable it for your tenant.
How It Works
Writeback runs as follows:
- A verification of a flow that has Directory Image Writeback enabled is approved, by the approver or by automated approval.
- HYPR gathers every image captured by the flow's Photo ID and Liveness Capture step and Document and Biometric Verification step.
- If a rotation interval is set and this user was written back within that window, HYPR skips the write and records it.
- Otherwise, HYPR runs your
USER_DIRECTORY_IMAGE_WRITEBACKcode customization and passes it the images, Base64-encoded. - Your script writes them to the destination and returns an outcome. HYPR records the result in the Audit Trail.
A writeback can fail because the destination is unreachable, the credentials are rejected or the script returns a failure. A failed writeback 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. The following table compares them.
| Setting | Direction | Purpose |
|---|---|---|
| Custom Directory Source | Reads | Fetches 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 Directory | Writes | Sends the images this verification captured out to your directory. Described on this page |
You can use either setting on its own, or both on the same flow.
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. The script and its attributes hold everything about the destination: its URL, its authentication and the attribute the image lands in. See Create a Customization.
A saved writeback customization. The code is read-only until you turn on Edit Mode, and Test runs it against input you supply. Attributes are managed in the Attributes panel.
What Your Script Receives
On each writeback attempt, your script receives the requester's loginIdentifier, the workflowId of the verification and an images array with one entry per captured image. Each entry carries a sourceType naming the step and capture it came from, the Base64-encoded imageBytes, the imageFormat, the documentType of a document capture and isCropped, which is true for a cropped face extract. For the field types and every sourceType value, see Code Customizations: Image Writeback.
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 later on this page uses the following attributes.
| Attribute | Example value | Purpose |
|---|---|---|
IMAGE_WRITEBACK_ENDPOINT | directory.example.com | Host of the API that receives the images |
API_TOKEN | (the token issued to your integration) | Bearer token presented on each request |
Add anything else your destination needs, such as a tenant identifier, an API version or 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, must be allowed to write the image attribute on another user's record. The script acts on the requester's behalf rather than as the requester. When you provision the credential:
- 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
The following minimal writeback 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 Writeback on a Live Flow
Confirm the flow captures images. Writeback sends what the Photo ID and Liveness Capture step and the Document and Biometric Verification step produce. A flow with neither step has nothing to send, and each approved 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 you enable writeback for everyone.
Enable Writeback on the Verification Flow
A registered customization runs only when a verification flow uses it. After you write and test the script, enable it on the flow:
- Open Verification Flows.
- Select the flow.
- In the left navigation pane, expand Advanced Customization and select Image Directory.
- From the Custom Writeback Directory drop-down, choose your customization.
- Set the Writeback Rotation Interval.
- 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.
Custom Directory Source is the reading half of this section, and writeback does not need it. To use it as well when its drop-down is empty, first create a User Image Directory Source customization. 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 approved 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. This suits a flow that users re-verify often but whose stored image only needs refreshing occasionally.
HYPR sets the retry behavior; it is not set per flow. Each writeback is attempted up to three times in total, with a short pause between attempts. Both a thrown error and a script that returns FAILURE trigger a retry.
Troubleshooting
Each of the following outcomes appears in the Audit Trail with its reason.
| Entry | What it means | What to do |
|---|---|---|
AFFIRM_WRITEBACK_SKIPPED — within rotation window | This user's images were written within the rotation interval | Expected. Shorten the rotation interval if you need writes more often |
AFFIRM_WRITEBACK_FAILURE — no images available | The verification produced no images | Confirm the flow includes a capture step and that the requester completed it |
AFFIRM_WRITEBACK_FAILURE — missing writeback image | One expected capture could not be retrieved. The remaining images are still sent | Check that the step it came from completed |
AFFIRM_WRITEBACK_FAILURE — code customization returned FAILURE | Your script returned FAILURE, for example after a non-success response from the destination | Check the destination's response, the token in your attributes and the write permission on the target attribute |
AFFIRM_WRITEBACK_FAILURE — with an error message | The script threw | Reproduce it in Test mode; add ctx.log() calls around the failing call |
Because a writeback never changes the verification outcome, the requester and the approver see none of these entries. You see them in the Audit Trail.
Approver-Visible Face Comparison
The approver's Scorecard shows the face-from-video extracted during the requester's liveness capture in its Photo ID and Liveness section. It appears side by side with the face extracted from the requester's submitted document. This comparison view does not depend on Directory Image Writeback.
Photo ID and Liveness panel showing the face extracted from the document (left) and the face extracted from the liveness video (right).
See What the Approver Sees for the full Scorecard flow.
Audit and Observability
HYPR records every writeback decision in the Audit Trail. The following table lists the events.
| Event | Recorded when |
|---|---|
AFFIRM_WRITEBACK_TRIGGERED | HYPR is about to hand images to the script; lists the source types being sent |
AFFIRM_WRITEBACK_SUCCESS | The script reported success |
AFFIRM_WRITEBACK_SKIPPED | The write was skipped, with the reason — for example, the user is inside the rotation window |
AFFIRM_WRITEBACK_FAILURE | An attempt failed, with the reason: the script returned a failure, threw an error, an expected image was missing or no images were available |
See Audit Trail for the canonical event reference.
Use Cases
Writeback supports the following scenarios:
- New account setup: Capture identity documents and a selfie during a user's first verification, then write them to the user's directory record
- 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
Related
- Affirm Customizations → Image Writeback — the code customization contract
- Liveness-Only (Anchor Image) — the reading half of the Image Directory section, for comparing a selfie against a stored reference image
- Writing Affirm Code Customizations — the
ctxobject, attributes and testing - Audit Trail — writeback lifecycle events
- Data Retention — the data retention setting for Document and Biometric Verification
- Biometric Data and the Privacy Notice — which steps capture images and how long each copy is kept