B. Handling Result Flags
Entrupy provides a flagging mechanism that allows users or integrators to report a potential issue with an authentication result assigned by Entrupy. This system directs the Entrupy support team to review the specific case and resolve it appropriately. Flagging is the preferred method for disputing a result, rather than resubmitting an item, which could incur additional costs.
Flags are typically used when an end-user or the integrating platform believes there might be an error or a need for re-evaluation of an authentication outcome. The ability to allow users to flag via SDK is configurable; for some deployments limiting this function to the platform is a better fit.
Always fetch the latest flag state before taking any action. Confirm that the item is eligible for flagging (is_flaggable) and use the current status to decide whether to show “Flag”, “Clear Flag”, or neither (or present the built-in Flag View via displayFlagViewForItem).
1. Getting Flag Details for a Result
Fetch the flag details for that specific authentication result using its Entrupy ID.
Use getFlagDetailsForResult(withEntrupyID:completionHandler:) (Swift) / getFlagDetailsForResultWithEntrupyID:completionHandler: (Objective-C) to obtain:
- The current flag status (e.g.,
none,flagged,resolved) and any existing flag details (flag_info). - Whether the item is currently eligible to be flagged (
is_flaggable). - The list of supported flag reasons (
supported_flag_reasons) to populate your custom reason picker UI.
The SDK returns a dictionary payload which can be decoded into EntrupyFlagDetails:
flag_status: decodes intoEntrupyCaptureResultStatusFlagsupported_flag_reasons: array ofEntrupyCaptureResultStatusFlagInfo
EntrupyCaptureResultStatusFlag includes:
id: The current flag status (e.g.,none,flagged,resolved).is_flaggable: Whether the item can currently be flagged (true/false).flag_info: OptionalEntrupyCaptureResultStatusFlagInfodescribing the existing flag (only populated when the item is already flagged).
EntrupyCaptureResultStatusFlagInfo includes:
id: The reason identifier. When setting a flag, pass the selected reason’sidasflagReasonIdtosetFlag(...).label: User-facing reason text to display in your selection UI.message: Forsupported_flag_reasonsthis is alwaysnil. This field is populated inflag_status.flag_infowith the user-provided note when an item has already been flagged.
Not all result types are eligible for flagging. It is important to check is_flaggable before attempting to set or clear a flag to avoid errors.
// Swift
import EntrupySDK
// Ensure your class conforms to a delegate or uses a completion handler
// as provided by the SDK for this asynchronous operation.
extension YourViewController {
func fetchFlagDetails(for entrupyID: String) {
EntrupyApp.sharedInstance().getFlagDetailsForResult(withEntrupyID: entrupyID) { details, error in
if let error = error {
let nsError = error as NSError
print("Error fetching flag details for \(entrupyID): \(nsError.localizedDescription) (Code: \(nsError.code))")
return
}
guard let details else {
print("No details or error returned from getFlagDetailsForResult for \(entrupyID)")
return
}
do {
let jsonData = try JSONSerialization.data(withJSONObject: details, options: [])
let parsed = try JSONDecoder().decode(EntrupyFlagDetails.self, from: jsonData)
let statusId = parsed.flag_status.id
let isFlaggable = parsed.flag_status.is_flaggable
print("Flag details for \(entrupyID): Status=\(statusId.description), Flaggable=\(isFlaggable)")
// Existing flag info (populated when the item is currently flagged)
let message = parsed.flag_status.flag_info?.message ?? ""
let reason = parsed.flag_status.flag_info?.label ?? ""
let reasonId = parsed.flag_status.flag_info?.id ?? ""
// Reasons you can present in your custom UI when the user is setting a flag.
// Use the selected reason's `id` as `flagReasonId` when calling `setFlag(...)`.
let supportedReasons = parsed.supported_flag_reasons
switch statusId {
case .none, .resolved:
// If status is 'none' or 'resolved' AND is_flaggable is true -> present 'Flag' option
if isFlaggable {
// Show 'Flag' button
} else {
// Hide buttons
}
case .flagged:
// If status is 'flagged' -> present 'Clear Flag' option
// Show 'Clear Flag' button
break
default:
// Hide buttons
break
}
} catch {
print("Error decoding flag details result for \(entrupyID): \(error)")
}
}
}
}
2. Setting or Clearing a Flag Programmatically
Once you have determined that an item can be flagged (or a flag can be cleared), use the setFlag SDK method.
Recommended sequence (custom UI):
- Call
getFlagDetailsForResult(...)(Section 1) to check status/eligibility and retrievesupported_flag_reasons. - Present your custom UI (reason picker + optional note).
- Call
setFlag(...)when the user submits. - Implement
EntrupyFlagDelegateto handle success/failure callbacks and update your UI.
When calling setFlag(...), provide the Entrupy ID, a boolean indicating the desired flag state (true to set/submit, false to clear), a flagReasonId, and an optional message:
Your view controller adopts EntrupyFlagDelegate so it can submit the request and receive callbacks in one place.
import EntrupySDK
extension YourViewController: EntrupyFlagDelegate {
/// Submits or clears a flag for a given Entrupy result.
///
/// - Parameters:
/// - entrupyID: Unique ID of the authentication result.
/// - setFlagValue: `true` = set flag, `false` = clear flag.
/// - selectedReasonId: Reason `id` selected by the user from `supported_flag_reasons` (used when setting a flag).
/// - existingFlagReasonId: Reason `id` from `flag_status.flag_info.id` (used when clearing a flag).
/// - message: Optional free-form comment.
///
/// Validations include:
/// - Authorization check
/// - Ensuring a valid flag reason ID is provided when setting a flag
func submitOrClearFlag(
for entrupyID: String,
setFlagValue: Bool,
selectedReasonId: String?,
existingFlagReasonId: String?,
message: String?
) {
// Ensure user authorization is valid.
guard EntrupyApp.sharedInstance().isAuthorizationValid() else {
print("User not authorized. Cannot set or clear flag.")
return
}
// Determine the flagReasonId to send (required by the SDK for both set and clear).
let flagReasonIdToSend: String
if setFlagValue {
guard let selectedReasonId, !selectedReasonId.isEmpty else {
print("A valid flag reason ID is required when setting a flag.")
return
}
flagReasonIdToSend = selectedReasonId
} else {
guard let existingFlagReasonId, !existingFlagReasonId.isEmpty else {
print("A valid existing flag reason ID is required when clearing a flag (use flag_status.flag_info.id from getFlagDetailsForResult).")
return
}
flagReasonIdToSend = existingFlagReasonId
}
// Assign delegate before making call.
EntrupyApp.sharedInstance().flagDelegate = self
// Set or clear the flag.
EntrupyApp.sharedInstance().setFlag(
setFlagValue,
forResultWithEntrupyID: entrupyID,
flagReasonId: flagReasonIdToSend,
message: message
)
}
// MARK: - EntrupyFlagDelegate Methods
/// Fires when the SDK successfully sets or clears a flag.
func didFlagResultSuccessfully(
forEntrupyID entrupyID: String,
forRequestedFlag flagValue: Bool
) {
let action = flagValue ? "set" : "cleared"
print("Flag successfully \(action) for Entrupy ID: \(entrupyID)")
}
/// Fires when flag submission fails for any reason.
func didFlagResultFailWithError(
_ errorCode: EntrupyErrorCode,
description: String,
localizedDescription: String,
forEntrupyID entrupyID: String,
forRequestedFlag flagValue: Bool
) {
let action = flagValue ? "set" : "clear"
print("""
Failed to \(action) flag for Entrupy ID: \(entrupyID)
- Error Code: \(errorCode.rawValue)
- Localized Description: \(localizedDescription)
- Description: \(description)
""")
}
}
3. Using the Built-in Flag UI
Recommended: Use Entrupy’s built-in flagging sheet whenever possible. To present it, call displayFlagViewForItem(withEntrupyID:). The SDK handles reason selection, validation, and submission internally; you only need to listen for EntrupyFlagViewDelegate callbacks. For a fuller walkthrough of the delegate workflow, see the Flag View UI guide.
// Swift
import EntrupySDK
extension YourViewController: EntrupyFlagViewDelegate {
/// Presents the Entrupy-provided Flag View UI for a given authentication result.
///
/// - Parameter entrupyID: The unique Entrupy result ID for which the flag UI should be shown.
///
/// Requirements:
/// - User must be authorized (`isAuthorizationValid`)
/// - The SDK handles the UI presentation, you need to set the delegate before calling this method.
func presentFlagView(for entrupyID: String) {
let entrupyApp = EntrupyApp.sharedInstance()
// Ensure Entrupy authorization is valid before proceeding.
guard entrupyApp.isAuthorizationValid() else {
print("User not authorized. Cannot display flag view.")
return
}
// Assign self as delegate to capture flag view events.
entrupyApp.flagViewDelegate = self
// Request SDK to display the flag UI for the specified Entrupy ID.
entrupyApp.displayFlagViewForItem(withEntrupyID: entrupyID)
}
// MARK: - EntrupyFlagViewDelegate
/// Called when the user dismisses the flag view without submitting.
func didUserCancelFlagViewForItem(withEntrupyID entrupyID: String) {
print("User canceled flag operation for Entrupy ID: \(entrupyID)")
}
/// Called when the flag view is successfully displayed on screen.
func didDisplayFlagViewForItem(withEntrupyID entrupyID: String) {
print("Flag view displayed successfully for Entrupy ID: \(entrupyID)")
}
/// Called when the SDK fails to display the flag view.
///
/// This usually indicates an authorization issue, invalid Entrupy ID
func didDisplayFlagViewFailWithError(
_ errorCode: EntrupyErrorCode,
description: String,
localizedDescription: String,
forEntrupyID entrupyID: String
) {
let message = """
Failed to display flag view for Entrupy ID: \(entrupyID)
- Error Code: \(errorCode.rawValue)
- Description: \(description)
- Details: \(localizedDescription)
"""
print(message)
}
/// Called when the user successfully submits a flag from the SDK provided flag UI.
func didUserSubmitFlag(forEntrupyID entrupyID: String) {
print("User submitted flag for Entrupy ID: \(entrupyID)")
}
}
Use delegate callbacks such as didDisplayFlagViewForItem, didUserSubmitFlag, didUserCancelFlagViewForItem, and didDisplayFlagViewFailWithError to keep track of flagView and its actions.
4. Receiving Flag Resolution Notifications (Backend)
While the SDK allows you to initiate and potentially clear flags, the actual review and resolution of a flag (e.g., if Entrupy support changes a result or adds a note) happens on Entrupy's backend.
To be notified of these changes programmatically:
- Webhooks: Your backend server should be configured to receive webhook notifications from the Entrupy API for updates related to flag statuses or result changes.
Refer to the Entrupy API documentation for details on setting up webhooks.
Related Topics
- If you want the SDK to host the flagging workflow (reason selection, validation, submission) in a built-in bottom sheet, see the Flag View UI guide.
- To give users an immediate post-capture way to dispute an authentication, pair flagging with the Result Screen UI.
- To review ongoing status and manage actions (including flags) in the SDK’s main results experience, see the Detail View Controller guide.
- If you need to build a fully custom support experience (including flags) without presenting SDK UI, see Programmatic Customer Support.
By implementing these flag management features, you provide a valuable feedback loop for users and ensure that authentication results can be reviewed and addressed if concerns arise.