# One-off Direct Debit

Source: https://docs.gocardless.com/docs/collect-payments/one-off-payments/one-off-direct-debit

# One-off Direct Debit

One-off Direct Debits allow you to collect fixed or variable amounts from your customers on a flexible schedule. The customer sets up a Direct Debit mandate once; after that, you can collect payments of any amount at any time without requiring re-authorisation.

**Best for:** Usage-based billing, professional services with variable charges, invoice payments.

## One-off Direct Debit vs Pay By Bank

|                            | One-off via Direct Debit                    | Pay By Bank                      |
| -------------------------- | ------------------------------------------- | -------------------------------- |
| Mandate required           | Yes                                         | No                               |
| Customer authorisation     | Once (mandate setup)                        | Per payment                      |
| Confirmation speed         | 2-5 business days                           | Minutes                          |
| Re-use for future payments | Yes, collect again without re-authorisation | No, new authorisation each time  |
| Protection                 | Scheme-specific                             | None                             |
| Customer experience        | One-time setup, then hands-off              | The bank app redirects each time |

For time-sensitive payments, consider [Pay By Bank](/docs/collect-payments/one-off-payments/pay-by-bank), which confirms within seconds. If you need immediate confirmation for the first payment but also want a mandate for future charges, use [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) instead.

## How it works

1. The customer sets up a mandate via your chosen integration
2. You create a payment against the mandate via the API
3. GoCardless collects the payment (typically 2-5 business days)
4. You receive a webhook confirming the payment status
5. Funds are included in your next payout

**Key differences from recurring payments:** You control when and how much to charge. There's no automatic schedule; you create each payment individually via the API.

## Step-by-step guide

### Create a billing request

```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
import os

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
import com.gocardless.GoCardlessClient;

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(,
});
```

```net
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

  }
}
```

### Confirm the mandate

After creating the Billing Request, direct the customer to authorise the mandate. How you do this depends on your integration type:

- Hosted Pages — Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages).
- Custom API — Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages).

### Handle the outcome

Listen for webhooks to confirm the payment status:

| Event                     | Meaning                          |
| ------------------------- | -------------------------------- |
| billing_request_fulfilled | Customer authorised the mandate  |
| mandates_created          | Mandate created and ready to use |
| mandates_active           | Mandate active                   |

### Collect a payment

Retrieve the mandate ID from the fulfilled billing request:

```http
curl https://api.gocardless.com/billing_requests/BRQ000123 \\
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

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

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

$response = $client->billingRequests()->get('BRQ000123');

$mandateId = $response->mandate_request->links->mandate;
```

```python
import os

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

response = client.billing_requests.get('BRQ000123')

mandate_id = response.mandate_request.links.mandate
```

```ruby
require 'gocardless_pro'

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

response = client.billing_requests.get('BRQ000123')

mandate_id = response.mandate_request.links.mandate
```

```java
import com.gocardless.GoCardlessClient;

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

BillingRequest billingRequest = client.billingRequests()
.get("BRQ000123")
.execute();

String mandateId = billingRequest.getMandateRequest().getLinks().getMandate();
```

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

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

const billingRequest = await client.billingRequests.find("BRQ000123");

const mandateId = billingRequest.mandate_request.links.mandate;
```

```net
using GoCardless;

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

var billingRequest = await client.BillingRequests.GetAsync("BRQ000123");

var mandateId = billingRequest.MandateRequest.Links.Mandate;
```

```go
package main

    "context"
    "fmt"
    "os"

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

)

func main() 

    billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123")
    if err != nil 

    mandateId := billingRequest.MandateRequest.Links.Mandate
    fmt.Println(mandateId)

}
```

**Response:**

```json

    }
  }
}
```

**Then collect whenever you need to:**

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

```php
$response = $client->payments()->create([
    'params' => [
        'amount'      => 5000,
        'currency'    => 'GBP',
        'description' => 'Order #1234',
        'links'       => [
            'mandate' => 'MD123',
        ],
    ],
]);
```

```python
response = client.payments.create(
    params=,
    }
)
```

```ruby
response = client.payments.create(
  params: 
  }
)
```

```java
Payment payment = client.payments()
    .create()
    .withAmount(5000)
    .withCurrency("GBP")
    .withDescription("Order #1234")
    .withLinksMandate("MD123")
    .execute();
```

```javascript
const payment = await client.payments.create(,
});
```

```net
var payment = await client.Payments.CreateAsync(
    new PaymentCreateRequest
    
    }
);
```

```go
params := gocardless.PaymentCreateParams,
}

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

## What's next?

  
#### [Pay By Bank](/docs/collect-payments/one-off-payments/pay-by-bank)

Instant bank payments that confirm within seconds — no mandate required.

  
#### [Recurring Payments](/docs/collect-payments/recurring-payments/subscriptions)

Set up automatic subscription schedules against an active mandate.

  
#### [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate)

Collect an instant first payment while setting up a mandate for future charges.

  
#### [Mandate Events](/docs/collect-payments/events-and-webhooks/mandate-events)

Understand the webhooks fired during the mandate and payment lifecycle.