Guidecbuaeopen-financecompliance

Navigating CBUAE Open Finance (التمويل المفتوح): Your Essential Compliance Checklist

A practical, step-by-step compliance checklist for developers and fintechs building on the CBUAE Open Finance framework — covering consent, identity, payments, data residency, and Islamic finance requirements.

KhaleejiAPI TeamAugust 2, 202611 min read

The Central Bank of the UAE (CBUAE) introduced its Open Finance (التمويل المفتوح) regulatory framework under Circular No. 03/2025, requiring Licensed Financial Institutions (LFIs) and third-party providers (TPPs) to meet a strict set of technical and operational standards before going live. For developers, meeting these requirements isn't optional — a single non-compliant endpoint can block your application from the UAE financial ecosystem entirely.

This checklist distills the key obligations into actionable items you can tick off before every production deployment. Use KhaleejiAPI's four Open Finance endpoints alongside this guide to automate the checks that matter most.

Phase 1 — Identity & Data Validation

Strong identity validation is the foundation of every Open Finance flow. Malformed IBANs and unverified Emirates IDs are the top causes of payment rejections and KYC failures in UAE FinTech applications.

✅ 1.1 IBAN Validation

UAE IBANs are exactly 23 characters: country code AE + 2 check digits + 19-character BBAN. A MOD-97 checksum guards against transcription errors.

const res = await fetch('https://khaleejiapi.dev/api/v1/iban/validate', {
  method: 'POST',
  headers: { 'Authorization': '', 'Content-Type': 'application/json' },
  body: JSON.stringify({ iban: 'AE070331234567890123456' }),
});
const { data } = await res.json();
// { valid: true, country: "AE", bank: "Emirates NBD", formatted: "AE07 0331 2345 6789 0123 456" }
Checklist items:
  • [ ] Validate every payer and payee IBAN at the point of user input, not only at submission
  • [ ] Reject IBANs that do not start with AE for domestic UAE transfers
  • [ ] Surface the resolved bank name to the user for confirmation before payment initiation

✅ 1.2 Emirates ID Validation

Many UAE LFIs require Emirates ID as a KYC signal. The 15-digit format (784-YYYY-NNNNNNN-C) carries a Luhn checksum.

const res = await fetch('https://khaleejiapi.dev/api/v1/emirates-id/validate', {
  method: 'POST',
  headers: { 'Authorization': '', 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: '784-1985-1234567-8' }),
});
const { data } = await res.json();
// { valid: true, dob: "1985", gender: "male" }
Checklist items:
  • [ ] Validate Emirates ID format before submitting to any LFI endpoint
  • [ ] Do not store raw Emirates ID numbers beyond the KYC session (PDPL Article 9)
  • [ ] Log each validation attempt in your audit trail with a pseudonymised identifier

✅ 1.3 UAE VAT / TRN Validation

For B2B Open Finance flows involving VAT-registered businesses, validate the 15-digit Tax Registration Number (TRN) issued by the Federal Tax Authority:

const res = await fetch('https://khaleejiapi.dev/api/v1/vat/validate', {
  method: 'POST',
  headers: { 'Authorization': '', 'Content-Type': 'application/json' },
  body: JSON.stringify({ trn: '100123456700003', country: 'AE' }),
});
const { data } = await res.json();
// { valid: true, format: "UAE TRN", country: "AE" }
Checklist items:
  • [ ] Validate TRN for every invoice or payment involving a registered business
  • [ ] Confirm country code is AE before processing domestic VAT flows

---

Phase 2 — Participant Directory

Before initiating any Open Finance API call, confirm the target institution is an active CBUAE-licensed participant. Calling an inactive or unlicensed LFI can result in silent failures and difficult-to-debug 4xx errors from the bank's gateway.

✅ 2.1 Look Up Licensed Financial Institutions

const res = await fetch(
  'https://khaleejiapi.dev/api/v1/openfinance/participants?type=bank&status=active',
  { headers: { 'Authorization': '' } }
);
const { data } = await res.json();
// Returns: [{ id, name, licenseNumber, type, phase, status, endpoints }]
Checklist items:
  • [ ] Fetch the participant directory on application start and cache it for ≤ 24 hours
  • [ ] Verify the target LFI has status: "active" before any consent or payment request
  • [ ] Confirm the LFI's phase (R1–R5) covers the data scope you intend to access
  • [ ] Never hardcode institution IDs — look them up from the live directory
Participant typeCBUAE phases covered
bankR1 (read), R2 (payments), R3 (advanced data)
exchange_houseR2 (remittances)
finance_companyR1, R3
insuranceR4
pspR2, R5
---

Phase 3 — Consent Management (Article 22)

CBUAE Circular No. 03/2025 Article 22 is the most detailed compliance section. Every customer data access must be backed by a valid consent object that satisfies 15+ mandatory rules. Consent objects that fail validation will be rejected by LFIs at the API gateway level, forcing users through a frustrating re-consent flow.

✅ 3.1 Validate Every Consent Object Before Use

const res = await fetch('https://khaleejiapi.dev/api/v1/openfinance/consent/validate', {
  method: 'POST',
  headers: { 'Authorization': '', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    purpose: 'Account balance inquiry for personal finance management',
    consentMethod: 'explicit',
    dataTypes: ['account_balance', 'transaction_history'],
    duration: 6,
    withdrawalMethod: 'in-app',
    dataStorageLocation: 'AE',
  }),
});
const { data } = await res.json();
// { compliant: true, issues: [], score: 100 }

A score below 90 indicates the consent object will likely be rejected by UAE LFIs. The issues array provides rule-level explanations and remediation hints. Integrate this check into your CI/CD pipeline to catch non-compliant consent objects before they reach production.

Checklist items:
  • [ ] Every consent object achieves a validation score ≥ 90 before being presented to the user
  • [ ] Purpose field is specific and human-readable (not generic strings like "data access")
  • [ ] consentMethod is "explicit" — implicit consent is not permitted under Article 22
  • [ ] dataStorageLocation is set to "AE" for all UAE customer data
  • [ ] withdrawalMethod is accessible within 3 taps from the app's main screen
  • [ ] Consent duration does not exceed 12 months per grant
  • [ ] Sensitive data types (biometrics, health data) are excluded from standard consent scope
  • [ ] Each consent object is stored with a unique ID, creation timestamp, and expiry timestamp
  • [ ] Consent records are retained for a minimum of 5 years per UAE PDPL requirements

✅ 3.2 Consent Renewal and Revocation

  • [ ] Notify the customer at least 7 days before consent expiry
  • [ ] Provide a one-tap consent revocation flow inside the app
  • [ ] Revoke downstream access tokens immediately on consent withdrawal
  • [ ] Emit a consent.revoked webhook event to all subscribed services within 60 seconds

---

Phase 4 — Payment Initiation & ISO 20022

Payment payloads that don't conform to ISO 20022 message schemas are rejected at the bank gateway with opaque error codes. KhaleejiAPI's Payment Validator catches schema violations before they reach the LFI, saving the user from having to restart the full consent flow.

✅ 4.1 Validate Payment Payloads

const res = await fetch('https://khaleejiapi.dev/api/v1/openfinance/payment/validate', {
  method: 'POST',
  headers: { 'Authorization': '', '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",
  payerBank: "Emirates NBD",
  payeeBank: "FAB",
  ibanValidation: { payer: true, payee: true }
}
*/

The validator automatically selects the appropriate payment scheme:

Payment typeSchemeSettlement
instantAaniReal-time (< 10 s)
domesticUAEFTSSame-day
cross-borderSWIFT1–3 business days
bulkDirect DebitNext business day
Checklist items:
  • [ ] All payment payloads pass /openfinance/payment/validate before submission to the LFI
  • [ ] Currency is AED for domestic flows — do not submit FX amounts directly
  • [ ] Amount uses decimal notation with exactly 2 decimal places
  • [ ] paymentType matches the user's chosen settlement speed
  • [ ] Duplicate payment detection is in place (idempotency key or dedup window of 60 s)
  • [ ] Failed payments are retried with exponential backoff, not immediate re-submission

---

Phase 5 — Standards & Roadmap Alignment

CBUAE's Open Finance roadmap is published in phases (R1–R5). Knowing which phase covers your use case prevents building against APIs that aren't yet live.

✅ 5.1 Query the Standards Reference

const res = await fetch('https://khaleejiapi.dev/api/v1/openfinance/standards', {
  headers: { 'Authorization': '' },
});
const { data } = await res.json();
// Returns: roadmap phases R1–R5 with deadlines, scope, and status
Checklist items:
  • [ ] Confirm the APIs your application depends on are in a phase with status: "live"
  • [ ] Subscribe to CBUAE standards updates — breaking changes are announced per phase
  • [ ] Pin your integration to a specific phase version to avoid unexpected schema changes

---

Phase 6 — Islamic Finance Compliance

For UAE FinTechs operating under Sharia-compliant mandates, regulatory compliance extends beyond CBUAE's technical framework to Sharia supervisory board requirements.

✅ 6.1 Zakat Calculation

Zakat obligations must be calculated using current nisab thresholds derived from live gold and silver spot prices. Hardcoded nisab values are a Sharia audit finding.

const res = await fetch('https://khaleejiapi.dev/api/v1/zakat/calculate', {
  method: 'POST',
  headers: { 'Authorization': '', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    assets: { cash: 50000, gold: 100, silver: 500, investments: 25000 },
    currency: 'AED',
  }),
});
const { data } = await res.json();
// { zakatDue: 1875.00, nisabMet: true, zakatRate: 0.025, goldPriceAED: 287.50 }
Checklist items:
  • [ ] Zakat calculations use live gold/silver prices — never hardcoded nisab values
  • [ ] Display the nisab threshold and spot prices used to the customer for transparency
  • [ ] Refresh zakat calculations at the start of every new Hijri lunar year

✅ 6.2 Sukuk Tracking

const res = await fetch('https://khaleejiapi.dev/api/v1/sukuk?region=uae', {
  headers: { 'Authorization': '' },
});
const { data } = await res.json();
// Returns 12+ active GCC sukuk with yield, maturity, and Sharia board details
Checklist items:
  • [ ] Sukuk reference data includes Sharia board name and certification date
  • [ ] Maturity dates are calculated using the Hijri calendar where contractually specified
  • [ ] Profit distributions are calculated using the correct Hijri lunar month boundaries

---

Phase 7 — Security, Audit & Data Residency

CBUAE Open Finance requires comprehensive audit logging for every data access event. The UAE Personal Data Protection Law (PDPL, Federal Decree-Law No. 45/2021) adds data minimisation and residency obligations that sit alongside the CBUAE framework.

Checklist items:

Audit Logging

  • [ ] Every data access event emits a structured log entry: timestamp, user pseudonym, consent ID, data types accessed, LFI endpoint called
  • [ ] Audit logs are immutable — stored in append-only storage (not a mutable database table)
  • [ ] Logs are retained for a minimum of 5 years
  • [ ] Log storage location is within the UAE (AE) — not shared with US/EU regions

Data Residency

  • [ ] Customer financial data is stored exclusively in UAE-based infrastructure (dataStorageLocation: "AE")
  • [ ] No UAE customer PII is processed in regions outside the UAE without explicit PDPL-compliant cross-border transfer consent
  • [ ] Cloud provider region is documented and disclosed to the CBUAE licensing team

Security Controls

  • [ ] All API communication uses TLS 1.2 or higher (TLS 1.3 recommended)
  • [ ] API keys and OAuth tokens are never logged or included in error responses
  • [ ] Rate limiting is enforced on all consent and payment endpoints
  • [ ] HMAC-SHA256 webhook signatures are verified before processing inbound events
  • [ ] Penetration testing completed by a CBUAE-recognised security firm before go-live

---

Complete Pre-Launch Checklist (Quick Reference)

Copy this into your sprint board or CI gate:

IDENTITY & VALIDATION
[ ] Emirates ID validated at KYC entry point
[ ] All IBANs validated before payment initiation
[ ] TRN validated for every B2B VAT flow

PARTICIPANT DIRECTORY [ ] Target LFI confirmed active via /openfinance/participants [ ] LFI phase covers required data scope [ ] Directory refreshed within last 24 hours

CONSENT (Article 22) [ ] Consent score ≥ 90 from /openfinance/consent/validate [ ] Purpose is specific and human-readable [ ] Data storage location = "AE" [ ] Withdrawal accessible within 3 taps [ ] Duration ≤ 12 months [ ] Consent records retained ≥ 5 years

PAYMENTS (ISO 20022) [ ] Payment payload passes /openfinance/payment/validate [ ] Correct payment scheme selected (Aani / UAEFTS / SWIFT) [ ] Duplicate detection implemented (idempotency key)

ISLAMIC FINANCE [ ] Zakat uses live gold/silver prices [ ] Sukuk data includes Sharia certification

SECURITY & AUDIT [ ] Audit log on every data access event [ ] Logs immutable, in-UAE, retained ≥ 5 years [ ] TLS 1.2+ enforced [ ] Pen test completed

Automate the Checks with KhaleejiAPI

All four CBUAE Open Finance endpoints are available on the free tier — 1,000 requests/month, no credit card required. Run them in parallel to minimise latency:

const [participants, consentResult, paymentResult] = await Promise.all([
  fetch('https://khaleejiapi.dev/api/v1/openfinance/participants?type=bank&status=active',
    { headers: { 'Authorization': '' } }
  ).then(r => r.json()),
  fetch('https://khaleejiapi.dev/api/v1/openfinance/consent/validate', {
    method: 'POST',
    headers: { 'Authorization': '', 'Content-Type': 'application/json' },
    body: JSON.stringify(myConsentPayload),
  }).then(r => r.json()),
  fetch('https://khaleejiapi.dev/api/v1/openfinance/payment/validate', {
    method: 'POST',
    headers: { 'Authorization': '', 'Content-Type': 'application/json' },
    body: JSON.stringify(myPaymentPayload),
  }).then(r => r.json()),
]);

const isCompliant = participants.data.some((p: { id: string; status: string }) => p.id === targetLfiId && p.status === 'active') && consentResult.data.compliant && consentResult.data.score >= 90 && paymentResult.data.valid;

Running all three checks in parallel adds fewer than 100 ms to your pre-submission flow — a worthwhile investment that prevents costly LFI rejections and regulatory findings.

Sign up for a free API key →