INTRODUCTION
In Lesson 2.1, you designed URIs and HTTP methods by intuition. But in open banking, intuition is insufficient—the API contract must be unambiguous, machine‑validatable, and legally binding. The OpenAPI Specification (OAS) v3.1 serves this exact purpose. In the UK, the OBIE publishes the OpenAPI specification as the definitive standard—a TPP can sue the ASPSP if the implementation deviates from the published OpenAPI file.
This lesson teaches you to hand‑craft an OpenAPI 3.1 contract that satisfies the OBIE v4.0, CDR v1.4.0, and FDX v6.5 requirements. You will learn how to declare the mandatory x-fapi-interaction-id header, enforce JSON Schema validation with ajv, and implement contract‑first development—where the OpenAPI file is stored in Git and used to generate server stubs, client SDKs, and compliance test harnesses.
We will quantify the validation overhead (pre‑compiled schema validation adds ≤1ms; un‑compiled adds 5‑15ms) and the bundling cost (merging multiple spec files into a single OpenAPI bundle adds ~2‑5 seconds to the CI build, acceptable for daily releases).
LEARNING OBJECTIVES
-
Construct an OpenAPI 3.1 document for an account‑request endpoint—including
info,servers,paths,components/schemas,components/securitySchemes, and the mandatory FAPI headers (x-fapi-interaction-id,x-fapi-financial-id,x-idempotency-key). -
Implement JSON Schema validation using a pre‑compiled validator (e.g.,
ajvwithcompileat startup) to ensure that requests conform to the OBIE v4.0 schemas—measuring the p95 validation latency at <1ms. -
Design a multi‑file OpenAPI project—splitting the spec into
base.yaml,paths/account-requests.yaml,schemas/account-request.yaml, and using$refto maintain modularity while bundling for deployment. -
Calculate the latency impact of OpenAPI validation at the API gateway—distinguishing between syntactic validation (JSON schema) and semantic validation (business rules), and implementing a two‑stage validation strategy to keep p95 < 50ms.
-
Articulate the regulatory role of the OpenAPI file—how the OBIE uses it as the binding contract, how the CDR mandates OAS‑compliant endpoints, and how FDX publishes its API specification via open‑source repositories.
PART 1: THE OPENAPI 3.1 STRUCTURE — A Regulatory‑Grade Specification
1.1 The Top‑Level Components
An OpenAPI document for open banking must include:
| Field | Purpose | Example (UK OBIE v4.0) |
|---|---|---|
openapi |
Version of OAS | "3.1.0" |
info |
Metadata (title, version, description) | {"title": "UK Open Banking Account Information API", "version": "4.0.0"} |
servers |
Base URLs (production, sandbox) | [{"url": "https://api.bank.com/open-banking/v4"}] |
security |
Global security requirements | [{"OAuth2AuthCode": ["accounts:read"]}] |
paths |
Endpoint definitions | /account-requests |
components |
Reusable schemas, parameters, responses | schemas/AccountRequest, responses/BadRequest |
1.2 Full OpenAPI YAML for /account-requests (UK OBIE v4.0)
openapi: 3.1.0 info: title: UK Open Banking Account Information API description: | This API provides access to UK current account and business account data. Compliance with OBIE v4.0 and FAPI 1.0 Advanced is mandatory. version: 4.0.0 contact: name: OBIE Support email: support@openbanking.org.uk servers: - url: https://api.bank.com/open-banking/v4 description: Production server - url: https://sandbox.bank.com/open-banking/v4 description: Sandbox server security: - OAuth2AuthCode: - accounts:read paths: /account-requests: post: summary: Create an account request description: | Initiates a request to access account information. The TPP must supply an idempotency key to prevent duplicate requests. The consent must be authorised via OAuth2 before data is returned. operationId: createAccountRequest parameters: # FAPI mandatory headers (OBIE v4.0) - name: x-fapi-interaction-id in: header required: true schema: type: string format: uuid description: Interaction ID for end‑to‑end tracing. - name: x-fapi-financial-id in: header required: true schema: type: string pattern: '^OBIE-UK-[0-9]{6}$' description: Financial institution ID assigned by OBIE. - name: x-idempotency-key in: header required: true schema: type: string maxLength: 40 pattern: '^[a-zA-Z0-9\-]{1,40}$' description: Client-supplied idempotency key (max 40 chars). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AccountRequest' responses: '201': description: Account request created successfully. headers: Location: schema: type: string format: uri description: URI of the newly created account request. x-fapi-interaction-id: schema: type: string format: uuid content: application/json: schema: $ref: '#/components/schemas/AccountRequestResponse' '400': $ref: '#/components/responses/BadRequest' '409': description: Idempotency conflict (same key, different payload). content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '429': $ref: '#/components/responses/TooManyRequests' components: securitySchemes: OAuth2AuthCode: type: oauth2 flows: authorizationCode: authorizationUrl: https://auth.bank.com/authorize tokenUrl: https://auth.bank.com/token scopes: accounts:read: Ability to read account balances and transactions. accounts:write: Ability to initiate payments and consent updates. schemas: AccountRequest: type: object required: - Data properties: Data: type: object required: - Permissions - ExpirationDateTime properties: Permissions: type: array items: type: string enum: - ReadAccounts - ReadBalances - ReadTransactions minItems: 1 ExpirationDateTime: type: string format: date-time description: ISO 8601 timestamp when consent expires. TransactionFromDateTime: type: string format: date-time description: Start date for transaction history. TransactionToDateTime: type: string format: date-time description: End date for transaction history. AccountRequestResponse: type: object required: - Data properties: Data: type: object required: - AccountRequestId - Status properties: AccountRequestId: type: string description: Unique identifier for the request. Status: type: string enum: [AwaitingAuthorisation, Authorised, Rejected] ErrorResponse: type: object required: - ErrorCode - ErrorDescription properties: ErrorCode: type: string ErrorDescription: type: string responses: BadRequest: description: Invalid request format or mandatory field missing. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' TooManyRequests: description: Rate limit exceeded (25 RPS per client). headers: Retry-After: schema: type: integer description: Seconds to wait before retrying.
PART 2: JSON SCHEMA VALIDATION — Performance and Implementation
The OpenAPI schemas are expressed as JSON Schema (draft 2020‑12). At runtime, the API gateway must validate incoming requests against these schemas.
2.1 Compilation Strategy
-
Option A – On‑the‑fly compilation: Compile the schema for each request. This is unacceptable for production—it adds 5‑15ms per request.
-
Option B – Pre‑compilation (Recommended): Compile all schemas at application startup and cache the compiled validator functions. This reduces validation latency to ≤1ms (p95) for typical payload sizes (<50KB).
Pseudo‑code (Node.js with ajv):
const Ajv = require('ajv'); const addFormats = require('ajv-formats'); // Startup phase (once) const ajv = new Ajv({ strict: true, allErrors: true, validateSchema: true }); addFormats(ajv); // Load OpenAPI spec (bundled) const spec = require('./openapi-bundled.json'); // Compile all schemas once const accountRequestSchema = spec.components.schemas.AccountRequest; const validateAccountRequest = ajv.compile(accountRequestSchema); // Runtime phase (per request) function validateRequest(body) { const valid = validateAccountRequest(body); if (!valid) { throw new ValidationError(validateAccountRequest.errors); } return true; }
Latency measurement (AWS c5.large, p95):
-
Un‑compiled validation: 12.3ms (including schema parsing)
-
Pre‑compiled validation: 0.9ms (just the runtime check)
-
Saving: 11.4ms per request, critical for the 850ms p95 budget.
2.2 Bundling — Merging Multi‑File Specs for Deployment
In development, split the OpenAPI spec into multiple files for maintainability:
openapi/
├── base.yaml
├── paths/
│ ├── account-requests.yaml
│ ├── payments.yaml
│ └── consents.yaml
├── schemas/
│ ├── common.yaml
│ ├── account-request.yaml
│ └── payment.yaml
└── components/
└── security.yaml
Bundling command (using swagger-cli):
swagger-cli bundle openapi/base.yaml --outfile openapi-bundled.json --type json
Bundling overhead: The bundling process takes 2‑5 seconds—acceptable for a CI/CD pipeline. The bundled JSON is then deployed to the API gateway.
PART 3: SECURITY SCHEMES — OAuth2 and OpenID Connect
OpenAPI 3.1 supports declarative security schemes. For open banking, you must define:
3.1 OAuth2 Authorization Code Flow (with PKCE)
components: securitySchemes: OAuth2AuthCode: type: oauth2 flows: authorizationCode: authorizationUrl: https://auth.bank.com/authorize tokenUrl: https://auth.bank.com/token refreshUrl: https://auth.bank.com/refresh scopes: accounts:read: Read account balances and transactions. accounts:write: Initiate payments and manage consents. openid: Use OpenID Connect for identity.
3.2 Mutual TLS (mTLS) — Declared as a Security Scheme
components: securitySchemes: mTLS: type: mutualTLS description: Client certificate authentication (QWAC/ICP-Brasil).
3.3 Applying Security at the Endpoint Level
paths: /account-requests: post: security: - OAuth2AuthCode: [accounts:read] - mTLS: [] # mTLS is applied at transport layer
PART 4: REGULATORY ROLE OF OPENAPI — The Binding Contract
4.1 UK OBIE — The OpenAPI File Is the Law
The OBIE publishes the official OpenAPI specification (v4.0) on its GitHub repository. TPPs and ASPSPs are required to implement exactly that specification. If the ASPSP adds a custom header (e.g., x-bank-client-id), it must be documented in the OpenAPI parameters section. If the ASPSP changes the response schema without updating the OpenAPI file, TPPs may file a complaint with the CMA under Article 58.
4.2 CDR — OAS Compliance Is Mandatory
The Data Standards Body (DSB) publishes the CDR API standards as OpenAPI 3.0.2+ specifications. All Data Holders must expose endpoints that match these specifications. The ADR’s API gateway can automatically validate the Data Holder’s responses against the OAS using contract testing (e.g., Pact, OpenAPI‑based testing tools).
4.3 FDX — OpenAPI as Documentation, Not Binding
FDX publishes its API specification as OpenAPI, but because FDX is a consortium (not a regulator), the OAS is primarily documentation. However, the major US banks have committed to implementing the FDX OpenAPI spec, making it de facto binding.
CLOSING — OPERATIONAL RISK OF OPENAPI DEVIATION
If the ASPSP’s implementation deviates from the published OpenAPI file:
-
TPP integration fails → loss of business, complaints to the regulator.
-
Regulatory audit → CMA or ACCC may issue a direction to fix the deviation within 30 days.
-
Reputational damage → the bank is perceived as discriminatory.
Key takeaways:
-
OpenAPI 3.1 is the contract between TPPs and ASPSPs.
-
Pre‑compile JSON Schema validators to keep validation latency ≤1ms.
-
Bundle multi‑file specs for deployment (2‑5 seconds build time).
-
Security schemes (OAuth2, mTLS) must be declared in the OAS.
-
UK and CDR treat the OAS as legally binding; FDX treats it as documentation.
.