# Changelog
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
- `GoCardlessClient.Resources.BillingRequestWithActions` โ single-call API
combining billing request creation + actions (`POST /billing_requests_with_actions`)
- `GoCardlessClient.Resources.OutboundPaymentImports` โ bulk outbound payment
import batches (`POST /outbound_payment_imports`, `GET`, list)
- `GoCardlessClient.Resources.OutboundPaymentImportEntries` โ entries within an
outbound payment import batch
### ๐ 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:**
```elixir
# 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`:**
```elixir
# 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:**
```elixir
# 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