# GoCardless Hosted Pages Overview

Source: https://docs.gocardless.com/docs/collect-payments/integration-types/gocardless-hosted-pages

# GoCardless Hosted Pages

This is the fastest way to start collecting payments. Redirect your customers to a GoCardless-hosted page to complete mandate setup and payment authorisation. Once done, they're redirected back to your site.

Supports: **All payment types** (one-off, recurring, instalments, Pay By Bank, Instant + DD, Commercial VRP)

## Best for

- Quick implementation with minimal development
- Teams without front-end development resources
- Prototyping and early releases
- A proven, scalable, compliant payment journey

## What you get out of the box

- Mobile-responsive design
- Multi-language support
- Scheme-appropriate authorisation flows per country
- Regulatory compliance handled
- Optimised conversion flow

You can set your company name and logo. For more control over the look and feel, consider the [Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow) or [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) approach.

## How it works

1. Create a Billing Request via the API, specifying the payment type
2. Create a Billing Request Flow; this generates a hosted URL
3. Redirect your customer to the URL
4. Customer completes authorisation on the GoCardless-hosted page
5. Customer is redirected back to your redirect_uri
6. Listen for webhooks to confirm the outcome

## Step-by-step guide

### Create a billing request

The Billing Request defines what you're collecting. The payload differs by payment type:

#### Direct Debit Mandate

```http
curl -X POST https://api.gocardless.com/billing_requests \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '
    }
  }'
```

```php
<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$response = $client->billingRequests()->create([
    'params' => [
        'mandate_request' => [
            'scheme' => 'bacs',
        ],
    ],
]);
```

```python

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

response = client.billing_requests.create(
    params=
    }
)
```

```ruby
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
    access_token: ENV['GC_ACCESS_TOKEN'],
    environment: :sandbox
)

response = client.billing_requests.create(
  params: 
  }
)
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequestCreateResponse response = client.billingRequests()
    .create()
    .withMandateRequestScheme("bacs")
    .execute();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const response = await client.billingRequests.create(,
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    params := gocardless.BillingRequestCreateParams,
    }

    result, err := client.BillingRequests.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(result)
}
```

**Response:**

```json
,
    "actions": [
      ,
      ,
      
    ]
  }
}
```

#### Pay By Bank

```http
curl -X POST https://api.gocardless.com/billing_requests \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '
    }
  }'
```

```php
<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$response = $client->billingRequests()->create([
    'params' => [
        'payment_request' => [
            'description' => 'Order #9012',
            'amount'      => 12000,
            'currency'    => 'GBP',
            'scheme'      => 'faster_payments',
        ],
    ],
]);
```

```python

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

response = client.billing_requests.create(
    params=
    }
)

```

```ruby
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
    access_token: ENV['GC_ACCESS_TOKEN'],
    environment: :sandbox
)

response = client.billing_requests.create(
  params: 
  }
)
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequestCreateResponse response = client.billingRequests()
    .create()
    .withPaymentRequestDescription("Order #9012")
    .withPaymentRequestAmount(12000)
    .withPaymentRequestCurrency("GBP")
    .withPaymentRequestScheme("faster_payments")
    .execute();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const response = await client.billingRequests.create(,
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    params := gocardless.BillingRequestCreateParams,
    }

    result, err := client.BillingRequests.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(result)
}
```

**Response:**

```json
,
    "actions": [
      ,
      ,
      
    ]
  }
}
```

#### Direct Debit + Pay By Bank

```http
curl -X POST https://api.gocardless.com/billing_requests \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d ',
      "mandate_request": 
    }
  }'
```

```php
<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$response = $client->billingRequests()->create([
    'params' => [
        'payment_request' => [
            'description' => 'First payment',
            'amount'      => 5000,
            'currency'    => 'GBP',
            'scheme'      => 'faster_payments',
        ],
        'mandate_request' => [
            'scheme' => 'bacs',
        ],
    ],
]);
```

```python

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

response = client.billing_requests.create(
    params=,
        'mandate_request': ,
    }
)
```

```ruby
  require 'gocardless_pro'

  client = GoCardlessPro::Client.new(
      access_token: ENV['GC_ACCESS_TOKEN'],
      environment: :sandbox
  )

  response = client.billing_requests.create(
    params: ,
      mandate_request: 
    }
  )
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequestCreateResponse response = client.billingRequests()
    .create()
    .withPaymentRequestDescription("First payment")
    .withPaymentRequestAmount(5000)
    .withPaymentRequestCurrency("GBP")
    .withPaymentRequestScheme("faster_payments")
    .withMandateRequestScheme("bacs")
    .execute();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const response = await client.billingRequests.create(,
  mandate_request: ,
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    ,
        MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest
        
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    params := gocardless.BillingRequestCreateParams,
        MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest,
    }

    result, err := client.BillingRequests.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(result)
}
```

**Response:**

```json
,
    "mandate_request": ,
    "actions": [
      ,
      ,
      ,
      ,
      
    ]
  }
}
```

#### Variable Recurring Payments (VRP)

```http
curl -X POST https://api.gocardless.com/billing_requests \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d ']
        }
      }
    }
  }'
```

```php
<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$response = $client->billingRequests()->create([
    'params' => [
        'fallback_enabled'     => true,
        'purpose_code'         => 'loan',
        'payment_context_code' => 'billing_goods_and_services_in_arrears',
        'payment_purpose_code' => 'bank_loan_delayed_draw_funding',
        'mandate_request'      => [
            'scheme'      => 'faster_payments',
            'constraints' => [
                'start_date'             => '2024-11-01',
                'max_amount_per_payment' => 50000,
                'periodic_limits'        => [
                    [
                        'period'           => 'month',
                        'max_total_amount' => 100000,
                        'alignment'        => 'creation_date',
                    ],
                ],
            ],
        ],
    ],
]);
```

```python

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

response = client.billing_requests.create(
    params=,
                ],
            },
        },
    }
)
```

```ruby
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
    access_token: ENV['GC_ACCESS_TOKEN'],
    environment: :sandbox
)

response = client.billing_requests.create(
  params: 
        ]
      }
    }
  }
)
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequestCreateResponse response = client.billingRequests()
    .create()
    .withFallbackEnabled(true)
    .withPurposeCode("loan")
    .withPaymentContextCode("billing_goods_and_services_in_arrears")
    .withPaymentPurposeCode("bank_loan_delayed_draw_funding")
    .withMandateRequestScheme("faster_payments")
    .withMandateRequestConstraintsStartDate("2024-11-01")
    .withMandateRequestConstraintsMaxAmountPerPayment(50000)
    .withMandateRequestConstraintsPeriodicLimitsBuilder()
        .withPeriod("month")
        .withMaxTotalAmount(100000)
        .withAlignment("creation_date")
    .done()
    .execute();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const response = await client.billingRequests.create(,
      ],
    },
  },
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    
                }
            }
        }
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    fallbackEnabled := true
    params := gocardless.BillingRequestCreateParams,
                },
            },
        },
    }

    result, err := client.BillingRequests.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(result)
}
```

**Response:**

```json
,
      "links": ,
      "constraints": 
        ]
      }
    },
    "payment_request": null,
    "subscription_request": null,
    "instalment_schedule_request": null,
    "metadata": ,
    "fallback_enabled": true,
    "fallback_occurred": false,
    "purpose_code": "loan",
    "payment_purpose_code": "bank_loan_delayed_draw_funding",
    "sign_flow_url": null,
    "auto_fulfil": false,
    "actions": [
      
        }
      },
      ,
      ,
      
      },
      
    ],
    "links": 
  }
}
```

### Create a billing request flow

This generates the hosted URL where the customer completes authorisation.

```php
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequestFlows()->create([
"params" => [
"redirect_uri" => "https://my-company.com/landing",
"exit_uri" => "https://my-company.com/exit",
"links" => [
"billing_request" => "BRQ000010NMDMH2"
]
]
]);

````

```python

client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_request_flows.create(params=
})
````

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_request_flows.create(
  params: 
  }
)
```

```java

String accessToken = "your_access_token_here";
GoCardlessClient client = GoCardlessClient
    .newBuilder(accessToken)
    .withEnvironment(SANDBOX)
    .build();

BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create()
  .withRedirectUri("https://my-company.com/landing")
  .withExitUri("https://my-company.com/exit")
  .withLinksBillingRequest("BRQ000010NMDMH2")
  .execute();
```

```javascript
const constants = require("gocardless-nodejs/constants");
const gocardless = require("gocardless-nodejs");
const client = gocardless("your_access_token_here", constants.Environments.Sandbox);

const billingRequestFlow = await client.billingRequestFlows.create(,
});
```

```cs
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var resp = await gocardless.BillingRequestFlows.CreateAsync(
  new GoCardless.Services.BillingRequestFlowCreateRequest()
  ,
  }
);

GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow;
```

```http
POST https://api.gocardless.com/billing_request_flows HTTP/1.1

  }
}
```

```go
package main

	gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

accessToken := "your_access_token_here";
opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint)
client, err := gocardless.New(accessToken, opts)

billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams
billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing"
billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit"
billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2"
billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams)
```

```cli
gc create billing_request_flow \
  -d "links[billing_request]= BRQ000010NMDMH2" \
  -d 'redirect_uri=https://my-company.com/landing' \
  -d 'exit_uri=https://my-company.com/exit'
```

Response:

```json

  }
}
```

The response includes an authorisation_url; redirect your customer there.

### Handle the redirect

Send your customer to the authorisation_url. GoCardless collects any required details: name, email, bank account and handles the scheme-appropriate authorisation flow.

When the customer completes or exits, they are redirected to your redirect_uri or exit_uri with query parameters:

| Parameter               | Example value |
| ----------------------- | ------------- |
| billing_request_id      | BRQ0000101    |
| billing_request_flow_id | BRF0000101    |

> **Warning:**
> Don't use the redirect to confirm the outcome. Always use webhooks.

### Listen for webhooks

| Event                        | Meaning                                  |
| ---------------------------- | ---------------------------------------- |
| billing_request_fulfilled    | Customer completed the flow              |
| mandate_created              | Mandate is active (for DD payment types) |
| payment_confirmed            | Payment confirmed (for Pay By Bank)      |
| billing_request_flow_expired | The customer didn't complete on time     |

#### Pre-collecting customer details

If you already have the customer's name, email, and address, submit them before creating the flow. The hosted page skips those fields or locks them if you prefer.

### Collect customer details (optional)

```php
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequests()->collectCustomerDetails("BR123", [
"params" => [
"customer" => [
"email" => "paddington@bearthings.com"
"given_name" => "Paddington",
"family_name" => "Bear"
],
"customer_billing_detail" => [
"address_line1" => "32 Windsor Gardens",
"city" => "London",
"postal_code" => "W9 3RG",
"country_code" => "GB"
]
]
]);

````

```python

client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_requests.collect_customer_details("BR123", params=,
  customer_billing_detail: 
})
````

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_requests.collect_customer_details("BR123", ,
    customer_billing_detail: 
  }
})
```

```java
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_requests.collect_customer_details("BR123", ,
    customer_billing_detail: 
  }
})
```

```javascript
const constants = require('gocardless-nodejs/constants');
const gocardless = require('gocardless-nodejs');
const client = gocardless('your_access_token_here', constants.Environments.Sandbox);

const resp = await client.billingRequests.collectCustomerDetails("BR123", ,
  customer_billing_detail: 
});
```

```cs
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var customer = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomer
;

var customerBillingDetail =new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomerBillingDetail
;

var resp = await gocardless.BillingRequests.CollectCustomerDetails("BR123",
  new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest
  );
```

```http
POST /billing_requests/BRQ000010NMDMH2/actions/collect_customer_details HTTP/1.1
,
    "customer_billing_detail": 
  }
}
```

```go
package main

	gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

accessToken := "your_access_token_here"
config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint))
if err != nil 
client, err := gocardless.New(config)
if err != nil 

billingRequestCollectCustomerDetailsParams := gocardless.BillingRequestCollectCustomerDetailsParams,
  CustomerBillingDetail: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail,
}

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

**Response:** Updated Billing Request with collect_customer_details marked completed.

### Collect bank account (optional)

```php
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequests()->collectBankAccount("BRQ000010NMDMH2", [
"params" => [
"account_number" => "55779911",
"branch_code" => "200000",
"account_holder_name" => "Frank Osborne",
"country_code" => "GB"
]
]);

````

```python

client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_requests.collect_bank_account("BRQ000010NMDMH2", params=)
````

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_requests.collect_bank_account("BRQ000010NMDMH2", 
})
```

```java

String accessToken = "your_access_token_here";
GoCardlessClient client = GoCardlessClient
    .newBuilder(accessToken)
    .withEnvironment(SANDBOX)
    .build();

client.billingRequests().collectBankAccount("BRQ000010NMDMH2")
  .withAccountNumber("55779911")
  .withBranchCode("200000")
  .withAccountHolderName("Frank Osborne")
  .withCountryCode("GB")
  .execute();
```

```javascript
const constants = require("gocardless-nodejs/constants");
const gocardless = require("gocardless-nodejs");
const client = gocardless("your_access_token_here", constants.Environments.Sandbox);

const resp = await client.billingRequests.collectBankAccount("BRQ000010NMDMH2", );
```

```cs
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var resp = await gocardless.BillingRequests.CollectBankAccountAsync("BRQ000010NMDMH2",
  new BillingRequestCollectBankAccountRequest
  );
```

```http
POST /billing_requests/BRQ000010NMDMH2/actions/collect_bank_account HTTP/1.1

}
```

```go
package main

	gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

accessToken := "your_access_token_here"
config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint))
if err != nil 
client, err := gocardless.New(config)
if err != nil 

billingRequestCollectBankAccountParams := gocardless.BillingRequestCollectBankAccountParams

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

**Response:** Updated Billing Request with collect_bank_account marked completed.

> **Info:**
> When creating the Billing Request Flow, pass `lock_customer_details: true` and/or
>   `lock_bank_account: true` to prevent customers editing pre-filled values.

## What's next?

  
#### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates)

Create mandates and collect bank account details via the API.

  
#### [Prefill Customer Details](/docs/optimise/prefill-customer-details)

Skip form steps by supplying customer details before the hosted flow.

  
#### [JavaScript Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow)

Embed the payment flow directly on your site without redirecting customers.

  
#### [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages)

Full API control for teams that need complete UX ownership.