← all adapters
psd2-style
simulates Open Banking / PSD2 (Berlin Group NextGenPSD2) 1.3.6
restadapter v0.1.019 routes
verification
use it
# add to stunt.yaml
services:
psd2:
adapter: embedded:psd2-style
# then
$ stunt upThe embedded: source extracts this adapter from the binary — no git clone, fully offline.
how to mock the Open Banking / PSD2 (Berlin Group NextGenPSD2) API locally
Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of Open Banking / PSD2 (Berlin Group NextGenPSD2). It works offline, keeps state across requests and restarts, and every response is synthetic: the route shapes, status codes, pagination, and webhook delivery follow the real Open Banking / PSD2 (Berlin Group NextGenPSD2) 1.3.6 surface — the data is fake, the behavior is real.
backing stores
consentsauthorisationsaccountstransactionsaccess_tokens
api surface (19)
generated from the adapter manifest — exactly what boots, nothing more
19 routes
POST/v1/oauth/token
POST/v1/consents
GET/v1/consents/{consentId}
DELETE/v1/consents/{consentId}
POST/v1/consents/{consentId}/authorisations
GET/v1/consents/{consentId}/authorisations/{authorisationId}
PUT/v1/consents/{consentId}/authorisations/{authorisationId}
POST/v1/consents/{consentId}/authorisations/{authorisationId}
GET/v1/accounts
GET/v1/accounts/{resourceId}/balances
GET/v1/accounts/{resourceId}/transactions
POST/v1/payments/{product}
GET/v1/payments/{product}/{paymentId}/status
POST/v1/payments/{product}/{paymentId}/authorisations
GET/v1/payments/{product}/{paymentId}/authorisations/{authorisationId}
PUT/v1/payments/{product}/{paymentId}/authorisations/{authorisationId}
POST/v1/payments/{product}/{paymentId}/authorisations/{authorisationId}
GET/v1/payments/{product}/{paymentId}
DELETE/v1/payments/{product}/{paymentId}
VM-verified behaviors (24)
- ✓the tpp token endpoint mints a bearer; other grants and missing or unknown bearers are rejected
- ✓a created consent answers 201 received with self and startAuthorisation links, and reads back
- ✓the sca redirect flow advances one hop per PUT: started → psuAuthenticated → scaReceived
- ✓an update carrying neither method nor OTP is a 400 PARAMETER_INVALID that leaves the chain put
- ✓after the 1s challenge window a read derives finalised and the consent reads valid
- ✓delete terminates the consent and consent-bound reads then reject it
- ✓account reads require a valid consent: 401 CONSENT_INVALID without one
- ✓a valid consent unlocks the seeded account list with per-account links
- ✓withBalance=true embeds an interimBooked balance in each account entry
- ✓the balances read returns interimBooked and forwardAvailable pairs and 404s unknown accounts
- ✓the transaction report requires bookingStatus and dateFrom
- ✓bookingStatus splits booked from pending and dateFrom/dateTo bound the report
- ✓a restricted consent scopes the account list and 404s uncovered reads
- ✓a consent past its validUntil finalises but gates reads with 401 CONSENT_EXPIRED
- ✓with no Consent-ID header, only-expired consents still answer CONSENT_EXPIRED
- ✓an unknown Consent-ID is 400 CONSENT_INVALID; a not-yet-finalised one is 401 CONSENT_INVALID
- ✓page/size walks every account exactly once with a next link only between pages
- ✓the next href round-trips the caller's other query params (withBalance)
- ✓a malformed page cursor is 400 FORMAT_ERROR; a cursor past the end is an empty last page
- ✓the tpp bearer dies at its 3600s expires_in with 401 TOKEN_EXPIRED
- ✓a payment validates its product and amount before answering 201 RCVD with startAuthorisation
- ✓the payment SCA chain mirrors the consent chain and finalises on read
- ✓the transaction status walks RCVD → ACTC → ACSC on the clock and terminal payments refuse cancellation
- ✓a non-terminal payment cancels to 204/CANC and simulate_fail drives RJCT
Not implemented (6)
- No Confirmation of Funds (POST /v1/funds-confirmations)
- No card accounts (GET /v1/card-accounts and card transactions)
- No periodic or bulk payments (standing orders)
- No transaction detail (GET /v1/accounts/{id}/transactions/{resourceId})
- No GET /v1/consents/{id}/status sub-resource
- No payment cancellation-authorisations SCA sub-resource
Differs from the real API (7)
- SCA finalisation is derive-on-read after a fixed 1s challenge window
- Payment status derives on read: ACTC at 1s, ACSC at 3s — fixed, not bank async
- simulate_fail: true in POST /payments forces RJCT (simulator-only trigger)
- Signed transition webhooks are a simulator extension; NextGenPSD2 defines none
- scaRedirect _links URL is synthetic — no real bank SCA login page behind it
- DELETE consent returns 200 + body; real NextGenPSD2 returns 204 No Content
- PARAMETER_MISSING-<FIELD> error codes are simulator conventions, not the official code list
want more of the Open Banking / PSD2 (Berlin Group NextGenPSD2) surface? adapters are YAML + Starlark — the authoring guide covers adding routes, fixtures, and state machines. Open an issue for anything big first, or just file a PR — merged routes ship in the next release.