> For the complete documentation index, see [llms.txt](https://docs.younium.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.younium.com/payments-integrations/gocardless.md).

# GoCardless

## Overview

The GoCardless integration connects Younium to a merchant’s GoCardless account through **OAuth**. It supports Direct Debit mandate collection via GoCardless Billing Requests, automatic payment collection for posted invoices, manual payment/retry/refund actions, webhook-driven status updates, and payout accounting when GoCardless transfers funds to the merchant bank.

The integration operates at **legal entity** scope. Each legal entity stores OAuth tokens, organisation id, creditor verification status, a primary Younium **payment method** for collections, and per-currency **payout methods**. Accounts with GoCardless as the order payment method hold **online payment details** including GoCardless customer id, mandate id, and mandate status.

***

## Authentication

An administrator connects Younium to GoCardless from the integration settings of a legal entity. Younium sends them to GoCardless, where they sign in to the merchant's GoCardless account and approve the connection; GoCardless returns them to Younium and the integration is live. There are no API keys to copy and no credentials for the customer to look after.

The connection is made per legal entity, and each legal entity connects to one GoCardless organisation. Younium reads the creditor's verification status from GoCardless when it connects and keeps it up to date afterwards, so the integration settings show both that the connection works and where the merchant stands in GoCardless's own verification of them.

Younium only ever acts on the GoCardless organisation the legal entity is connected to; updates arriving for any other organisation are ignored.

Each attempt to connect is valid once. If the approval is not completed as started — the same approval link is reused, or the attempt otherwise does not go through — Younium simply returns the administrator to the integration settings without connecting, rather than showing an error. Starting the connection again from the settings page always begins a fresh attempt.

### Settings

| Setting  | Description                                                                              | Default                                  |
| -------- | ---------------------------------------------------------------------------------------- | ---------------------------------------- |
| `Status` | Creditor verification with GoCardless (`Unknown`, `Approved`, `InReview`, `NeedsAction`) | Read from GoCardless and kept up to date |
| `Email`  | The merchant account the connection was approved from                                    | From the connection                      |

***

## Sandbox vs. Production

GoCardless runs a separate sandbox, and you choose which one to connect to when you start the connection.

The two are entirely separate accounts: a sandbox connection can never collect a real payment, and moving from testing to live means connecting again against the live GoCardless account rather than switching a setting. Younium keeps updates from the two apart, so a sandbox payment cannot appear as a real one.

***

## Activation

Approving the connection in GoCardless activates the integration. From that point Younium can set up mandates, collect payments, and record what GoCardless reports back.

The connection and the merchant's standing with GoCardless are two different things. GoCardless verifies the creditor on its own schedule, and the verification status Younium shows can still be under review, or waiting on something from the merchant, while the connection itself is perfectly healthy.

***

## Deactivation

Disconnecting withdraws Younium's access to the GoCardless organisation and removes what Younium held for that legal entity.

When the disconnection is initiated from GoCardless's side instead — the merchant removes Younium there — Younium clears the same records without trying to withdraw access that is already gone. Either way, mandates and payments already in GoCardless stay in the merchant's account.

***

## Save and Setup

Updating settings via `UpdateSettings` persists `PaymentMethodId`, mandate email template **language**, and **MandateRequestEmailSubject**. Default mandate template is created on first settings load if missing.

### Settings

| Setting                                                    | Description                                                               | Default                                                  |
| ---------------------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------- |
| `PaymentMethodId`                                          | Younium payment method for GoCardless collections (required for payments) | Unset until configured                                   |
| `DefaultMandateRequestTemplate.MandateRequestEmailSubject` | Mandate email subject                                                     | `Payment details request for {legalEntityName} services` |
| `DefaultMandateRequestTemplate.Language`                   | Billing Request Flow language (`en`, `da`, `nl`, …)                       | `English` → `en`                                         |
| Payout methods (`GoCardlessPayoutMethod`)                  | Per-currency payout + bank fee mapping                                    | Empty until added                                        |

Payout method validation requires a different financial account than the main payment method’s financial account.

***

## Custom fields created by the integration

GoCardless does not create Younium custom fields. Mandate and payment linkage uses GoCardless **metadata** and `OnlinePaymentDetails`.

***

## Eligibility and scope

### Supported currencies

Payments and mandates: `GBP`, `EUR`, `SEK`, `DKK`, `AUD`, `NZD`, `CAD`, `USD` (account currency must be in this set for mandate requests).

### Automatic payment job (`GoCardless invoice payment`)

Minimum interval 30 minutes. Selects invoices where:

* `PaymentMethodForInvoice == GoCardless`
* `Status == Posted`
* `DueDate` at least 15 days before today has passed (`DueDate.AddDays(-15) <= today`)
* `OnlinePaymentStatus == Default`
* `TotalAmount.Amount >= 0`

Requires active mandate on account; charge date is `max(invoice.DueDate, mandate.NextPossibleChargeDate)` when the latter is later.

### Payment creation validation

* `PaymentMethodId` configured
* Payout method exists for invoice currency
* Account `GoCardLessMandateId` present
* Invoice not processing; not already succeeded (except refund path)
* Outstanding balance is greater than zero and does not exceed the invoice total
* Refunds: no successful GoCardless payment in the last 7 days (safe period)

### Webhook tenant resolution

Each event is mapped to tenant/legal entity by:

1. `Younium_Id` metadata (`tenantId:legalEntityId`), or
2. Shared-database lookup by `OrganisationId`, or
3. Main-database `GoCardlessSettings` by organisation id

Events without resolution are skipped with error logging.

***

## Field mapping

### Metadata on Billing Request and Payment

| Younium value               | GoCardless `metadata` key | Format                        |
| --------------------------- | ------------------------- | ----------------------------- |
| Account id + account number | `Younium_Account`         | `{accountId}:{accountNumber}` |
| Tenant + legal entity       | `Younium_Id`              | `{tenantId}:{legalEntityId}`  |
| Invoice id + invoice number | `Younium_Invoice`         | `{invoiceId}:{invoiceNumber}` |

### Billing Request (mandate)

| Younium field                                       | GoCardless field                         |
| --------------------------------------------------- | ---------------------------------------- |
| `Account.Currency.Code`                             | `MandateRequest.currency`                |
| `Account.OnlinePaymentDetails.GoCardLessCustomerId` | `Links.customer` (when reusing customer) |
| Metadata above                                      | `Metadata`, `MandateRequest.metadata`    |

### Billing Request Flow (prefilled customer)

| Younium field                                        | GoCardless `PrefilledCustomer` field |
| ---------------------------------------------------- | ------------------------------------ |
| `Account.InvoiceEmailAddress`                        | `email`                              |
| `Account.DefaultInvoiceAddress.Street`               | `address_line1`                      |
| `Account.DefaultInvoiceAddress.City`                 | `city`                               |
| `Account.Name`                                       | `company_name`                       |
| `Account.DefaultInvoiceAddress.Zip`                  | `postal_code`                        |
| `{ApiBaseUrl}api/gocardless/billingrequestcompleted` | `redirect_uri`                       |
| `true`                                               | `lock_currency`                      |
| Template language                                    | `language`                           |

### Payment create

Younium requests the invoice's **outstanding balance**, not its full total, so a partially paid, credited or written-off invoice is charged only for what remains due.

| Younium field                                           | GoCardless `Payment` field                             |
| ------------------------------------------------------- | ------------------------------------------------------ |
| `Invoice.UnsettledAmount` (minor units)                 | `amount`                                               |
| Invoice currency (enum mapping)                         | `currency`                                             |
| `Invoice.InvoiceNumber`                                 | `description`                                          |
| `Account.OnlinePaymentDetails.GoCardLessMandateId`      | `links.mandate`                                        |
| Metadata                                                | `Younium_Invoice`, `Younium_Id`                        |
| `{attemptPrefix}:{InvoiceNumber}:{Invoice.Id}:{amount}` | `idempotency_key` (max 128 chars, truncated if longer) |
| Resolved charge date (`yyyy-MM-dd`)                     | `charge_date` (optional)                               |
| `true`                                                  | `retry_if_possible`                                    |

Amount conversion uses smallest currency unit via `ConvertAmountToSmallestCurrencyUnit`; reversal uses `ConvertFromSmallestUnitToDecimalAmount` when posting Younium payments. Because the outstanding balance is part of the idempotency key, requesting payment again after the balance has changed creates a new payment request rather than being treated as a duplicate of the earlier one.

### Refund create

| Younium field                       | GoCardless `Refund` field             |
| ----------------------------------- | ------------------------------------- |
| Payment id (latest successful)      | `links.payment`                       |
| Invoice total (minor units)         | `amount`, `total_amount_confirmation` |
| Same metadata / idempotency pattern | `metadata`, `idempotency_key`         |

### Payment posted in Younium (success webhook)

| Younium `Payment` field                | Source                                       |
| -------------------------------------- | -------------------------------------------- |
| `PaymentReference`                     | `Invoice.InvoiceNumber`                      |
| `PaymentDescription`                   | Configured payment method description        |
| `Amount`                               | GoCardless payment amount (from minor units) |
| `PaymentMethodId` / `PaymentAccountId` | `GoCardlessSettings.PaymentMethodId`         |
| `PaymentDate`                          | `UtcNow`                                     |
| `ExchangeRate`                         | `Invoice.ExchangeRate`                       |
| Settlement                             | Full invoice amount to `PaymentSettlement`   |

### Mandate status mapping (GoCardless → Younium)

| GoCardless `MandateStatus`                | `GoCardlessMandateStatus`   |
| ----------------------------------------- | --------------------------- |
| `PendingCustomerApproval`                 | `MandateRequested`          |
| `PendingSubmission`, `Submitted`          | `MandateApprovedByCustomer` |
| `Active`                                  | `MandateApproved`           |
| `Failed`                                  | `Failed`                    |
| `Cancelled`                               | `Cancelled`                 |
| `Expired`                                 | `Expired`                   |
| `Consumed`, `Blocked`, `SuspendedByPayer` | `NoMandate`                 |

### Creditor verification mapping

| GoCardless `CreditorVerificationStatus` | `GoCardlessSettings.Status` |
| --------------------------------------- | --------------------------- |
| `Successful`                            | `Approved`                  |
| `InReview`                              | `InReview`                  |
| `ActionRequired`                        | `NeedsAction`               |
| `Unknown`                               | `Unknown`                   |

### GoCardless payment status → `OnlinePaymentStatus`

Mapped in utilities for webhook and API responses (`Processing`, `Failed`, `Succeeded`, etc., per GoCardless payment/refund status).

***

## Payment and mandate flows

### Mandate request

`RequestMandate` creates Billing Request + Flow, emails the authorisation URL (document template `GoCardlessMandateRequest`), and sets `GoCardlessMandateStatus` to `MandateRequested` with `GoCardLessCustomerId` from the billing request. Webhook `billing_requests.fulfilled` or mandate events update mandate id and status on `OnlinePaymentDetails`.

### Collection

Manual API or job calls `RequestPayment`, which collects the invoice's outstanding balance rather than its full total. Webhook `payments` events drive processing: on success, Younium posts a payment and sets `OnlinePaymentStatus.Succeeded`; failures respect `will_attempt_retry`; late failures on settled invoices create reversing payments.

> **Note on partially paid invoices:** If part of an invoice has already been paid, credited or written off, requesting payment through GoCardless collects only the remaining balance. Younium refuses the request if the invoice has no outstanding balance to collect.

### Retry and refund

* **Retry:** `Payments.Retry` on latest failed external payment id from logs.
* **Refund:** `Refunds.Create` against latest successful payment; success posts negative payment; seven-day guard on recent successful payments.

### Payout (`payouts` paid)

When payout status is `Paid`, Younium loads payout items, resolves invoice metadata for linked payments, computes totals including bank fees, and posts a payout journal debiting the currency-specific payout method and crediting the main GoCardless payment method, with bank-fee postings. Duplicate payout ids are skipped.

***

## Webhook events

| Resource type        | Actions handled  | Younium outcome                                                               |
| -------------------- | ---------------- | ----------------------------------------------------------------------------- |
| `creditors`          | `updated`        | Refresh `Status`                                                              |
| `billing_requests`   | `fulfilled`      | Process mandate                                                               |
| `mandates`           | (various)        | Update `OnlinePaymentDetails` mandate id/status; optional application webhook |
| `organisations`      | `disconnected`   | Disconnect merchant                                                           |
| `payments`           | (status changes) | Update invoice online status; post or reverse payments                        |
| `payouts`            | `paid`           | Payout journal; `pending`/`bounced` logged                                    |
| `refunds`            | (status changes) | Refund payment posting or failure handling                                    |
| Other resource types | —                | Informational log only                                                        |

***

## Events and jobs

| Trigger           | Name                                    | Behaviour                                           |
| ----------------- | --------------------------------------- | --------------------------------------------------- |
| Scheduled job     | GoCardless invoice payment              | Create GoCardless payment for eligible invoices     |
| Webhook           | GoCardless Event API                    | Mandate, payment, payout, refund processing         |
| Application event | `PublishWebhookEvent` on mandate update | External notification when `triggerWebhook` is true |

No `InvoicePosted` / draft invoice application event subscriptions are registered by this integration.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.younium.com/payments-integrations/gocardless.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
