INTRODUCTION

You have designed the resources, written the OpenAPI contract, implemented idempotency, pagination, error handling, and discovery. But a single question remains: does your implementation actually match the contract? And more critically: will it stay matched after six months of feature additions and refactors?

In open banking, the OpenAPI contract is not documentation—it is a legal promise. The CMA can audit your API against the published OBIE specification. If your implementation deviates, you are in breach. The only way to guarantee continuous compliance is automated contract testing.

This lesson teaches you to build a compliance pipeline. You will implement mock servers (using Prism or WireMock) that simulate the ASPSP for TPP development, run contract tests (using Pact or OpenAPI‑based tools) that verify your implementation against the spec, and enforce compliance gates in your CI/CD pipeline that block deployments if the contract is violated.

We will quantify the testing overhead (full test suite runs in ~5 minutes on a CI agent, acceptable for every PR) and the cost of a compliance breach (estimated at £500,000 per incident, including remediation and regulatory fines).


LEARNING OBJECTIVES

  1. Implement a mock server using Prism (OpenAPI‑based mocking) that returns realistic responses based on the OpenAPI specification, including support for example values and x‑examples to simulate error cases.

  2. Design a contract‑first testing strategy—using openapi‑validator middleware in the test environment that validates every incoming request and outgoing response against the OpenAPI schema, failing the test suite if any deviation is detected.

  3. Construct consumer‑driven contract tests (Pact)—where the TPP (consumer) defines the expected request/response pairs, and the ASPSP (provider) verifies that their implementation satisfies those expectations, ensuring backward compatibility.

  4. Calculate the compliance gate execution time—measuring the runtime of the full test suite (integration tests + contract tests + schema validation) at 4.5 minutes (p95), fitting comfortably within a 15‑minute CI build window.

  5. Articulate the regulatory audit trail—demonstrating how the test results (including passing/failing logs) serve as evidence to regulators that the API is compliant with the OBIE v4.0 or CDR v1.4.0 specification.


PART 1: MOCK SERVERS — Simulating the ASPSP for TPP Development

1.1 Why Mock Servers?

TPPs cannot develop against a live ASPSP during early integration—it’s expensive, slow, and risky (they might accidentally initiate real payments). A mock server provides a sandbox that replicates the ASPSP’s behaviour, returning realistic but synthetic data.

1.2 Prism — OpenAPI Native Mocking

Prism (by Stoplight) generates a mock server directly from your OpenAPI file. It uses the example and x‑examples fields to generate realistic responses.

Installation:

bash
npm install -g @stoplight/prism-cli

Mock Server Command:

bash
prism mock openapi-bundled.yaml --port 4010

Example OpenAPI snippet with example :

yaml
schemas:
  Transaction:
    type: object
    properties:
      id:
        type: string
        example: "txn-abc-123"
      amount:
        type: number
        example: 100.00
      bookingDate:
        type: string
        format: date-time
        example: "2026-08-01T12:34:56Z"

Prism Behaviour:

  • GET /accounts/acc-123/transactions → returns a list of mock transactions.

  • POST /payments → returns a 201 Created with a mock payment ID.

  • Error simulation: If the TPP sends an invalid request, Prism returns a 400 with an error response (based on the OpenAPI responses definition).

Latency overhead of mock server: Prism returns responses in ~5‑10ms (p95) because it does not invoke a real database. This is perfect for TPP integration testing.

1.3 WireMock — Advanced Stubbing

For more complex scenarios (e.g., simulating a specific payment failure, or returning a specific Location header), use WireMock.

Example WireMock stub:

json
{
  "request": {
    "method": "POST",
    "urlPath": "/payments",
    "headers": {
      "x-idempotency-key": { "matches": "^pay-.*$" }
    },
    "bodyPatterns": [
      { "matchesJsonPath": "$.Data.Amount" }
    ]
  },
  "response": {
    "status": 201,
    "headers": {
      "Location": "http://localhost:4010/payments/pay-123"
    },
    "body": "{\"Data\":{\"PaymentId\":\"pay-123\",\"Status\":\"Pending\"}}"
  }
}

PART 2: CONTRACT VALIDATION — The Compliance Gate

2.1 The OpenAPI Validator Middleware

In the test environment (and optionally in production for debugging), implement an OpenAPI validation middleware that checks every request and response against the bundled OpenAPI spec.

Python (Flask) Implementation:

python
from openapi_core import create_spec
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator

# Load the bundled OpenAPI spec
spec = create_spec('openapi-bundled.yaml')
request_validator = RequestValidator(spec)
response_validator = ResponseValidator(spec)

@app.before_request
def validate_request():
    request_data = {
        'path': request.path,
        'method': request.method,
        'headers': request.headers,
        'body': request.get_json()
    }
    try:
        request_validator.validate(request_data)
    except Exception as e:
        return jsonify({"ErrorCode": "SCHEMA_VIOLATION", "detail": str(e)}), 400

@app.after_request
def validate_response(response):
    response_data = {
        'status_code': response.status_code,
        'headers': response.headers,
        'body': response.get_json()
    }
    try:
        response_validator.validate(response_data)
    except Exception as e:
        # Log the violation but do not fail the request
        app.logger.error(f"Response schema violation: {e}")
    return response

2.2 CI/CD Compliance Gate

In your CI pipeline (e.g., GitHub Actions, Jenkins), add a step that runs the full test suite and validates that all endpoints satisfy the OpenAPI contract.

yaml
# .github/workflows/ci.yml
steps:
  - name: Run Integration Tests
    run: pytest tests/

  - name: Validate OpenAPI Contract
    run: |
      # Spin up the API server (test environment)
      docker-compose -f docker-compose.test.yml up -d

      # Run contract validation suite
      npm run test:contract

      # Check for compliance breaches
      if grep -q "SCHEMA_VIOLATION" test-output.log; then
        echo "Compliance breach detected!"
        exit 1
      fi

Execution time: The full test suite (integration + contract) runs in ~4.5 minutes (p95) on a 4‑core CI agent.


PART 3: CONSUMER‑DRIVEN CONTRACT TESTING (PACT)

3.1 The Pact Flow

Pact is a consumer‑driven contract testing tool. The TPP (consumer) defines the expected request/response pairs. The ASPSP (provider) verifies that it can satisfy those expectations.

Advantage: If the ASPSP changes its API (e.g., adds a new mandatory field), the Pact verification fails, alerting the ASPSP that TPPs will break.

text
+-----------------------------------------------------------------------+
|                    PACT CONTRACT TESTING FLOW                          |
+-----------------------------------------------------------------------+
|                                                                        |
|  TPP (Consumer)                    ASPSP (Provider)                    |
|     |                                  |                               |
|     |--(1) Write Pact test----------->|                               |
|     |  (defines expected request/     |                               |
|     |   response)                     |                               |
|     |                                  |                               |
|     |<-(2) Generate Pact file---------|                               |
|     |  (pacts/consumer-aspsp.json)    |                               |
|     |                                  |                               |
|     |                                  |                               |
|     |--(3) Submit Pact file----------->|                               |
|     |  (via Pact Broker)              |                               |
|     |                                  |                               |
|     |                                  |--(4) Run Provider Tests----->|
|     |                                  |   (verify that the actual   |
|     |                                  |    API satisfies the Pact)  |
|     |                                  |                               |
|     |                                  |<-(5) Verification result-----|
|     |                                  |   (pass/fail)               |
|     |                                  |                               |
+-----------------------------------------------------------------------+

3.2 Pact Example (Python — Consumer Side)

python
import pact
from pact import Consumer, Provider
import requests

pact = Consumer('TPP_App').has_pact_with(Provider('Bank_ASPSP'))

@pact.given('User has a valid account')
@pact.upon_receiving('a request for transactions')
@pact.with_request(
    method='GET',
    path='/accounts/acc-123/transactions',
    headers={'Authorization': 'Bearer token'}
)
@pact.will_respond_with(
    status=200,
    body={
        'data': {
            'transaction': [
                {'id': 'txn-1', 'amount': 100.00, 'bookingDate': '2026-08-01'}
            ]
        },
        'links': {'self': '/accounts/acc-123/transactions?limit=100'}
    }
)
def test_get_transactions():
    with pact:
        response = requests.get(
            f"{pact.uri}/accounts/acc-123/transactions",
            headers={'Authorization': 'Bearer token'}
        )
    assert response.status_code == 200

Verification (Provider side) : The ASPSP runs the Pact verification tool, which replays the requests defined in the Pact file and compares the actual responses against the expected responses.


PART 4: THE REGULATORY AUDIT TRAIL — Proving Compliance

4.1 The Compliance Evidence Bundle

When the regulator asks, “How do you know your API is compliant?”, the certified practitioner presents:

  1. The OpenAPI contract (Git commit hash, timestamp).

  2. The CI/CD pipeline logs (showing that all contract tests passed before deployment).

  3. The Pact verification report (showing that all consumer contracts are satisfied).

  4. The audit logs from the API gateway (showing that the deployed version matches the contract).

4.2 Automated Reporting

Generate a compliance report after every CI run:

json
{
  "timestamp": "2026-08-03T12:34:56Z",
  "openapi_file": "openapi-bundled.yaml",
  "openapi_hash": "a7f3e8d9c1b2...",
  "validation_results": {
    "total_endpoints": 12,
    "passing": 12,
    "failing": 0
  },
  "pact_results": {
    "total_consumers": 3,
    "verified": 3,
    "failed": 0
  },
  "deployment_environment": "production",
  "api_version": "v4.0.0"
}

Regulatory value: This report serves as prima facie evidence that the ASPSP is compliant with the OBIE v4.0 or CDR specification. It significantly reduces the burden of a manual audit.

Â