Skip to main content

Open banking TPP onboarding: taking a licensed TPP from sandbox to production

Open banking TPP onboarding on Zerq: check authorisation and certificates, issue sandbox and production profiles, run a go-live gate, and offboard cleanly.

  • how-to
  • open-banking
  • developer-portal
  • partners
Zerq team

A payment institution sends your open banking team its authorisation number, a qualified certificate and a testing facility request. Weeks later it wants production. Later, its regulator withdraws its payment initiation permission, and nobody on the platform team watches the register. Open banking TPP onboarding looks like ordinary partner onboarding, but every stage carries a regulatory condition, and several are enforced at the gateway.

In the EU, the RTS on strong customer authentication and secure communication requires a testing facility open to authorised TPPs and applicants, with no sensitive information shared through it. TPPs identify themselves with eIDAS certificates carrying their authorisation number and roles. Production access must not become a registration process: the EBA treats onboarding steps beyond what secure communication technically needs as obstacles. A withdrawn authorisation is published in public registers, and no rule requires the regulator to notify each bank.

So how do banks onboard third party providers for open banking without a second identity system beside the gateway? This guide walks an EU or UK ASPSP through Zerq, from pre-credential checks to offboarding, and marks where Zerq stops: register lookups, TPP certificate validation and consent stay in your PKI, authorization server and own systems. UAE LFIs see a single caller, the API Hub; our UAE open finance LFI guide covers that model.

Why generic partner onboarding breaks for regulated TPPs

Most gateway developer portals assume self-service sign-up: Apigee issues keys to developer apps, Azure API Management issues subscription keys, and Kong's portal registers applications. That fits commercial partners, where the credential is the identity. For a licensed TPP it runs backwards: a regulator and a certificate issuer fix the identity, a sign-up key predates any register check, and a manual approval queue before production is the extra registration the EBA classes as an obstacle.

AWS API Gateway and Azure API Management both check client certificates against a trust store, but neither knows a firm is authorised for account information and not payment initiation, or that its licence was withdrawn yesterday. That mapping usually lives in a spreadsheet, so access outlives licences, while the sandbox runs on a separate stack whose contract drifts from production. The fix is to model the TPP once, give it sandbox and production access contracts, and make the move between them a logged change.

How open banking TPP onboarding maps onto Zerq

The model is one client per TPP, the pattern behind our banking and open banking use case. The client holds identity, collection access, policy and portal settings. Its profiles are the access contracts: a sandbox token profile for functional testing, an optional sandbox-cert profile for certificate testing (Step 3), and a production profile using OIDC with RFC 8705 certificate-bound tokens. Collections follow the certificate's roles, so the gateway enforces the role check.

Certificate role (ETSI TS 119 495)CollectionBase path
PSP_AI, account informationob-accounts/ob/accounts
PSP_PI, payment initiationob-payments/ob/payments
PSP_IC, card-based payment instrumentsob-funds/ob/funds-confirmations
Testing facility, any roleob-sandbox/sandbox

Two Zerq behaviours shape the layout. Collection access and policy belong to the client, not the profile, so a sandbox token is valid on every collection the client holds, and sandbox load tests draw from production's rate-limit bucket. The limiter also runs before authentication, keyed on the X-Client-ID header as sent, so unauthenticated calls carrying a TPP's Client ID count against its limits. Put the environment boundary at the ingress, and rate-limit by source on the sandbox host too.

Use two hostnames. The sandbox host forwards only /sandbox to Zerq. The production host requires a client certificate, validates its chain and revocation status (Zerq does not validate certificates itself), sets X-Client-ID and X-Profile-ID from a lookup keyed on the certificate (an eIDAS subject never contains your Zerq IDs), and forwards the certificate in X-SSL-Client-Cert. Both hosts strip any caller-sent X-Proxy-ID header, which Zerq treats as a test-console call and leaves out of request logs. Every production request therefore runs as the certificate holder's production profile, whatever the caller's headers. Zerq validates the access token, compares its cnf.x5t#S256 thumbprint with the forwarded certificate, applies the profile's methods and the client's collections and policy, then forwards to your core banking adapter.

The ingress must be the only path in. Zerq Copilot for Gateway in the developer portal calls Gateway MCP on the backend directly (DEVELOPER_PORTAL_GATEWAY_BASE_URL) with the selected profile's credential, so a sandbox token used there would reach production collections once assigned; leave portal Copilot off for TPP-facing portals (AI_MODELS unset on the developer-portal service). Validate certificates at the edge on a TPP-only host rather than with the Nginx Proxy Manager example's optional_no_ca setting, and keep the backend off networks where another container could forge X-SSL-Client-Cert.

Step 1: verify authorisation and the certificate before any credential exists

None of this happens in Zerq: the gateway should only see vetted TPPs.

  1. Look the firm up in its home regulator's register and, for EU payment and e-money institutions, the EBA's PSD2 register (the EBA Credit Institution Register for banks acting as TPPs). In the UK, check the FCA register.
  2. Read the certificate. Under ETSI TS 119 495 the subject organizationIdentifier carries the authorisation number (for example, PSDPL-PFSA-1234567890). A QCStatement lists the roles (PSP_AS, PSP_PI, PSP_AI, PSP_IC) and names the regulator. Both must match the register.
  3. Validate the chain to an issuer you accept and check revocation. The EBA leaves the certificate type to the bank but recommends regulators encourage using QWACs and QSealCs in parallel. The production path below identifies TPPs by their QWAC; QSealC signature checks belong in your own services. UK banks must also accept, and publish, at least one other independent form of identification.
  4. Record the authorisation number, roles, certificate serial, fingerprint and date checked.

Applicants may use the testing facility, so sandbox access needs a confirmed application, not a licence. For EU production the eIDAS certificate is sufficient identification, so automate this check.

Step 2: create the policy, the TPP client and the sandbox profile

  1. Go to Policies, click New Policy, and create one policy for every TPP (Name tpp-fair-usage), with Rate limit and Quota matching your published fair usage policy. Click Create.
  2. Go to Clients and click New Client. Set Name to the legal entity and authorisation number, Description to the roles, certificate serial and date checked, and Email to the technical contact. Set Collections to ob-sandbox only and Policy to tpp-fair-usage. Click Create and copy the Client ID.
  3. Zerq creates a default token profile with every client. Open the client's Profiles, edit that profile, set Profile Name to sandbox and Allowed HTTP Methods to GET and POST, then Update Profile.
  4. Confirm ob-sandbox and its proxies are Published and its Target Endpoint points at synthetic data, never customer data.

One shared policy applies the same limits to every TPP. PSD2 also bars treating TPP requests worse than the customer's own without objective reasons: Article 66(4)(c) for payment orders and Article 67(3)(b) for data requests. Size the limits against your customer interface, not only other TPPs. For sizing from capacity and evidencing parity, see open banking API rate limits. The UK Open Banking Standard expects a documented fair usage policy and a 429 when throttling, which Zerq returns.

Step 3: open the ASPSP developer portal to the TPP's engineers

  1. Open the client, click Edit, switch Developer Portal access on, add the TPP engineers' addresses to Authorized emails, and click Save.
  2. Send the TPP the portal URL. Zerq sends no invitations: each engineer requests a short-lived, single-use magic link, and the response never reveals whether an address is registered.
  3. After sign-in, the engineer sees only ob-sandbox, and the Profile selector shows sandbox with a TOKEN badge.
  4. The Auth Headers panel copies X-Client-ID, X-Profile-ID and Authorization; in Try It, Send Request pre-fills them and Send shows status, latency, headers and body.
  5. Download OpenAPI exports the spec as OpenAPI 3.0 or 3.1, which helps meet the RTS duty to give TPPs and applicants the interface documentation free of charge (you still publish a summary on your website).

The EBA's guidelines expect TPPs to test certificate exchange and error messages there, so publish sandbox proxies for error cases. The token profile covers functional testing only. For certificate testing, have the sandbox host request a client certificate (accepting applicants' test certificates and forwarding them in X-SSL-Client-Cert) and add a sandbox-cert profile using OIDC with requireCertificateBoundToken, so TPPs can test token binding before production.

The flow matches our integration partner and vendor onboarding; for a TPP, the portal follows the register check.

Step 4: create the production profile with certificate-bound tokens

For EU production, run Steps 4 and 5 automatically when a TPP with a valid eIDAS certificate first connects or registers its OAuth client, not in a scheduled window. The EBA accepts a registration or certificate-upload step only if it is technically necessary, automated and timely.

Zerq is not your authorization server; it validates tokens your OIDC provider issues. Certificate binding covers the mTLS half of FAPI 2.0's sender-constrained token requirement; DPoP, the non-mTLS alternative, is not supported. Zerq verifies JWT access tokens signed with the RS256 family from your JWKS and does not introspect opaque tokens, while FAPI expects PS256 or ES256 for signed objects, so confirm the gateway verifies a test token from your authorization server.

  1. Open the client's Profiles and click New Profile. Set Profile Name to production, Active on and Allowed HTTP Methods to what the TPP's APIs need (account information still needs POST, and DELETE in the UK, for consent resources) and scope roles with collections. Leave IP Address Restrictions empty: Zerq sees the ingress's address, not the TPP's, so enforce egress ranges at the ingress. Click Create Profile, then click Manage Authentication on the profile row and set Authentication Type to OpenID Connect.
  2. Set requireCertificateBoundToken through the management API or the Management MCP update_profile tool. There is no dashboard toggle yet, and only OIDC profiles accept the flag.
  3. In Keycloak, enable OAuth Mutual TLS Certificate Bound Access Tokens in the TPP client's Advanced settings. Without it, every call fails with 401.
  4. Set MTLS_CLIENT_CERT_HEADER=X-SSL-Client-Cert and GATEWAY_ENABLE_CACHE=false in the backend service's environment; the shipped default caches GET responses ahead of authentication, workflows and logging.
  5. Add the TPP's certificate to the production ingress lookup, mapped to this Client ID and production Profile ID.

The two profiles in the management API's field names (YAML only to allow comments):

# Sandbox: testing facility, synthetic data
name: sandbox
clientId: 66f1c2a9e4b0a1d2c3f4a5b6   # the TPP's client
authType: token                      # opaque bearer token issued by Zerq
allowedMethods: [GET, POST]
allowedIPs: []                       # any source address
active: true
---
# Production: live traffic
name: production
clientId: 66f1c2a9e4b0a1d2c3f4a5b6   # same client: same collections, same policy
authType: oidc                       # token from your authorization server
allowedMethods: [GET, POST]          # scope by collection; AIS consents also need POST
allowedIPs: []                       # egress ranges enforced at the ingress
active: true
requireCertificateBoundToken: true   # token cnf must match the certificate

The flag is a partial update needing a modifier or admin management token:

curl -X PUT "https://zerq-api.bank.example/api/v1/clients/$CLIENT_ID/profiles/$PROD_PROFILE_ID" \
  -H "Authorization: Bearer $MGMT_OIDC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requireCertificateBoundToken": true}'

Through Management MCP, the same change is update_profile with client_id, id and requireCertificateBoundToken: true. For certificate-authenticated access without bound tokens, a plain mtls profile is simpler; see our mTLS setup guide.

Don't assign production collections yet. A correctly bound call now passes authentication and gets 404 (path outside its collections), proving token, certificate and headers line up without releasing data.

Step 5: run the go-live gate

The gate is your own automated configuration test, not a TPP approval queue. Because the TPP holds its private key, either it runs the gate calls with its certificate and a token from your authorization server against a test account, or you run them with a bank-owned test certificate mapped to a test client with identical profile settings. Use curl with --cert and --key.

  1. Send a bound production call to /ob/accounts/accounts and expect 404.
  2. As soon as the automated checks pass, open the client, click Edit, check only the collections matching the certificate roles, and click Save.
  3. Run each call in the table below.
  4. Go to Logs, filter by Client ID, and confirm each call's Profile ID and status.
  5. Have an Auditor pull the Audit Logs entries for the client and profile changes into the change record.
CallExpected
Bound token for a test account, matching certificate, GET /ob/accounts/accounts200
Same token with another accepted, mapped certificate401
Sandbox token sent to the production host with the TPP's certificate401
PUT on a profile that does not allow it405
Account-information-only TPP calling GET /ob/payments/{id}404
Call from outside the TPP's egress range403 (from the ingress)
Burst above tpp-fair-usage429

The sandbox token fails there because the ingress pins the production profile and an opaque Zerq token is not OIDC. In the request log, sandbox and production calls share a Client ID and differ by Profile ID:

Request ID       7c0e2b1f-4d1a-4f0e-9a51-2f8d3c6b9e10
Method           GET
Path             /sandbox/accounts
Target endpoint  https://ob-sandbox.internal/accounts
Status code      200
Client ID        66f1c2a9e4b0a1d2c3f4a5b6
Profile ID       66f1c2b4e4b0a1d2c3f4a5c1   (sandbox)
Collection       ob-sandbox

Request ID       e41a9d02-6b7c-4c3e-8f15-0a2b9c7d4e61
Method           GET
Path             /ob/accounts/accounts
Target endpoint  https://ob-core.internal/accounts
Status code      200
Client ID        66f1c2a9e4b0a1d2c3f4a5b6
Profile ID       66f1c2c7e4b0a1d2c3f4a5d9   (production)
Collection       ob-accounts

Denied calls log the same IDs with their 401, 403 or 405. Our observability page covers the log and audit views.

Go-live checklist

  • Register entry and certificate roles re-checked on the go-live date.
  • Certificate fingerprint in the production ingress lookup, mapped to the right Client ID and Profile ID.
  • Caller-sent X-Proxy-ID headers stripped at both ingress hosts.
  • Certificate-bound tokens issued to the TPP's OAuth client, and requireCertificateBoundToken read back as true.
  • Production collections published, collections and methods matching the certificate roles, ingress allowlist matching the TPP's egress.
  • Every gate call observed in request logs with the expected Profile ID, audit entries on the change record.
  • Sandbox profiles left active for testing announced interface changes, and portal Copilot off.
  • A named offboarding owner and a scheduled register check.

Step 6: offboard when authorisation is withdrawn or a certificate is revoked

Issuers revoke certificates on an authentic regulator request, but nothing obliges the regulator to send one. Watch the register and act in Zerq, where changes apply on the next request.

  1. Confirm the scope: the whole authorisation, one role, or the certificate alone.
  2. Cut access at that level. Full withdrawal: set the client to inactive, and every profile fails with 401. One role: open the client, click Edit, uncheck the collection (ob-payments, say) and click Save; those calls return 404. Revoked certificate: switch the production profile's Active toggle off, remove the fingerprint from the ingress lookup, and stop issuing tokens to it.
  3. For a full withdrawal, also switch Developer Portal access off and clear Authorized emails.
  4. If the relationship continues, click Rotate credentials on sandbox, which invalidates the old token immediately, and vet any replacement certificate through Step 1 before reactivating production.
  5. Confirm the failures in Logs and keep the Audit Logs entries.

Disable rather than delete: deleting a client removes its profiles and your restore path, and a block for suspected fraud under PSD2 Article 68(5) must be justified, reported to the regulator and lifted once the reason ends. A register-watch job can run steps 2 to 4 under its own OIDC identity with the Management MCP tools update_client, update_profile and rotate_profile_credentials; avoid toggle_client_status in automation: it flips the state rather than setting it. Zerq has no register feed or approval step, so the watcher and its sign-off are yours.

What this looks like in practice

Consider a mid-sized retail bank whose testing facility runs on a separate gateway with self-service sign-up. Production onboarding is a ticket asking TPPs to email certificates, mapped to clients in a spreadsheet. When a payment institution loses its payment initiation permission, its payment calls keep succeeding until a quarterly access review catches it.

On Zerq, a job checks the register and parses the certificate when a TPP applies, creates the client and sandbox profile through the management API, and authorizes its engineers for the portal, so they test the same day. Production is a second profile and a collection assignment made once automated checks pass, with log and audit entries on the change record. When the watcher sees payment initiation withdrawn, it removes ob-payments from that client with update_client; the next payment call returns 404, and account information carries on.

Summary

TPP onboarding is partner onboarding with a regulator in the loop, so order matters: authorisation and certificate first, then sandbox and portal access, then a certificate-bound production profile limited to the TPP's roles, behind a gate you can evidence. On Zerq that is one client, sandbox and production profiles, role-scoped collections and an ingress that pins identity to the certificate, and offboarding becomes a toggle or an unchecked collection. If a TPP later adds an agent feature, offer it a second client; see AI agents in open banking. The security model and platform capabilities cover the underlying controls; our FAPI 2.0 gateway guide covers tokens in depth.


Zerq is an enterprise API gateway built for regulated industries — one platform for API management, AI agent access, compliance audit, and developer portal, running entirely in your own infrastructure. See how it works or request a demo to walk through your specific requirements.