Delegated SCA — Requirements v2.111 min read
The Authentication requirements, Authorization requirements, and User Journeys must be adhered to.
The tables below list the rules that apply to Delegated SCA. All request validation of the TPP's credentials, access token, and consent is performed by the Hub before your Ozone Connect endpoint is called. The rules below cover what your Ozone Connect endpoint must validate and what it must return.
Consent Validation
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 customer is involved — there is no authentication or authorization at this stage. The purpose is to reject consents early that your systems cannot fulfil.
standardVersionstandardVersion (a top-level property on the consent object) is the URL path version the TPP will call on subsequent payment initiation requests. If you do not support that version for the Payment Initiation 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).consent.PersonalIdentifiableInformationinvalid.Initiation.DebtorAccountinvalid.Initiation.CreditorInitiation.Creditor is optional. If provided, it must contain 1–10 creditor entries. Validate that each creditor is a valid UAE domestic creditor — the account is reachable on a supported UAE domestic rail (AANI or UAEFTS) and, where the state of the receiving account can be determined, able to receive payments. Mandatory fields, IBAN, and BIC derivation rules apply to every entry — see Creditor. If any check fails, respond with invalid.ApiMetadata.DelegatedAuthentication.SingleBeneficiarySupported (exactly 1 creditor entry), ApiMetadata.DelegatedAuthentication.MultipleBeneficiariesSupported (2–10 entries), or ApiMetadata.DelegatedAuthentication.OpenBeneficiariesSupported (Initiation.Creditor omitted). If the LFI has not advertised support for the requested beneficiary model, respond with invalid.BaseConsentIdBaseConsentId, validate that:- The
BaseConsentIdreferences an existing consent known to the LFI and belonging to the same end user. - The referenced consent is a Service Initiation consent (
authorization_details[0].typeisurn:openfinanceuae:service-initiation-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. TheBaseConsentIdmust always reference the original root consent.
invalid.consent.CurrencyRequestCurrencyRequest is for non-local currency and international transfers. If present, respond with invalid.Payment Execution
/paymentsWhen the TPP initiates a payment under an authorized consent, the API Hub validates the access token, consent status, amount/currency consistency with the consent, and OpenAPI schema before forwarding the request to your Ozone Connect POST /payments endpoint. The rules below cover what your Ozone Connect endpoint must validate on receipt. Error responses MUST conform to the POST /payments OpenAPI schema — the errorCode values referenced below are drawn from the error schema matching the returned HTTP status (Error400, Error403, or Error409). Delegated SCA delegates strong customer authentication to the TPP, so the LFI MUST additionally verify the SCA proof delivered in the Risk block and the customer-present headers before executing the payment.
PersonalIdentifiableInformationPOST /payments). Note that DebtorAccount is not part of the payment-time PII (the debtor is fixed by the consent) and Initiation.Creditor is a single object rather than an array. Reject with HTTP 400 and:errorCode:JWE.DecryptionError— if decryption of the PII payload fails.errorCode:Body.InvalidFormat— if any required property is missing, of the wrong type, or the payload contains additional or undocumented properties (additionalProperties: false).
PersonalIdentifiableInformation (Creditor)Initiation.Creditor entirely (the "open beneficiaries" model).If
Initiation.Creditor was provided at consent time, the submitted creditor on the payment request MUST exactly match one of the 1–10 consent-time entries — see Creditor for the match rules. If it matches none of the entries, reject with HTTP 400 errorCode: Consent.FailsControlParameters.If
Initiation.Creditor was omitted at consent time, the creditor validation that would normally run at consent-validate MUST be performed here instead. The LFI MUST validate that the submitted creditor is a valid UAE domestic creditor — the account is reachable on a supported UAE domestic rail (AANI or UAEFTS) and, where the state of the receiving account can be determined, able to receive payments. Mandatory fields, IBAN, and BIC derivation rules apply. If any check fails, reject with HTTP 400 errorCode: Consent.FailsControlParameters.Risk.DebtorIndicators.AuthenticationChallengeOutcome MUST be Pass, AuthenticationFlow MUST be MFA, and at least two of PossessionFactor.IsUsed, KnowledgeFactor.IsUsed, or InherenceFactor.IsUsed MUST be true with a valid Type set on each. ChallengeDateTime MUST be recent relative to the payment request. If any of these conditions are not met, reject with HTTP 400 errorCode: Consent.FailsControlParameters.x-fapi-auth-dateTue, 11 Sep 2012 19:43:31 UTC. If missing or malformed, reject with HTTP 400 errorCode: Body.InvalidFormat.x-fapi-customer-ip-address400 errorCode: Body.InvalidFormat.Initiation.InstructedAmount at the time the payment is received, taking into account any holds, pending transactions, and overdraft limits applied by the LFI. If the account has insufficient funds, reject with HTTP 400 errorCode: GenericError and errorMessage: Payment rejected due to insufficient funds.Inactive, Dormant, or Suspended, reject with HTTP 403 errorCode: Consent.AccountTemporarilyBlocked and errorMessage: The account is temporarily blocked.Closed, Deceased, or Unclaimed since consent authorization, reject with HTTP 403 errorCode: Consent.PermanentAccountAccessFailure and errorMessage: The account is permanently inaccessible.Initiation.Creditor and the same Initiation.InstructedAmount (currency and value) is currently in Pending status. If so, reject the new payment as a duplicate with HTTP 409 errorCode: Payment.DuplicateInFlight and errorMessage: A payment with the same creditor and amount is already in flight under this consent. Once the prior payment has left Pending (reached AcceptedSettlementCompleted, AcceptedCreditSettlementCompleted, AcceptedWithoutPosting, or Rejected), a subsequent identical payment is permitted.This check is distinct from
x-idempotency-key handling — idempotency keys protect against network-retry of the same request, whereas this rule catches genuinely duplicate payment intents submitted under different keys.If all validations above pass, the LFI MUST create the payment record in its systems and return HTTP 201 with the generated PaymentId per the POST /payments OpenAPI schema. Full response handling is covered in the API Guide.
Screening Checks
Once the payment record has been created, the LFI MUST apply its standard fraud, sanctions, and AML screening controls before the payment is submitted to the domestic rail. These checks are the LFI's responsibility and follow the LFI's own policies and regulatory obligations. Screening may result in the payment being held, rejected, or referred for manual review after the 201 response has been returned to the TPP. The outcome MUST be reflected in the payment's Status and surfaced via GET /payments/{paymentId} so the TPP can observe the final state.
Pending and the final outcome is reflected when available. A payment MUST NOT be rejected solely because screening exceeded 3 seconds.PATCH /payment-log/{id} on the API Hub Consent Manager with paymentResponse.status: Rejected and a paymentResponse.RejectReasonCode entry. The entry's Code MUST use the LFI. namespace (the check that failed is in the LFI's systems, not AANI or UAEFTS), matching the pattern ^LFI\.[A-Za-z0-9]+$. The Message MUST be sanitised for onward relay to the TPP — it MUST NOT reveal detection logic, sanctions list matches, or internal case identifiers.Example:
Code: LFI.ScreeningRejectedMessage: Payment rejected by LFI screening controls.Rail Submission
Once the payment has passed screening, the LFI MUST submit it to the domestic rails for processing. AANI is the primary rail for Delegated SCA payments; UAEFTS is the fallback.
PATCH /payment-log/{id} on the API Hub Consent Manager to update paymentResponse.status to the new Open Finance status. Rail statuses that are deliberately not mapped (see Payment Status) do not require a PATCH; the mapping document is the source of truth for which rail transitions are reportable.paymentTransactionId propagationpaymentTransactionId on the next PATCH /payment-log/{id} — ideally on the same PATCH as the accompanying status transition. Once set, paymentTransactionId MUST NOT be changed. Note that paymentTransactionId identifies the payment instruction on the rail and is distinct from the Bank Data Sharing transactionId (which identifies a ledger entry).paymentResponse.RejectReasonCode on the PATCH /payment-log/{id} call. The Code MUST use the namespace of the rail that rejected the payment (AANI. or FTS., matching the spec pattern ^(AANI|FTS)\.[A-Za-z0-9]+$), with the specific reason code mapped directly from the rail's originating rejection code. The Message MUST be sanitised for onward relay to the TPP.Example:
Code: AANI.AM04Message: Payment request cannot be executed as insufficient funds at debtor account.PATCH /payment-log/{id} deliverystatus, paymentTransactionId, and RejectReasonCode changes cannot be dropped. If a PATCH fails with a transient error (HTTP 5xx, connection error, or timeout), the LFI MUST retry with exponential backoff until the update is accepted; updates that cannot be delivered immediately MUST be queued and retried rather than abandoned. A PATCH rejected with a 4xx response indicates a client-side issue that retry will not fix — the LFI MUST NOT retry in this case and MUST raise the failure for operational investigation.Payment Status Retrieval
/payments/{paymentId}The TPP may use GET /payments/{paymentId} to retrieve the current status of a payment it has initiated. The API Hub validates the access token and consent, then forwards the request to your Ozone Connect endpoint.
GET /payments/{paymentId} for at least 1 year from the creation date of the payment. Within this window, the endpoint MUST return the current Status of the payment, reflecting any subsequent state changes (e.g. screening outcomes, rail settlement, reversal).Status returned by GET /payments/{paymentId} MUST exactly match the status most recently PATCHed to the API Hub Consent Manager via PATCH /payment-log/{id}. The LFI is responsible for keeping the two representations in lockstep — any status change in the LFI's systems MUST be reflected on both surfaces before the change is observable to the TPP.paymentTransactionId consistencyGET /payments/{paymentId} MUST return the same paymentTransactionId. Before the rail has assigned one, paymentTransactionId MUST be omitted from the response rather than returned as an empty string.