Cancels whichever stage the id names: a billing request pre-fulfilment (expires its flows), or a payment — GoCardless only cancels pending_submission payments, anything later rejects with invalid_state (cancellation_failed) -> invalid_request, never retried.
Verified-idempotent. GoCardless documents Idempotency-Key for creates
only, and documents cancellation_failed for cancelling a payment that is
already cancelled (what it answers for an already-cancelled billing
request is undocumented), so a repeated cancel can be refused although
the cancel it repeats went through. On any rejection the payment or
billing request is re-read, and one that is already cancelled resolves as
canceled; any other state rethrows the original error. The caller's key
still rides the Idempotency-Key header, as its digest when GoCardless
cannot have taken it as given (see idempotencyKeyHeader).
Creates a subscription GoCardless itself bills (POST /subscriptions)
against an existing MANDATE — savedPaymentMethodToken is the mandate id
(MD...), and GoCardless derives the customer from it, so
pspCustomerId is ignored. Cadence is weekly/monthly/yearly only:
interval "day" and RRULE schedules reject (invalid_request) instead
of approximating, and so does an intervalCount that would miss a year
without a charge (over 52 weeks, 12 months or 1 year). Metadata and the
idempotencyKey are handled as createPaymentSession handles them.
merchantRefNum rides the dedicated name field
(max 255 chars; GoCardless also sets it as the description on each
payment created) — never payment_reference, which is restricted to
accounts with their own Service User Number. startAt maps to the
date-only start_date (the instant's stated calendar date); omitted, the
first charge lands on the mandate's next_possible_charge_date. planId
rejects: GoCardless subscriptions have no plan object.
Creates the billing request (the payment) plus the billing request flow (the GoCardless-hosted authorisation UI). The session's clientSecret is the flow's authorisation_url — the client adapter redirects the payer to it, GoCardless fulfils the billing request on completion (auto_fulfil is always on), and the outcome is confirmed via webhooks or retrievePayment.
A reused idempotencyKey resolves to the billing request GoCardless already
holds under it. GoCardless documents no parameter comparison, so the
adapter compares: its amount, currency and host id must match this
input, or the call rejects with invalid_request, marked outcomeUnknown
unless that billing request was cancelled or its payment failed or was
cancelled (see idempotencyKeyReused). The replayed session
reports the status of the payment the billing request created, as
retrievePayment does, except that a payment awaiting the customer's
approval reads processing where retrievePayment reports
requires_action: a replay of a billing request that has a payment
carries no clientSecret. While the billing request has no payment, the
session reports the billing request's own status. Only a pending
billing request gets a fresh authorisation URL; once the payer has
authorised, or the request is fulfilled or cancelled, the session carries
no clientSecret.
Refused with invalid_request before any request: a zero amount,
metadata GoCardless cannot hold (a key name over 50 characters, a value
over 500, the id included), and an idempotencyKey sent as its digest
that holds a lone surrogate. An idempotencyKey GoCardless cannot have
taken as given, over 128 characters however GoCardless can have read it,
or holding a NUL, CR or LF, once trimmed, is sent as a SHA-256 digest of
itself (see idempotencyKeyHeader).
Metadata keys past the third are withheld, never refused.
Missed-webhook recovery: GET /events, normalized by the same mapper webhooks use.
Pages GET /subscriptions with GoCardless cursor semantics (after; limit 1-500, default 50).
Reconciliation passthrough. Only present if getCapabilities().supportsListing.
Reconciliation passthrough. Only present if getCapabilities().supportsListing.
Single-event contract method. GoCardless BATCHES up to 250 events per delivery, so this only accepts single-event bodies — a multi-event delivery throws (invalid_request) instead of silently dropping events. Webhook ingress for GoCardless should verify once, then fan out with parseGoCardlessWebhookEvents (see the package README for the recipe).
Refunds against a fresh read of the payment; omit amount to refund the
remainder. More than the remainder, or an explicit amount of 0, rejects
locally with invalid_request, and a payment or refund amount GoCardless
sends that is not a whole number rejects with unknown. Before any
request, a reason over the 500 characters a metadata value holds, and
an idempotencyKey holding a lone surrogate, reject with
invalid_request, the latter marked outcomeUnknown, as an earlier release
may have refunded under it. The refund's stamp is the SHA-256 of the key
as given, whatever header carries it.
Each refund is created with the SHA-256 of its idempotencyKey in its
GoCardless metadata (payfanout_key_sha256, next to reason), so a
replay is recognised from the refund itself. A reused key resolves to the
refund created with it, which must belong to this payment and, when an
amount is given, be for that amount, or the call rejects with
invalid_request, marked outcomeUnknown unless that refund was cancelled,
bounced or had its funds returned. A request the remainder check refuses,
such as the replay of a refund that used up the payment, is never sent:
the payment's refunds are read and the one stamped with this key is
returned, or the refusal stands. A create GoCardless rejects is settled by
the same read.
GoCardless lets accounts opt out of the total_amount_confirmation check,
so none of this relies on it, nor on whether GoCardless checks the key
before the request body. Refunds created by adapter versions without the
stamp are not recognised: a replay of one that the remainder check
refuses rejects, as it did before. While GoCardless reports an amount
already refunded on the payment, the stamp is also checked before any
create, so a key GoCardless no longer honours (it promises at least 30
days) is still read back instead of refunding again.
A read of the payment's refunds that fails sends nothing further. A
transient failure rejects retryable (psp_unavailable, or
rate_limited), with GoCardless's answer to a failed create on
raw.rejection; retry with the same key, as a new one can refund twice.
Any other failure leaves open whether this key already refunded, so the
error is marked outcomeUnknown: before a create it is a final
invalid_request and the refund is not sent, and after a rejected
create GoCardless's rejection stands.
GET /subscriptions/:id — the subscription id alone keys retrieval (savedPaymentMethodToken is not needed).
Accepts BOTH ids the host may hold — GoCardless ids are typed by prefix (BRQ = billing request/session, PM = payment) — so the redirect return trip can resolve outcomes from the session id alone.
Polls an async refund to a terminal state — bank refunds submit on debit-scheme timing.
Side-effect-free credential probe — the engine behind a host "Test
connection" button. Makes ONE read-only GET /payments (limit 1) and reads
the RAW HTTP status so an auth rejection (401/403) is told apart from an
outage (429/5xx) directly from the status line, never from a body that a
proxy or edge error page may not carry. Only a 2xx answer carrying the
payment list ({ payments: [...] }) passes. Any other answer that is
neither an auth rejection nor an outage means the probe never reached
that list, as when a baseUrl or goCardlessVersion
override is wrong (GoCardless documents path_not_found and
version_not_found), or a baseUrl names a host that answers 200 with
something else: it reports internal, naming the HTTP status and, when
the body carries one, GoCardless's error reason.
A single shot with no transport retry loop: a "Test connection" click
cannot hang on backoff, and a bad key is not replayed. Never mutates PSP
state, never puts the token in the result.
Webhook handling — same adapter, separate concerns. Both async: future PSPs may need remote key retrieval; the contract stays uniform. MUST operate on the RAW request body bytes/string — re-serializing a parsed body breaks signatures (the conformance suite tests this).
POST /subscriptions/:id/actions/cancel — stops FUTURE payment creation only: payments the subscription has already created still collect unless they are cancelled separately (GoCardless documents this explicitly). GoCardless rejects the action with a cancellation_failed invalid_state error once a subscription is already cancelled or finished, so this is verified-idempotent: on any rejection the subscription is re-fetched and a terminal state resolves as success — the billing stop the caller asked for already holds. The caller's key rides the Idempotency-Key header, matching the adapter's other cancel actions, as its digest when GoCardless cannot have taken it as given (see idempotencyKeyHeader).