# Taking Direct Debit payments using Billing Requests and Custom Payment Pages

## What is a billing request?

For the purposes of this tutorial, a `Billing Request` is a wrapper around all of the GoCardless APIs required to take a payment from a customer. This allows you, the integrator, to define desired outcomes upfront (for example, "I want to take a payment from X") and guides you through the process to achieve them.

## What is the aim of this tutorial?

This tutorial aims to familiarise beginners with using `Billing Requests` to collect Direct Debit payments using Custom Payment Pages. It will not cover Instant Bank payments (IBP) or VerifiedMandates (VM).

## Getting started

For this tutorial, you will need:

- An [API token](/getting-started/set-up#step-by-step_guide)
- The GoCardless client library of your choice configured in your language of choice
- A [Creditor](https://developer.gocardless.com/api-reference#core-endpoints-creditors) to collect payments against

## Creating a Billing Request

We can start by creating a `Billing Request`. This will allow us to request a `Mandate` to take a payment against that is linked to a `Creditor`.

```HTTP
POST https://api.gocardless.com/billing_requests HTTP/1.1
Content-Type: application/json
{
  "billing_requests": {
    "mandate_request": {
      "scheme": "bacs"
    },
    "links": {
      "creditor": "CR123"
    }
  }
}

HTTP/1.1 201 Created
Location: /billing_requests/BRQ123
Content-Type: application/json
{
    "billing_requests": {
        "id": "BRQ123",
        "created_at": "2023-03-22T15:20:08.397Z",
        "status": "pending",
        "mandate_request": {
            "currency": "GBP",
            "scheme": "bacs",
            "links": {}
        },
    ...
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/billing_requests" \
-d @- << EOF
{
  "billing_requests": {
    "mandate_request": {
      "scheme": "bacs"
    },
    "links": {
      "creditor": "CR123"
    }
  }
}
EOF
```

```ruby
billing_request = @client.billing_requests.create(
  params: {
    mandate_request: {
      scheme: "bacs"
    }
  links: { creditor: "CR123" },
  }
)
```

```PHP
$client->billingRequests()->create([
  "params" => [
    "mandate_request" => [
      "scheme" => "bacs"
    ]
    "links" => [
      "creditor" => "CR123"
    ]
  ]
]);
```

```Python
client.billing_requests.create(params={
  "mandate_request": {
    "scheme": "bacs"
  },
  "links": {
    "creditor": "CR123"
  }
})
```

```java
BillingRequest billingRequest = client.billingRequests().create()
  .withMandateRequestScheme("bacs")
  .withLinksCreditor("CR123")
  .execute();
```

```javascript
const billingRequest = await client.billingRequests.create({
  mandate_request: {
    scheme: "bacs",
  },
  links: {
    creditor: "CR123",
  },
});
```

```.net
var mandateRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestMandateRequest
{
  Scheme = "bacs",
};

var billingRequestLinks = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestLinks
{
  Creditor = "CR123"
};

var resp = await gocardless.BillingRequests.CreateAsync(
  new GoCardless.Services.BillingRequestCreateRequest()
  {
    MandateRequest = mandateRequest,
    links = billingRequestLinks,
  }
);

GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest;
```

```Go
accessToken := "your_access_token_here"
config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint))
if err != nil {
	fmt.Printf("got err in initialising config: %s", err.Error())
	return
}
client, err := gocardless.New(config)
if err != nil {
	fmt.Println("error in initialisating client: %s", err.Error())
	return
}

billingRequestCreateParams := gocardless.BillingRequestCreateParams{
  MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{
    Scheme: "bacs",
  },
  Links: &gocardless.BillingRequestCreateParamsLinks{
    Creditor: "CR123",
  },
}

billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams)
```

For the purposes of this tutorial, we only need to keep track of the ID of the `Billing Request`: `BRQ123`

We request the desired `scheme`, in this instance, we are going to use `bacs` for a GBP mandate. If you want to collect in EUR, use `sepa_core`. We link the `Billing Request` to the creditor we wish to pay out to, `CR123`.

In the next steps, we complete the required `Billing Request` `actions` to fulfil our request. The `actions` returned from the API describe steps that must be taken for a `Billing Request` to be `fulfilled`. They can change depending on the type of payment being taken or set up (e.g a Direct Debit or Instant Bank payment). We don’t need to worry about them too much in this tutorial - but it’s good to be aware of them! You can read more about them [here](https://developer.gocardless.com/billing-requests/billing-request-actions) if you’re interested.

## Collect customer details

Next, we need to collect the details of our customer

```HTTP
POST https://api.gocardless.com/billing_requests/BRQ123/actions/collect_customer_details HTTP/1.1
Content-Type: application/json
{
  "data": {
    "customer": {
      "email": "alice@example.com",
      "given_name": "Alice",
      "family_name": "Smith"
    },
    "customer_billing_detail": {
      "address_line1": "1 Somewhere Lane",
      "city": "London",
      "postal_code": "E5 8EE",
      "country_code": "GB"
    }
  }
}

HTTP/1.1 200
Content-Type: application/json
{
  "billing_requests": {
    "id": "BRQ123",
    ...
    "links": {
      "customer": "CU123",
      "customer_billing_detail": "CBD123"
    },
    ...
  },
  "resources": {
    "customer": {
      "id": "CU123",
      "created_at": "2021-03-22T12:20:04.238Z",
      "email": "alice@example.com",
      "given_name": "Alice",
      "family_name": "Smith",
      ...
    },
    "customer_billing_detail": {
      "id": "CBD123",
      "created_at": "2021-03-22T12:20:04.374Z",
      "address_line1": "1 Somewhere Lane",
      ...
    }
  }
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/billing_requests/BRQ123/actions/collect_customer_details" \
-d @- << EOF
{
  "data": {
    "customer": {
      "email": "alice@example.com",
      "given_name": "Alice",
      "family_name": "Smith"
    },
    "customer_billing_detail": {
      "address_line1": "1 Somewhere Lane",
      "city": "London",
      "postal_code": "E5 8EE",
      "country_code": "GB"
    }
  }
}
EOF
```

```PHP
$client->billingRequests()->collectCustomerDetails("BR123", [
  "params" => [
    "customer" => [
      "email" => "alice@example.com",
      "given_name" => "Alice",
      "family_name" => "Smith"
    ],
    "customer_billing_detail" => [
      "address_line1" => "1 Somewhere Lane",
      "city" => "London",
      "postal_code" => "E5 8EE",
      "country_code" => "GB"
    ]
  ]
]);
```

```python
client.billing_requests.collect_customer_details("BR123", params={
  "customer": {
    "email": "alice@example.com",
    "given_name": "Alice",
    "family_name": "Smith",
  },
  "customer_billing_detail": {
    "address_line1": "1 Somewhere Lane",
    "city": "London",
    "postal_code": "E5 8EE",
    "country_code": "GB",
  }
})
```

```ruby
@client.billing_requests.collect_customer_details("BR123", {
  params: {
    customer: {
      email: "alice@example.com",
      given_name: "Alice",
      family_name: "Smith",
    },
    customer_billing_detail: {
      address_line1: "1 Somewhere Lane",
      city: "London",
      postal_code: "E5 8EE",
      country_code: "GB",
    }
  }
})
```

```java
client.billingRequests().collectCustomerDetails("BR123")
  .withCustomerEmail("alice@example.com")
  .withCustomerGivenName("Alice")
  .withCustomerFamilyName("Smith")
  .withCustomerBillingDetailAddressLine1("1 Somewhere Lane")
  .withCustomerBillingDetailCity("London")
  .withCustomerBillingDetailPostalCode("E5 8EE")
  .withCustomerBillingDetailCountryCode("GB")
  .execute();
```

```javascript
const resp = await client.billingRequests.collectCustomerDetails("BR123", {
  customer: {
    email: "alice@example.com",
    given_name: "Alice",
    family_name: "Smith",
  },
  customer_billing_detail: {
    address_line1: "1 Somewhere Lane",
    city: "London",
    postal_code: "E5 8EE",
    country_code: "GB",
  },
});
```

```.Net
var customer = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomer
{
  Email = "alice@example.com",
  GivenName = "Alice",
  FamilyName = "Smith",
};

var customerBillingDetail = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomerBillingDetail
{
  AddressLine1 = "1 Somewhere Lane",
  City = "London",
  PostalCode = "E5 8EE",
  CountryCode = "GB",
};

var resp = await gocardless.BillingRequests.CollectCustomerDetails("BR123",
  new BillingRequestCollectCustomerDetailsRequest
  {
    Customer = customer,
    CustomerBillingDetail = customerBillingDetail,
  });
```

```go
billingRequestCollectCustomerDetailsParams := gocardless.BillingRequestCollectCustomerDetailsParams{
  Customer: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomer{
    GivenName:  "Alice",
    FamilyName: "Smith",
    Email:      "alice@example.com",
  },
  CustomerBillingDetail: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail{
    AddressLine1: "1 Somewhere Lane",
    City:         "London",
    PostalCode:   "E5 8EE",
    CountryCode:  "GB",
  },
}

billingRequest, err := client.BillingRequests.CollectCustomerDetails(context, "BR123", billingRequestCollectCustomerDetailsParams)
```

Note we now have a link to a `Customer` and `Customer Billing Detail`

## Collect bank account details

Now we need to collect the customer bank account details to be able to create a `Mandate` against the customer.

```HTTP
POST https://api.gocardless.com/billing_requests/BRQ123/actions/collect_bank_account HTTP/1.1
Content-Type: application/json
{
  "data": {
    "account_number": "55779911",
    "branch_code": "200000",
    "account_holder_name": "Alice Smith",
    "country_code": "GB"
  }
}

HTTP/1.1 200
Content-Type: application/json
{
  "billing_requests": {
    "id": "BRQ123",
    ...
    "links": {
      "customer": "CU123",
      "customer_billing_detail": "CBD123"
    },
    ...
  },
  "resources": {
    "customer": {
      "id": "CU123",
      "created_at": "2021-03-22T12:20:04.238Z",
      "email": "alice@example.com",
      "given_name": "Alice",
      "family_name": "Smith",
      ...
    },
    "customer_billing_detail": {
      "id": "CBD123",
      "created_at": "2021-03-22T12:20:04.374Z",
      "address_line1": "1 Somewhere Lane",
      ...
    },
    "customer_bank_account": {
      "id": "BA123",
      "created_at": "2021-03-22T12:20:04.374Z",
      "account_holder_name": "Alice Smith",
      "account_number_ending": "11",
      "country_code": "GB",
      "currency": "GBP",
      "bank_name": "BARCLAYS BANK PLC",
      "enabled": true,
      "links": {
        "customer": "CU123"
      }
    }
  }
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/billing_requests/BRQ123/actions/collect_bank_account" \
-d @- << EOF
{
  "data": {
    "account_number": "55779911",
    "branch_code": "200000",
    "account_holder_name": "Alice Smith",
    "country_code": "GB"
  }
}
EOF
```

```PHP
$client->billingRequests()->collectBankAccount("BR123", [
  "params" => [
    "account_number" => "55779911",
    "branch_code" => "200000",
    "account_holder_name" => "Alice Smith",
    "country_code" => "GB"
  ]
]);
```

```python
client.billing_requests.collect_bank_account("BR123", params={
  "account_number": "55779911",
  "branch_code": "200000",
  "account_holder_name": "Alice Smith",
  "country_code": "GB",
})
```

```ruby
@client.billing_requests.collect_bank_account("BR123", {
  params: {
    account_number: "55779911",
    branch_code: "200000",
    account_holder_name: "Alice Smith",
    country_code: "GB",
  }
})
```

```java
client.billingRequests().collectBankAccount("BR123")
  .withAccountNumber("55779911")
  .withBranchCode("200000")
  .withAccountHolderName("Alice Smith")
  .withCountryCode("GB")
  .execute();
```

```javascript
const resp = await client.billingRequests.collectBankAccount("BR123", {
  account_number: "55779911",
  branch_code: "200000",
  account_holder_name: "Alice Smith",
  country_code: "GB",
});
```

```.net
var resp = await gocardless.BillingRequests.CollectBankAccountAsync("BR123",
  new BillingRequestCollectBankAccountRequest
  {
    AccountNumber = "55779911",
    BranchCode = "200000",
    AccountHolderName = "Alice Smith",
    CountryCode = "GB",
  });
```

```go
billingRequestCollectBankAccountParams := gocardless.BillingRequestCollectBankAccountParams{
  BranchCode:        "200000",
  CountryCode:       "GB",
  AccountNumber:     "55779911",
  AccountHolderName: "Alice Smith",
}

billingRequest, err := client.BillingRequests.CollectBankAccount(context, "BR123", billingRequestCollectBankAccountParams)
```

## Confirm Payer details

This is needed when you have a Mandate Request. As a scheme compliance rule, we are required to allow the payer to crosscheck the details entered by them and confirm them.

For a live integration, you would want to show a summary of the payer details (the information we took in the previous two steps) and give the option to cancel. For the purposes of this tutorial, we can just call the confirm endpoint.

```HTTP
POST https://api.gocardless.com/billing_requests/BRQ123/actions/confirm_payer_details HTTP/1.1

HTTP/1.1 200
Content-Type: application/json
{
  "billing_requests": {
    "id": "BRQ123",
    "mandate_request": {
      "currency": "GBP",
      "scheme": "bacs",
      "links": {
        "mandate": "MD123"
      }
    },
    "actions": [
      ...
      {
        "type": "confirm_payer_details",
        "required": true,
        "requires_actions": [
          "collect_customer_details",
          "collect_bank_account"
        ],
        "status": "completed"
      }
      ...
    ]
  }
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/billing_requests/BRQ123/actions/confirm_payer_details" \
-d @- << EOF
{}
EOF
```

```PHP
$client->billingRequests()->confirmPayerDetails("BR123");
```

```python
client.billing_requests.confirm_payer_details("BR123")
```

```ruby
@client.billing_requests.confirm_payer_details("BR123")
```

```java
client.billingRequests().confirmPayerDetails("BR123").execute();
```

```javascript
const resp = await client.billingRequests.confirmPayerDetails("BR123");
```

```.net
var resp = await gocardless.BillingRequests.ConfirmPayerDetailsAsync("BR123");
```

```go
billingRequestFulfilParams := gocardless.BillingRequestFulfilParams{}
billingRequest, err := client.BillingRequests.Fulfil(context, "BR123", billingRequestFulfilParams)
```

We want to keep track of our Mandate ID for the step where we take a payment.

## Fulfil

This step ‘executes’ the `Billing Request`, using the contents of our request to create a `Mandate`. This will create a `Mandate` within GoCardless to take payments against. The `fulfil` action is the step where the collected Information will be submitted to our partner bank(s).

It can be batched with the confirm payer details call above. It is a separate step (and API call) as we may sometimes want to combine different types of payment (e.g Open banking) with the creation of a `Mandate`.

```HTTP
POST https://api.gocardless.com/billing_requests/BRQ123/actions/fulfil HTTP/1.1

HTTP/1.1 200
Content-Type: application/json
{
  "billing_requests": {
    "id": "BRQ123",
    "status": "fulfilled",
    ...
  },
  ...
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/billing_requests/BRQ123/actions/fulfil" \
-d @- << EOF
{}
EOF
```

```PHP
$client->billingRequests()->fulfil("BR123");
```

```python
client.billing_requests.fulfil("BR123")
```

```ruby
billing_request = @client.billing_requests.fulfil("BR123")
```

```java
client.billingRequests().fulfil("BR123").execute();
```

```javascript
const resp = await client.billingRequests.fulfil("BR123");
```

```.net
var resp = await gocardless.BillingRequests.FulfilAsync("BR123");
```

```go
billingRequestFulfilParams := gocardless.BillingRequestFulfilParams{}
billingRequest, err := client.BillingRequests.Fulfil(context, "BR123", billingRequestFulfilParams)
```

## Taking a payment

We can now use the GoCardless Payments API to take a payment against our newly created `Mandate`!

```HTTP
POST https://api.gocardless.com/payments HTTP/1.1
Content-Type: application/json
{
  "payments": {
    "amount": 1200,
    "currency": "GBP",
    "reference": "Wine Box",
    "metadata": {
      "order_dispatch_date": "2023-03-29"
    },
    "links": {
      "mandate": "MD123"
    }
  }
}

HTTP/1.1 201 Created
Location: /payments/PM123
Content-Type: application/json
{
  "payments": {
    "id": "PM123",
    "created_at": "2023-03-22T17:01:06.000Z",
    "charge_date": "2023-03-24",
    "amount": 1200,
    "currency": "GBP",
    "status": "pending_submission",
    "reference": "WINEBOX001",
    "metadata": {
      "order_dispatch_date": "2023-03-29"
    },
    ...
    "links": {
      "mandate": "MD123",
      "creditor": "CR123"
    }
  }
}
```

```cURL
curl --silent \
-H "Content-Type: application/json" \
-H "Gocardless-Version: 2015-07-06" \
-H "Authorization: Bearer ${API_ACCESS_TOKEN}" \
"https://api.gocardless.com/payments" \
-d @- << EOF
{
  "payments": {
    "amount": 1200,
    "currency": "GBP",
    "charge_date": "2023-03-24",
    "reference": "Wine Box",
    "metadata": {
      "order_dispatch_date": "2023-03-29"
    },
    "links": {
      "mandate": "MD123"
    }
  }
}
EOF
```

```PHP
$client->payments()->create([
  "params" => ["amount" => 1200,
               "currency" => "GBP",
               "metadata" => [
                 "order_dispatch_date" => "2023-03-29"
               ],
               "links" => [
                 "mandate" => "MD123"
               ]]
]);
```

```python
client.payments.create(params={
  "amount": 1200,
  "currency": "GBP",
  "reference": "WINEBOX001",
  "metadata": {
    "order_dispatch_date": "2023-03-29"
  },
  "links": {
    "mandate": "MD123"
  }
})
```

```ruby
payment = @client.payments.create(
  params: {
    amount: 1200,
    currency: "GBP",
    description: "Wine Box",
    links: {
      mandate: "MD123"
    }
  },
)
```

```java
import com.gocardless.services.PaymentService.PaymentCreateRequest.Currency;

Payment payment = client.payments().create()
  .withAmount(1200)
  .withCurrency(Currency.GBP)
  .withReference("WINEBOX001")
  .withMetadata("order_dispatch_date", "2023-03-29")
  .withLinksMandate("MD123")
  .execute();
```

```javascript
const payment = await client.payments.create({
  amount: 1200,
  currency: "GBP",
  reference: "WINEBOX001",
  metadata: {
    order_dispatch_date: "2023-03-29",
  },
  links: {
    mandate: "MD123",
  },
});
```

```.net
var paymentRequest = new GoCardless.Services.PaymentCreateRequest()
{
    Amount = 1200,
    Currency = GoCardless.Services.PaymentCreateRequest.PaymentCurrency.GBP,
    Description = "Wine Box",
    Links = new GoCardless.Services.PaymentCreateRequest.PaymentLinks()
    {
        Mandate = "MD0123"
    }
};

var paymentResponse = await gocardless.Payments.CreateAsync(paymentRequest);
GoCardless.Resources.Payment payment = paymentResponse.Payment;
```

```go
paymentCreateParams := gocardless.PaymentCreateParams{
  Amount:     1200,
  Currency:   "GBP",
  Reference:  "WINEBOX001",
  Metadata:   map[string]interface{}{"order_dispatch_date": "2023-03-29"},
  Links: gocardless.PaymentCreateParamsLinks{
    Mandate: "MD123",
  },
}

payment, err := client.Payments.Create(context, paymentCreateParams)
```

Note that we charge the amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR).

We can see the date that the payment will be taken by looking at the `charge_date` in the response.

## What's next?
