LFI · CAAP · API Guide

CAAP Operations API Guide 10 min read

When an LFI adopts CAAP, the end user's authentication and consent authorisation experience is delivered by CAAP rather than by the LFI. CAAP drives that experience by calling endpoints on the LFI's Ozone Connect server. This guide walks the end-to-end flow and focuses on what is different about the CAAP path — from the redirect into CAAP, through registration and account or policy selection, to the final redirect back to the TPP.

01 Endpoints in scope

CAAP Operations endpoints the LFI MUST implement

These endpoints are called on the LFI's Ozone Connect server. They use the same base URL, mTLS, and (where configured) JWT authentication as the LFI's other Ozone Connect surfaces — see Ozone Connect Base URL.

EndpointDirectionPurpose
POST/consent/actions/validateAPI Hub → LFILFI validates the consent at PAR time; gates whether the consent is created and the request_uri is returned to the TPP.
POST/users/actions/register/initializeCAAP → LFIIdentify the end user at the LFI from an encrypted Emirates ID; return the end user's LFI userId.
POST/users/actions/register/completeCAAP → LFIComplete registration after the end user has answered the LFI's OTP challenge.
GET/accountsCAAP → LFIReturn every account the end user can share or initiate from, depending on the use case.
GET/{type}-insurance-policiesCAAP → LFIReturn every insurance policy of the given type the end user can share.
Hub-side endpoints CAAP calls

CAAP also calls the API Hub's Headless Heimdall and Consent Manager at the end of the journey to patch the consent and complete the interaction. The LFI does not implement those — the API Hub does — but they appear in the sequence flow below for completeness.

02 API sequence flow

End-to-end flow diagram

Sequence diagramCAAP Consent FlowClick to expand
03 Step 1 — Consent creation

POST /par

The journey begins with the standard POST/par flow — including the API Hub's gating call to POST/consent/actions/validate on the LFI before the consent is created. See Consent Journey — API Guide for the full mechanics; nothing about this step changes for CAAP-adopting LFIs.

Once the TPP has the request_uri, it redirects the end user to the API Hub's authorize URL. The API Hub recognises that this LFI is configured for CAAP and redirects the end user on to CAAP rather than to an LFI-operated authorization endpoint — this is the first point at which CAAP differs from the LFI-operated flow.

04 Step 2 — Authentication

End user authenticates at CAAP via EFR or UAE Pass

CAAP authenticates the end user using EFR or UAE Pass. This step does not involve the LFI — CAAP integrates with the national identity rails directly. The end user's Emirates ID is established as a result.

05 Step 3 — Register the end user

POST /users/actions/register/initialize

Once CAAP has the end user's Emirates ID, it calls POST/users/actions/register/initialize on the LFI's Ozone Connect server. The request body carries the Emirates ID encrypted — never in cleartext.

Encryption with the LFI's ENC1 key

CAAP encrypts the Emirates ID using the LFI's ENC1 public key — the same server-side encryption key referenced in Keys & Certificates. The LFI MUST decrypt the payload using the corresponding ENC1 private key.

The LFI MUST return providerUserIdentifier.userId on the initial response

Regardless of whether the LFI subsequently issues a challenge, the response to register/initialize MUST contain the LFI's identifier for the end user on data.providerUserIdentifier.userId. CAAP uses this identifier from that point on, including the psuIdentifiers.userId it patches onto the consent at the end of the journey — it MUST be identical across all of those uses, and MUST satisfy the opacity rules described in Consent Journey — Identifier requirements.

userId MUST be opaque and non-sensitive

The userId the LFI returns is stored centrally by the API Hub. It MUST be opaque, non-sensitive, and LFI-defined — never an Emirates ID, passport number, email, phone number, CIF, account number, or any other PII. Use an internal customer reference, a UUID, or another opaque token.

Optional challenge

The LFI may choose to issue its own challenge before registration is final — typically an OTP sent over the LFI's usual SCA channel. To do so, the LFI responds with registrationStatus set to AwaitingChallengeResponse and a challengeId alongside the providerUserIdentifier.userId. CAAP collects the OTP from the end user and calls POST/users/actions/register/complete.

If the LFI does not need to challenge the end user, it responds to the initial register/initialize call directly with registrationStatus: Complete alongside providerUserIdentifier.userId — CAAP skips the complete step entirely.

06 Step 4 — Complete registration

POST /users/actions/register/complete (challenged journeys only)

Where the LFI issued a challenge, CAAP submits the end user's response via POST/users/actions/register/complete. The LFI verifies the response and returns registrationStatus: Complete. Registration is now finalised and CAAP proceeds to build the authorization page.

Failed challenge responses are not HTTP errors

Per the CAAP Operations spec, an incorrect challenge response MUST be returned as an HTTP 200 with a result indicator in the payload — not as a 4xx. Reserve non-2xx status codes for genuine error conditions (malformed requests, internal failures).

07 Step 5 — Build the authorization page

Fetch the accounts or policies the end user can select from

With the end user registered, CAAP retrieves the data needed to render the authorization page. The endpoint called depends on the consent type, and CAAP signals the use case via the o3-caap-consent-use-case header on the accounts endpoint.

In all three cases, the LFI MUST return every item the end user can choose from — do not pre-filter to a subset. CAAP renders the full list and the end user picks from it on the authorization page.

Consent typeCAAP callsLFI returns
Bank Data SharingGET/accounts with o3-caap-consent-use-case: accountsEvery account the end user is permitted to share for data sharing.
Bank Service InitiationGET/accounts with o3-caap-consent-use-case: paymentsEvery account the end user is permitted to initiate the requested payment from.
Insurance Data SharingGET/{type}-insurance-policies, once per insurance type in the consent permissionsEvery policy of that type the end user is permitted to share.
08 Step 6 — Authorize and redirect

CAAP completes the journey on the API Hub

CAAP renders the authorization page per the User Experience (which shows the end-to-end end user journey screen by screen), displaying the consent details and the accounts or policies the end user can select. After the end user clicks Authorize, CAAP completes the journey in the same way an LFI-operated authorization server would — against the API Hub, not against the LFI:

  • PATCH the consent. CAAP calls PATCH/consents/{consentId} on the API Hub Consent Manager, setting status to Authorized and including the psuIdentifiers.userId returned by the LFI on register/initialize, plus either accountIds (Bank Data Sharing, Bank Service Initiation) or insurancePolicyIds (Insurance Data Sharing) for the items the end user selected.
  • Complete the interaction. CAAP calls POST/auth/{interactionId}/doConfirm on Headless Heimdall, which issues a redirect back to the TPP's callback URI with the authorization code and state.
  • Follow the redirect. CAAP forwards the redirect to the end user's browser, returning the end user to the TPP. The TPP exchanges the code for tokens on POST/token and the consent is now Authorized.
The LFI is no longer on the path

From this point onwards the consent is live and runtime data and payment calls flow through the API Hub to the LFI's Ozone Connect endpoints (Bank Data Sharing, Bank Service Initiation, Insurance Data Sharing) as normal. CAAP is not involved in those calls.