All notable changes to this project will be documented in this file.

[2.0.0] โ€” 2026-05-24

๐Ÿ”ด Breaking bug fixes

  • Resource.update/5 now uses HTTP POST (was incorrectly using HTTP PUT). GoCardless does not support PUT โ€” all update operations require POST to the resource endpoint. This was a silent runtime failure: all update/4 calls across every resource were returning 405 Method Not Allowed from the API.

  • Action endpoints now wrap params in the resource key (was wrapping in "data"). The GoCardless API requires %{"billing_requests" => params}, not %{"data" => params}. Every cancel, retry, fulfil, pause, resume, approve, and other action calls were failing with validation errors.

  • Fixed GoCardless-Version header name (was GoCardlessClient-Version). The API was silently receiving no valid version header on every request.

๐Ÿ†• New modules

๐Ÿ†• New functions on existing modules

  • OutboundPayments.withdrawal/3 โ€” POST /outbound_payments/withdrawal
  • OutboundPayments.statistics/2 โ€” GET /outbound_payments/statistics
  • Blocks.block_by_reference/3 โ€” POST /blocks/block_by_reference
  • Institutions.list_for_billing_request/4 โ€” GET /billing_requests/:id/institutions
  • ScenarioSimulators.run/4 โ€” POST /scenario_simulators/:type/actions/run (previously referenced in docs but never defined โ€” caused UndefinedFunctionError)
  • RedirectFlows.list/3 and stream/3
  • InstalmentSchedules.create_with_dates/3 and create_with_schedule/3 (replaces ambiguous create/3 with clearly named wrappers)

๐Ÿ†• New webhook event type helpers

Added to GoCardlessClient.Webhooks:

  • instalment_schedule_event?/1
  • outbound_payment_event?/1
  • creditor_event?/1
  • customer_event?/1
  • export_event?/1
  • payment_account_transaction_event?/1
  • scheme_identifier_event?/1

๐Ÿ—‘๏ธ Removed

  • GoCardlessClient.Resources.Transfers โ€” this module referenced a /transfers endpoint that does not exist in the GoCardless API. All calls would have returned 404. Removed entirely.

๐Ÿงน Phantom function cleanup

Removed create/3 and update/4 from read-only resources where these operations don't exist in the API:

  • Balances โ€” read-only; removed phantom create/3, update/4
  • CurrencyExchangeRates โ€” read-only; removed phantom create/3, update/4
  • Events โ€” read-only; removed phantom create/3, update/4
  • Exports โ€” read-only; removed phantom create/3, update/4
  • NegativeBalanceLimits โ€” read-only; removed phantom create/3, update/4
  • PayoutItems โ€” list-only; removed phantom create/3, get/3, update/4
  • PaymentAccounts โ€” read-only; removed phantom create/3, update/4
  • PaymentAccountTransactions โ€” read-only; removed phantom create/3, update/4
  • Payouts โ€” read-only except metadata; removed phantom create/3
  • TaxRates โ€” read-only; removed phantom create/3, update/4
  • TransferredMandates โ€” get-only; removed phantom create/3, list/3, update/4
  • Institutions โ€” removed phantom create/3, update/4
  • Logos โ€” write-only; removed phantom get/3, list/3, update/4
  • MandatePDFs โ€” write-only; removed phantom get/3, list/3
  • FundsAvailabilities โ€” renamed create/3 โ†’ check/3; removed phantom get/3, list/3
  • CustomerNotifications โ€” removed phantom create/3, get/3, list/3, update/4; kept handle/4
  • BankDetailsLookups โ€” renamed create/3 โ†’ lookup/3; removed phantom get/3, list/3
  • BankAccountDetails โ€” removed phantom create/3, update/4; kept get/3
  • MandateImports โ€” removed phantom list/3 (the API has no list endpoint for this resource)

๐Ÿงช Tests

  • Fixed GoCardlessClient.TestCase โ€” Bypass server URL was opened but never wired to the client; every HTTP test was silently hitting the real GoCardless sandbox (or failing with connection errors). The client now receives a _base_url_override pointing at the local Bypass server.

  • Added Bypass-wired tests for 15 resource modules (from 2):

    • CustomersTest โ€” create, get, list, update (POST not PUT), remove (DELETE), header assertions
    • PaymentsTest โ€” create, cancel (action key), retry, list, update (POST not PUT)
    • MandatesTest โ€” create, cancel (action key), reinstate
    • BillingRequestsTest โ€” create, all action endpoints (verifies resource key wrapping)
    • SubscriptionsTest โ€” create, pause, resume, cancel
    • ScenarioSimulatorsTest โ€” run/4 path, mandate scenario, invalid scenario guard
    • BlocksTest โ€” create, block_by_reference, disable/enable actions
    • OutboundPaymentsTest โ€” create, withdrawal, statistics, cancel, approve
    • InstalmentSchedulesTest โ€” create_with_dates, create_with_schedule, cancel
    • BillingRequestWithActionsTest โ€” full single-call flow
    • RedirectFlowsTest โ€” create, complete, list
    • PayoutsTest โ€” list, update (POST), PayoutItems.list
    • WebhooksResourceTest โ€” list, retry
    • EventsTest โ€” list with filters, get
    • MiscResourcesTest โ€” BankDetailsLookups, FundsAvailabilities, MandatePDFs, Institutions, Balances, CustomerNotifications
    • PaginatorTest โ€” single-page, multi-page cursor following, error propagation
    • WebhooksHelpersTest โ€” all 7 new event type helpers, payload size guard

Upgrade guide

Update all create/3 calls for renamed functions:

# Before (returns 404)
GoCardlessClient.Resources.FundsAvailabilities.create(client, params)
GoCardlessClient.Resources.BankDetailsLookups.create(client, params)

# After
GoCardlessClient.Resources.FundsAvailabilities.check(client, params)
GoCardlessClient.Resources.BankDetailsLookups.lookup(client, params)

Replace ambiguous InstalmentSchedules.create/3:

# Before
GoCardlessClient.Resources.InstalmentSchedules.create(client, %{instalments: [...]})

# After (explicit)
GoCardlessClient.Resources.InstalmentSchedules.create_with_dates(client, %{instalments: [...]})
GoCardlessClient.Resources.InstalmentSchedules.create_with_schedule(client, %{interval_unit: "monthly", ...})

Remove any direct Transfers module usage:

# Before (returns 404 โ€” endpoint doesn't exist)
GoCardlessClient.Resources.Transfers.create(client, params)

# Use TransferredMandates for post-switch mandate data:
GoCardlessClient.Resources.TransferredMandates.get(client, mandate_id)

[1.0.0] โ€” Initial release