Skip to content

Bank Data Sharing — Requirements v2.1

The Authentication requirements, Authorization requirements, and User Journeys must be adhered to.

The tables below list the rules that apply to Bank Data Sharing. All request validation of the TPP's credentials, access token, and consent is performed by the Hub before your Ozone Connect endpoints are called. The rules below cover what your Ozone Connect endpoints must validate and what they must return.

When a TPP creates a consent, the API Hub calls your POST /consent/action/validate endpoint before the consent is created. You MUST validate the consent and respond with status: "valid" or status: "invalid". If you respond with invalid, the API Hub will not create the consent and the TPP will receive an error.

This validation runs before the PSU is involved — there is no authentication or authorization at this stage. The purpose is to reject consents early that your systems cannot fulfil.

The field names in the rules below match the Ozone Connect newConsent payload the Hub delivers — standardVersion sits at the top level of the consent object; BaseConsentId, AccountType, AccountSubType, and Permissions sit under consentBody.Data.

#RuleDetail
1Unsupported standardVersionThe consent's standardVersion (a top-level property on the consent object) is the URL path version the TPP will call on subsequent data sharing requests. If you do not support that version for the Account Information API family, respond with invalid.

Where you are dual-running multiple versions during a deprecation window (see Major Version Deprecation) — for example v2.0 alongside v3.1 — you MUST respond valid for every version you serve.

Minor versions are backward compatible (see Version Management), so prior minors within each major you run are also valid (e.g. running v2.0 and v3.1 means v2.0, v3.0, and v3.1 all resolve to valid).
2Unsupported AccountTypeIf the consent's AccountType array contains a value that is not supported by the API Hub integration the consent was received on, respond with invalid. Each API Hub integration is scoped to a single segment (Retail, SME, or Corporate). If the LFI serves multiple segments, each segment MUST be configured as a separate API Hub integration because the API Hub has a single authorization endpoint. Validate that every requested AccountType is within scope of the integration that received the consent.
3Unsupported AccountSubTypeIf the consent's AccountSubType array contains a value not supported by this LFI, respond with invalid. For example, if the LFI does not offer Mortgage products but the consent requests Mortgage, the consent MUST be rejected at validation.
4Unsupported permissionsIf the consent includes permissions that reference an endpoint the LFI has not yet delivered, respond with invalid. For example, if the consent includes ReadStandingOrdersBasic or ReadStandingOrdersDetail but GET /accounts/{AccountId}/standing-orders is not yet available, the consent MUST be rejected at validation.
5Invalid BaseConsentIdIf the consent includes a BaseConsentId, validate that:
  • The BaseConsentId references an existing consent known to the LFI.
  • The referenced consent is a Data Sharing consent (authorization_details[0].type is urn:openfinanceuae:account-access-consent:*).
  • The referenced consent does not itself have a BaseConsentId — if it does, the TPP has incorrectly linked to an intermediate consent in the chain rather than the root consent. The BaseConsentId must always reference the original root consent.
If any of these checks fail, respond with invalid.

Authorization — Account Selection

The generic Authorization requirements apply to this journey. The rules below cover the additional account selection logic specific to Bank Data Sharing.

During the consent authorization journey, the customer selects which of their accounts to share with the TPP. The LFI is responsible for presenting the eligible accounts and applying any filters the TPP has specified in the consent.

#FieldRule
1consent.AccountTypeIf the consent specifies AccountType, only present accounts whose type matches one of the specified values (Retail, SME, Corporate). If not specified, present accounts of all types supported by this API Hub integration.
2consent.AccountSubTypeIf the consent specifies AccountSubType, only present accounts whose subtype matches one of the specified values. If not specified, present accounts of all subtypes.
3No eligible accountsIf the authenticated PSU does not hold any accounts matching the requested consent parameters (e.g. AccountType, AccountSubType, or the permissions requested), PATCH the consent to Rejected and call doFail with error: invalid_request and error_description: user_lacks_eligible_accounts. See Authorization requirements for details.
4Multiple selectionThe account selection screen must allow the customer to select more than one account. A consent with no accounts selected must not be authorised.

GET /accounts

#FieldRule
1accountIdsReturn the accounts whose id matches one of the values in the accountIds query parameter. Populate the Status field on each account so the TPP can see the current state.
2Data completenessAll fields that exist or are derivable from your systems must be populated on each account. All fields marked as required in the OpenAPI spec must be present. This includes accountHolderName, status, currency, accountType, and accountSubType where held.
3accountNumbersMust contain at least one entry. schemeName and identification are required on each entry.
4accountNumbers.schemeNameMust reflect the account identifier type: IBAN for CurrentAccount and Savings; MaskedPAN for CreditCard; MortgageReference for Mortgage; FinanceReference for Finance.
5customersFor non-business accounts, customers must contain at least one entry. For business accounts, populate businessCustomer instead.
6AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
7Account statusReturn all consented accounts regardless of Status. Accounts that are Inactive, Dormant, Suspended, Unclaimed, Deceased, or Closed MUST still be included — the Status field on each account reflects the current state so the TPP can observe it. This endpoint is exempt from the Account Status Handling mapping.

GET /accounts/{accountId}

#FieldRule
1accountReturn the account whose id matches the value in the accountId path parameter.
2Data completenessAll fields that exist or are derivable from your systems must be populated, consistent with what is returned by GET /accounts for the same account. All fields marked as required in the OpenAPI spec must be present.
3accountNumbersMust contain at least one entry. schemeName and identification are required on each entry.
4accountNumbers.schemeNameMust reflect the account identifier type: IBAN for CurrentAccount and Savings; MaskedPAN for CreditCard; MortgageReference for Mortgage; FinanceReference for Finance.
5AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/balances

#FieldRule
1accountReturn the balances for the account whose id matches the value in the accountId path parameter.
2Data completenessAll balance types that exist for the account must be returned. All fields marked as required in the OpenAPI spec must be present on each record, including accountId, balanceType, amount (with amount and currency), creditDebitIndicator, and timestamp.
3Multiple balance typesReturn one record per distinct balance type held for the account. More than one record per account is permitted and expected where multiple balance types exist. Include creditLines where applicable.
4InterimAvailableFor CurrentAccount and Savings accounts, a record with balanceType: InterimAvailable must always be included. This is the real-time available balance on the account.
5AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/beneficiaries

#FieldRule
1accountReturn the beneficiaries linked to the account whose id matches the value in the accountId path parameter.
2Required fieldsEvery beneficiary record must include accountId, beneficiaryId, beneficiaryType, and addedViaOF.
3Data completenessAll fields that exist or are derivable must be populated, including creditorAccount (with schemeName and identification), servicer, and reference where held.
4Empty resultIf the account holds no beneficiaries, return 200 with an empty data array. Do not return 404.
5AccountSubTypeOnly supported for CurrentAccount and Savings accounts. Not available for CreditCard, Finance, or Mortgage accounts.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/direct-debits

#FieldRule
1accountReturn the direct debits linked to the account whose id matches the value in the accountId path parameter.
2Required fieldsEvery direct debit record must include accountId, directDebitId, directDebitStatusCode, mandateIdentification, name, and frequency.
3Data completenessInclude previousPaymentDateTime and previousPaymentAmount where available.
4Empty resultIf the account holds no direct debits, return 200 with an empty data array. Do not return 404.
5AccountSubTypeOnly supported for CurrentAccount and Savings accounts. Not available for CreditCard, Finance, or Mortgage accounts.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/scheduled-payments

#FieldRule
1accountReturn the scheduled payments linked to the account whose id matches the value in the accountId path parameter.
2Required fieldsEvery scheduled payment record must include accountId, scheduledPaymentId, scheduledType, scheduledPaymentDateTime, and instructedAmount (with amount and currency).
3Data completenessInclude creditorAccount (with schemeName and identification), creditorAgent, creditorReference, and debtorReference where held.
4Empty resultIf the account holds no scheduled payments, return 200 with an empty data array. Do not return 404.
5AccountSubTypeOnly supported for CurrentAccount and Savings accounts. Not available for CreditCard, Finance, or Mortgage accounts.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/standing-orders

#FieldRule
1accountReturn the standing orders linked to the account whose id matches the value in the accountId path parameter.
2Required fieldsEvery standing order record must include accountId, standingOrderId, frequency, firstPaymentDateTime, standingOrderStatusCode, and firstPaymentAmount (with amount and currency).
3Data completenessInclude nextPaymentDateTime, nextPaymentAmount, lastPaymentDateTime, lastPaymentAmount, finalPaymentDateTime, finalPaymentAmount, numberOfPayments, creditorAccount, creditorAgent, and standingOrderType where held.
4Empty resultIf the account holds no standing orders, return 200 with an empty data array. Do not return 404.
5AccountSubTypeOnly supported for CurrentAccount and Savings accounts. Not available for CreditCard, Finance, or Mortgage accounts.
6Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/statements

#FieldRule
1accountReturn the statements for the account whose id matches the value in the accountId path parameter.
2fromStatementDateIf provided, return only statements with a statement date on or after this date. Filtering is open-ended (from the earliest available statement) if not provided.
3toStatementDateIf provided, return only statements with a statement date on or before this date. Filtering is open-ended (to the latest available statement) if not provided.
4Required fieldsEvery statement record must include accountId, accountSubType, statementId, statementDate, openingDate, closingDate, openingBalance (with creditDebitIndicator, amount, and currency), closingBalance (with creditDebitIndicator, amount, and currency), and summary (with creditDebitIndicator, subTransactionType, amount, and count per entry).
5Data completenessAll fields that exist or are derivable for each statement must be returned, including creditLine where applicable.
6Data retentionThe endpoint must support retrieval of at least the last two years of statements.
7Empty resultIf no statements exist within the requested range, return 200 with an empty data array. Do not return 404.
8PaginationPagination must be supported. meta.paginated, meta.totalRecords, and meta.totalPages must be accurate.
9AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
10Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/transactions

#FieldRule
1accountReturn the transactions for the account whose id matches the value in the accountId path parameter.
2fromBookingDateTimeIf provided, return only transactions booked on or after this date-time. Filtering is open-ended if not provided.
3toBookingDateTimeIf provided, return only transactions booked on or before this date-time. Filtering is open-ended if not provided.
4TimezoneAny timezone offset in fromBookingDateTime or toBookingDateTime must be ignored. Filter against local booking date-time only.
5Required fieldsEvery transaction record must include accountId, transactionId, transactionDateTime, transactionType, subTransactionType, creditDebitIndicator, status, bookingDateTime, and amount (with amount and currency).
6Data completenessAll fields that exist or are derivable must be populated, including balance (with creditDebitIndicator, balanceType, and amount) where available, merchantDetails, creditorAccount, debtorAccount, cardInstrument, currencyExchange, flags, and paymentPurposeCode where held.
7Transaction contexttransactionInformation and transactionReference must be provided where held to give the TPP meaningful context for the transaction.
8Data retentionThe endpoint must support retrieval of at least the last two years of transactions.
9Empty resultIf no transactions exist within the requested range, return 200 with an empty data array. Do not return 404.
10PaginationPagination must be supported. meta.paginated, meta.totalRecords, and meta.totalPages must be accurate.
11AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
12Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/products

#FieldRule
1accountReturn the products associated with the account whose id matches the value in the accountId path parameter.
2Data completenessAll product data that exists or is derivable from your systems must be returned, including fees, charges, rates, rewards, benefits, and eligibility criteria where held.
3FinanceRates formatFinanceRates may be returned as either a cleartext AEProductFinanceRates JSON object or as a JWE compact serialisation string. Encryption is at the LFI's discretion.
4FinanceRates — JWEIf encrypting FinanceRates, generate an ephemeral symmetric encryption key per response (must not be reused). Encrypt the AEProductFinanceRates payload as a JWE using the content encryption algorithm required by the Security Profile. Set exp to 30 minutes from the time of the response and set kid to the value of x-fapi-interaction-id. Transmit the encryption key to the User via an existing LFI channel (e.g. SMS or push notification) — do not include it in the API response.
5Empty resultIf no product data exists for the account, return 200 with an empty data array. Do not return 404.
6PaginationPagination must be supported. meta.paginated, meta.totalRecords, and meta.totalPages must be accurate.
7AccountSubTypeSupported for all account subtypes: CurrentAccount, Savings, CreditCard, Finance, and Mortgage.
8Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /accounts/{accountId}/customer

#FieldRule
1accountReturn the customers associated with the account whose id matches the value in the accountId path parameter.
2Multiple customersReturn one record per customer associated with the account. Joint accounts must return a record for each joint holder.
3Required fieldsEvery customer record must include id, claims verifiedClaims, customerType, customerCategory, and accountRole.
4Person claimsFor retail customers, verifiedClaims[].claims must include identityType, fullName, givenName, familyName, emiratesId, emiratesIdExpiryDate, and residentialAddress. Include all optional fields (middleName, birthDate, mobileNumber, email, nationality, etc.) where held.
5Corporate claimsFor SME/Corporate customers, verifiedClaims[].claims must include identityType, businessName, and tradeLicenceNumber. Include all optional fields (taxIdentificationNumber, dateOfIncorporation, countryOfIncorporation, corporateAddress, etc.) where held.
6Data completenessAll fields that exist or are derivable from your systems must be populated on each customer record.
7Empty resultIf no customer records are associated with the account, return 200 with an empty data array. Do not return 404.
8Paginationmeta.totalRecords and meta.totalPages must be accurate.
9Account statusIf the account is not Active, do not return the resource. Apply the Account Status Handling mapping to return 403 with the corresponding errorCode and errorMessage.

GET /customer

#FieldRule
1Customer identificationIdentify the customer from the o3-psu-identifier header passed by the Hub.
2Required fieldsThe customer record must include id, verifiedClaims, and customerCategory.
3Person claimsFor retail customers, verifiedClaims[].claims must include identityType, fullName, givenName, familyName, emiratesId, emiratesIdExpiryDate, and residentialAddress. Include all optional fields where held.
4Corporate claimsFor SME/Corporate customers, verifiedClaims[].claims must include identityType, businessName, and tradeLicenceNumber. Include all optional fields where held.
5Data completenessAll fields that exist or are derivable from your systems must be populated.

Account Status Handling

The rules above assume the account is in a readable state. The table below summarises how each value of AEAccountStatusCode maps to a response for endpoints under /accounts/{accountId}.

StatusReadableResponse if not readable
Active
Inactive
Dormant
Suspended403 with errorCode: Consent.AccountTemporarilyBlocked and errorMessage: The account is temporarily blocked.
Unclaimed403 with errorCode: Consent.PermanentAccountAccessFailure and errorMessage: The account is permanently inaccessible.
Deceased403 with errorCode: Consent.PermanentAccountAccessFailure and errorMessage: The account is permanently inaccessible.
Closed403 with errorCode: Consent.PermanentAccountAccessFailure and errorMessage: The account is permanently inaccessible.

GET /accounts is exempt from this mapping — it returns all consented accounts regardless of status, with the Status field populated so the TPP can see the current state.