← all adapters

adyen-style

simulates Adyen Checkout + Notification API v68

restadapter v0.1.014 routes

verification

VMVM tier — no SDK suite yet· surface 14 · not implemented 4 · differs 8

use it

# add to stunt.yaml
services:
  adyen:
    adapter: embedded:adyen-style

# then
$ stunt up

The embedded: source extracts this adapter from the binary — no git clone, fully offline.

how to mock the Adyen Checkout + Notification API locally

Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of Adyen Checkout + Notification API. 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 Adyen Checkout + Notification API v68 surface — the data is fake, the behavior is real.

backing stores

paymentsmodifications

api surface (14)

generated from the adapter manifest — exactly what boots, nothing more · covers 23% of the real API's 39 routes (derived from spec adyen-openapi CheckoutService-v68 + PaymentService-v68 @ 68, 68)

14 routes
POST/v68/payments
POST/v68/payments/details
GET/v68/payments
POST/v68/paymentMethods
POST/v68/paymentLinks
GET/v68/paymentLinks/{linkId}
POST/v68/payments/{paymentPspReference}/captures
POST/v68/payments/{paymentPspReference}/refunds
POST/v68/payments/{paymentPspReference}/reversals
POST/v68/payments/{paymentPspReference}/cancels
POST/v68/notifications/test
POST/v68/webhooks
GET/v68/webhooks
DELETE/v68/webhooks/{webhookId}

VM-verified behaviors (39)

  • a missing X-API-Key is a 401 security envelope
  • an unseeded API key is rejected identically
  • the seeded test key authorises; header spelling does not matter
  • the gate spans the whole surface, not just /payments
  • a plain card authorises instantly with a 16-digit 881 pspReference
  • the refused test card (...0002) answers Refused with refusalReason, still 200
  • simulate_fail refuses an instant payment outright
  • Idempotency-Key replays the same pspReference; a fresh call mints a new one
  • GET ?reference= returns the payment object; unknown references are 422 010
  • the unfiltered list is cursor-paginated; a garbage cursor is a 400
  • a 3DS card returns IdentifyShopper with a threeDS2 action and no pspReference yet
  • submitting the fingerprint authorises and mints the pspReference
  • paymentData tokens are single-use
  • challenge cards (...0081) add a ChallengeShopper round with a fresh token
  • simulate_fail refuses at completion with threeDSError
  • a missing paymentData or missing fingerprint is a 422 validation error
  • an idempotent replay re-renders the payment's CURRENT state, not the original response (deviation, asserted as-is)
  • the catalogue is scheme/ideal/paypal/applepay/googlepay, storedPaymentMethods empty
  • merchantAccount is required
  • any merchantAccount string is accepted — no account registry (deviation, asserted as-is)
  • creating a link assigns PL-N, defaults expiresAt to +24h, starts active
  • a zero amount or missing reference is a 422
  • an unknown link id is a 404 with errorCode 191
  • authorising a payment on the link's reference completes the link on read
  • a past expiresAt flips the link to expired on read, and terminal statuses persist
  • capture chains a CAP-prefixed pspReference and returns status received
  • a partial capture keeps the remainder capturable; over-capture is 422 702
  • refunds draw down the captured balance; over-refund is 422 705
  • refund before capture is 704, currency mismatch 708, zero amount 703
  • cancel is only for uncaptured payments; reversal is terminal from captured
  • a cancelled payment rejects every later modification
  • an unknown pspReference is a 422 010
  • webhook registration masks the hmacKey in every view
  • an authorisation delivers the standard envelope signed with the hook's own key
  • a capture chains originalReference and signs with the mock key via the events filter
  • a refused payment notifies AUTHORISATION with success "false"
  • only the first matching hook receives an event (deviation, asserted as-is)
  • deleting a hook silences it; the next matching hook takes over
  • the merchant-side receiver answers [accepted] and tolerates redelivery

Not implemented (4)

  • No Payouts, Disputes, or Terminal API (cloud/POS) endpoints
  • No paymentMethods/balance, gift-card, or stored-value endpoints
  • No amountUpdates, technicalCancels, or auto-rescue modification routes
  • No stored payment method lifecycle — tokens cannot be stored, listed, or disabled

Differs from the real API (8)

  • Per-hook hmacKey and events filter are local extensions — real Adyen hides the key
  • simulate_fail flag on /v68/payments forces Refused (simulator-only failure injection)
  • paymentLinks url is synthetic — no hosted checkout page; pay via the link reference
  • paymentMethods serves a fixed 5-method catalog with empty storedPaymentMethods
  • Webhook HMAC signs the base64-encoded signing string with eventCode in field 7; deliveries go to the first matching hook only
  • Idempotency replay re-renders the payment's current state, not the original response
  • Modification pspReferences carry CAP/REF/REV/CAN prefixes; real Adyen's are numeric
  • paymentMethods accepts any merchantAccount; real Adyen 403s on unknown accounts
want more of the Adyen Checkout + Notification API 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.