HAAPI Flow#

HaapiManager exposes the HAAPI flow as a structured state machine — start begins the flow, and submit / followLink advance it. Each step is returned as a typed model that your UI renders: a form to display, a selector to choose from, a polling indicator, a problem screen, or a final authorization response.

Starting the Flow#

HaapiManager.start triggers the first server interaction and returns the initial step:

haapiManager.start { [weak self] haapiResult in
    self?.handleHaapiResult(haapiResult)
}

The result falls into one of three top-level categories:

  • A representation — a typed step model the UI maps to a screen.
  • A problem representation — an error that requires the user to correct input and retry.
  • An error — a framework or transport failure (iOS surfaces this as a result variant; Android raises it as an exception).

Handling Step Types#

The step model is a sealed hierarchy. Cast or match on the concrete type to dispatch to the right UI:

private func handleHaapiResult(_ haapiResult: HaapiResult) {
    switch haapiResult {
    case .representation(let haapiRepresentation):
        handleHaapiRepresentation(haapiRepresentation)
    case .problem(let problemRepresentation):
        handleProblemRepresentation(problemRepresentation)
    case .error(let anError):
        handleError(anError)
    }
}

private func handleHaapiRepresentation(_ haapiRepresentation: HaapiRepresentation) {
    switch haapiRepresentation {
    case let authenticatorSelectorStep as AuthenticatorSelectorStep:
        // render authenticator selector
        break
    case let interactiveFormStep as InteractiveFormStep:
        // render form
        break
    case let pollingStep as PollingStep:
        // start polling
        break
    case let authResponseStep as OAuthAuthorizationResponseStep:
        // flow complete — exchange code for tokens
        break
    default:
        // handle other step types
        break
    }
}

All 14 step types and their carried fields are catalogued in iOS Representations .

Common step types across platforms include AuthenticatorSelectorStep, InteractiveFormStep, PollingStep, RedirectionStep, UserConsentStep, ContinueSameStep, OAuthAuthorizationResponseStep, and GenericRepresentationStep. The Android SDK additionally surfaces ClientOperationStep (and its sub-types ExternalBrowserClientOperationStep, WebAuthnRegistrationClientOperationStep, and others) as a sibling category for steps that delegate to an external operation rather than rendering a screen.

Advancing the Flow#

Based on user interaction, call either submit (when the step represents a form the user filled in) or followLink (when the step exposes navigation links the user chose). The next step is delivered the same way as start:

private func submit(formActionModel: FormActionModel, parameters: [String: Any]) {
    haapiManager.submitForm(formActionModel, parameters: parameters) { [weak self] haapiResult in
        self?.handleHaapiResult(haapiResult)
    }
}

private func followLink(_ link: Link) {
    haapiManager.followLink(link) { [weak self] haapiResult in
        self?.handleHaapiResult(haapiResult)
    }
}

Parameter values must be JSON-serialisable on all three platforms — string, number / Int / Long / Double, boolean, null, nested objects, arrays. The native side validates the type set at runtime; supplying a non-JSON-serialisable value (a class instance, a Date, a function) raises IllegalArgumentException on Android, throws on iOS, and rejects the Promise as HAAPI_UNEXPECTED on React Native.

For GET form actions, all three platforms require string-only parameter values. Convert numbers, booleans, and dates to String before submitting GET forms.

Polling Intervals#

When handling a PollingStep, check pollingStep.pollingProperties.interval for a server-provided polling interval (milliseconds, represented as a string). When present, prefer the server value over any client-side default. For BankID flows, the precedence is: server interval → BankID’s published 1-second cadence → application default.

Reaching the End of the Flow#

The flow completes when HaapiManager returns an OAuthAuthorizationResponseStep. The step’s properties contain a code — exchange it for tokens via OAuthTokenManager.fetchAccessToken. See OAuthTokenManager .

Was this helpful?