The Developer's Guide to CBUAE Open Finance Compliance 2026
A complete technical guide for developers building UAE Open Finance applications: consent management, payment validation, participant lookup, and API integration aligned with CBUAE Circular 03/2025.
What is CBUAE Open Finance Regulation?
In March 2025 the Central Bank of the UAE (CBUAE) published Circular No. 03/2025, which mandates an Open Finance framework for all Licensed Financial Institutions (LFIs) in the UAE. The regulation requires banks, insurance companies, payment service providers, and exchange houses to expose standardised APIs for data sharing, payment initiation, and consent management.
The framework rolls out in three phases:
| Phase | Target LFI Type | Deadline |
|---|---|---|
| Phase 1 | Banks and insurance companies | September 2025 |
| Phase 2 | Payment service providers, exchange houses | 2026 |
| Phase 3 | Finance companies, stored value facilities | 2027 |
Who Needs to Comply?
LFIs (supply side): The 18 UAE institutions enrolled so far include FAB, Emirates NBD, ADCB, DIB, Mashreq, ADIB, CBD, RAKBANK and others. They must expose customer data via standardised APIs once their phase deadline passes. TPPs (demand side): Fintech apps, personal finance managers, payment orchestration platforms — any software that reads customer data or initiates payments on behalf of UAE account holders. TPPs must obtain and store valid consent objects per Article 22, use ISO 20022 message formats, and log all access.Core Technical Requirements
1. Consent Management (Article 22)
Every access to customer financial data must be backed by a valid, explicit consent object. CBUAE Article 22 defines 15+ mandatory fields and rules:
- Purpose must be specific — "for personal finance management" is valid; "general use" is not
- Duration must be time-bounded (maximum 12 months per grant)
- Sensitive data (e.g. passport scans) requires a separate consent scope
- Customers must be able to withdraw consent in-app at any time
- Data storage location must be declared — UAE residents' data must remain within the AE jurisdiction by default
KhaleejiAPI's Consent Validator checks your consent objects against all of these rules before you go live:
const res = await fetch('https://khaleejiapi.dev/api/v1/openfinance/consent/validate', {
method: 'POST',
headers: {
'Authorization': Bearer ${process.env.KHALEEJI_API_KEY!},
'Content-Type': 'application/json',
},
body: JSON.stringify({
purpose: 'Account balance and transaction history for personal budgeting',
consentMethod: 'explicit',
dataTypes: ['account_balance', 'transaction_history'],
duration: 6, // months
withdrawalMethod: 'in-app',
dataStorageLocation: 'AE',
}),
});
const { data } = await res.json();
// { compliant: true, issues: [], score: 100 }
A non-compliant consent object returns compliant: false with an issues array explaining each violation and a remediation hint. Use this in your CI pipeline to gate deployments.
2. Participant Directory
Before sending any API request to an LFI, verify it is enrolled in the Open Finance framework and check its current phase and status. Calling an LFI endpoint before it has completed its phase rollout will result in 404 or 403 errors.
// List all Phase 1 banks
const res = await fetch(
'https://khaleejiapi.dev/api/v1/openfinance/participants?type=bank&phase=1&status=active',
{ headers: { 'Authorization': Bearer ${process.env.KHALEEJI_API_KEY!} } }
);
const { data } = await res.json();
// Returns: FAB, Emirates NBD, ADCB, DIB, Mashreq, ADIB, CBD, RAKBANK
Filter parameters:
| Param | Values | Description |
|---|---|---|
type | bank, insurance, psp, exchange_house, finance_company | Institution category |
phase | 1, 2, 3 | Rollout phase |
status | active, pending | Live vs. onboarding |
3. Payment Validation (ISO 20022)
All payment initiations within the Open Finance framework must conform to ISO 20022 message schemas. KhaleejiAPI's Payment Validator pre-checks your payload before it reaches the LFI's endpoint, preventing rejection errors that reset the full consent flow:
const res = await fetch('https://khaleejiapi.dev/api/v1/openfinance/payment/validate', {
method: 'POST',
headers: {
'Authorization': Bearer ${process.env.KHALEEJI_API_KEY!},
'Content-Type': 'application/json',
},
body: JSON.stringify({
payerIBAN: 'AE070331234567890123456',
payeeIBAN: 'AE460261234567890123456',
amount: 1500.00,
currency: 'AED',
paymentType: 'instant',
}),
});
const { data } = await res.json();
/*
{
valid: true,
paymentScheme: "Aani", // instant payments network
payerBank: "Emirates NBD",
payeeBank: "FAB",
ibanValidation: { payer: true, payee: true }
}
*/
The validator performs MOD 97 IBAN verification, identifies the payment scheme (Aani for instant, UAEFTS for domestic, SWIFT for international), and maps each IBAN to the issuing LFI.
4. Compliance Deadline Tracker
Regulation deadlines change. Use the Standards Reference API to pull the current phase roadmap, products in scope, and relevant regulation articles at runtime — instead of hardcoding dates that become stale:
const res = await fetch(
'https://khaleejiapi.dev/api/v1/openfinance/standards?section=compliance',
{ headers: { 'Authorization': Bearer ${process.env.KHALEEJI_API_KEY!} } }
);
const { data } = await res.json();
// Returns: phases array, deadlines, products in scope, regulation articles
End-to-End Compliance Checklist
Use this as a pre-launch gate for any UAE Open Finance integration:
[ ] Consent object passes /openfinance/consent/validate with score ≥ 90
[ ] Target LFI returned by /openfinance/participants with status=active
[ ] All payment payloads pass /openfinance/payment/validate before submission
[ ] Data storage location set to "AE" in every consent object
[ ] Withdrawal method is accessible in-app within 3 taps
[ ] Sensitive data types excluded from standard consent scope
[ ] Consent duration ≤ 12 months per grant
[ ] Audit log entries created for every data access event
Why Low Latency Matters for Compliance
Time-sensitive operations — consent validation during a payment flow, IBAN verification at checkout — must complete in under 200 ms from the user's perspective. KhaleejiAPI runs on AWS ap-south-1 (Mumbai) behind Cloudflare's UAE/GCC edge nodes. GCC users typically see 80–120 ms end-to-end for validation calls, compared to 200 ms+ from US-East infrastructure. This latency budget matters when your Open Finance flow chains three API calls (participant check → consent validate → payment validate) before the user's payment request even leaves your server.
Python Example: Full Compliance Flow
import requests
import os
BASE = "https://khaleejiapi.dev/api/v1/openfinance"
HEADERS = {
"Authorization": "Bearer " + os.environ["KHALEEJI_API_KEY"],
"Content-Type": "application/json",
}
def is_lfi_active(institution_name: str, phase: int = 1) -> bool:
"""Check whether an LFI is enrolled and active in the given phase."""
r = requests.get(
f"{BASE}/participants",
params={"type": "bank", "phase": phase, "status": "active"},
headers=HEADERS,
)
participants = r.json()["data"]["participants"]
return any(p["name"] == institution_name for p in participants)
def validate_consent(consent_payload: dict) -> dict:
"""Validate a consent object against CBUAE Article 22."""
r = requests.post(
f"{BASE}/consent/validate",
json=consent_payload,
headers=HEADERS,
)
return r.json()["data"]
def validate_payment(payment_payload: dict) -> dict:
"""Validate a payment initiation request against ISO 20022."""
r = requests.post(
f"{BASE}/payment/validate",
json=payment_payload,
headers=HEADERS,
)
return r.json()["data"]
# --- Example usage ---
# 1. Confirm the target bank is live
if not is_lfi_active("Emirates NBD", phase=1):
raise RuntimeError("Emirates NBD is not yet active in Phase 1")
# 2. Validate consent before requesting customer data
consent = validate_consent({
"purpose": "Account balance inquiry for personal finance dashboard",
"consentMethod": "explicit",
"dataTypes": ["account_balance"],
"duration": 3,
"withdrawalMethod": "in-app",
"dataStorageLocation": "AE",
})
if not consent["compliant"]:
print("Consent issues:", consent["issues"])
raise ValueError("Consent object is non-compliant")
# 3. Validate payment before initiating
payment = validate_payment({
"payerIBAN": "AE070331234567890123456",
"payeeIBAN": "AE460261234567890123456",
"amount": 500.00,
"currency": "AED",
"paymentType": "instant",
})
if not payment["valid"]:
raise ValueError(f"Payment validation failed: {payment}")
print("All compliance checks passed ✓")
Common Pitfalls
1. Purpose string too vague — "General banking access" will fail the consent validator. Be specific: name the feature and data type. 2. Missing withdrawal method — You must declare how a customer can revoke consent from within your app. A link to a support email is not sufficient. 3. Stale participant cache — LFI status changes during rollout. Refresh your participant list at least daily; never hardcode institution IDs. 4. Incorrect IBAN country code — UAE IBANs start withAE followed by 21 digits (23 total). Saudi IBANs start with SA and are 24 characters. The Payment Validator catches these early.
5. Duration > 12 months — The regulation caps consent grants at 12 months. Most use cases work fine with 3–6 months and a renewal reminder UX.
Get Started Free
All four CBUAE Open Finance endpoints are available on the free tier — 1,000 requests/month, no credit card required.
curl https://khaleejiapi.dev/api/v1/openfinance/participants?type=bank \
-H "Authorization: Bearer YOUR_KEY"
Sign up for a free API key →