> This page is for version v2 (default).
> For other versions, use one of these documentation indexes:
> - v2 (default): https://developers.clearpay.co.uk/v-2/llms.txt
> - v1: https://developers.clearpay.co.uk/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.clearpay.co.uk/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.clearpay.co.uk/_mcp/server.

# Capture Full Payment

POST https://global-api-sandbox.afterpay.com/v2/payments/capture
Content-Type: application/json

This endpoint performs a payment capture for the full value of the payment plan.

This operation is [idempotent](/idempotent-requests) based on the token, which allows for the safe retry of requests, guaranteeing the payment operation is only performed once.

Since the idempotency of this endpoint is based on the `token`, the inclusion of a `requestId` is not required.

## Approved Response (201)

If payment is approved by Clearpay, returns a [Payment object](/payment-object) in response, with a `status` of "APPROVED".

## Declined Response (201)

If payment is declined by Clearpay, for example, if invalid card details were entered, returns a [Payment object](/payment-object) in response, with a `status` of "DECLINED".

Please advise the consumer to contact the Clearpay Customer Service team for more information.

## Connection Timeouts

* Open timeout: 10 seconds
* Read timeout: 70 seconds

## Errors

In addition to the [PUT/POST Errors](/put-post-errors) applicable to all POST endpoints, the following errors are specific to Capture Full Payment:

| HTTP Status Code              | errorCode                          | Description                                                                            |
| :---------------------------- | :--------------------------------- | :------------------------------------------------------------------------------------- |
| **402**  Payment Required     | `invalid_token`                    | The checkout token is invalid, expired, or does not exist.                             |
| **412**  Precondition Failed  | `invalid_order_transaction_status` | The Consumer has not confirmed their payment for the order associated with this token. |
| **422**  Unprocessable Entity | `invalid_object`                   | The checkout token was missing or empty.                                               |

Reference: https://developers.clearpay.co.uk/immediate-payment-flow/capture-full-payment

## Authentication

- `Authorization` header (basic auth, required) — Basic authentication of the form `Basic <base64(username:password)>`.

## Request

### Headers

- `Accept` (string, optional, default: application/json)

### Body (application/json)

This endpoint expects an object.

- `token` (string, required) — The token returned in the [Create Checkout](/api-reference/online-api/checkouts/create-checkout) request.
- `merchantReference` (string, optional) — The merchant’s order id/reference that this payment corresponds to. This will update any value previously provided in the [Create Checkout](/api-reference/online-api/checkouts/create-checkout) request.

## Response

### 201

Payment Approved or Declined - Returns a Payment object

- `id` (string, required) — The unique, permanent, Clearpay-generated Order ID.
- `token` (string, required) — Checkout token that was used to complete payment.
- `status` (enum, required) — An order status of "APPROVED" or "DECLINED".
  - Allowed values: `APPROVED`, `DECLINED`
- `created` (string, required) — The UTC timestamp of when the payment was completed, in ISO 8601 format.
- `originalAmount` (PaymentOriginalAmount, required)
- `openToCaptureAmount` (PaymentOpenToCaptureAmount, required)
- `paymentState` (enum, required) — Current state for capturing payments.
  - Allowed values: `AUTH_APPROVED`, `AUTH_DECLINED`, `PARTIALLY_CAPTURED`, `CAPTURED`, `CAPTURE_DECLINED`, `VOIDED`
- `merchantReference` (string, required) — The merchant's order id/reference that this payment corresponds to.
- `refunds` (list of Refund, required) — An array of refunds. Note: in response to a Capture Full Payment call, this array will always be empty, since refunds cannot occur until payment is captured.
- `orderDetails` (OrderDetails, required)
- `events` (list of PaymentEvent, required) — One or more payment events that have occurred against the order.

## Errors

### 400 Bad Request Error

Bad Request - Invalid JSON or request format

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 401 Unauthorized Error

Unauthorized - Invalid API credentials

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 402 Payment Required Error

Payment Required - Invalid or expired token

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 405 Method Not Allowed Error

Method Not Allowed - Invalid HTTP method

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 406 Not Acceptable Error

Not Acceptable - Invalid Accept header

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 412 Precondition Failed Error

Precondition Failed - Consumer has not confirmed payment

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 415 Unsupported Media Type Error

Unsupported Media Type - Invalid Content-Type header

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 422 Unprocessable Entity Error

Unprocessable Entity - Missing or empty checkout token

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

### 500 Internal Server Error

Internal Server Error - Server error or missing request body

- `errorCode` (string, required) — A machine-readable error code that identifies the type of error.
- `errorId` (string, required) — A unique identifier for this specific error occurrence.
- `message` (string, required) — A human-readable description of the error.
- `httpStatusCode` (integer, required) — The HTTP status code associated with this error.

## Types

### PaymentOriginalAmount

- `amount` (string, required) — The amount as a string representation of a decimal number, rounded to 2 decimal places.
- `currency` (enum, required) — The currency in ISO 4217 format. Only "GBP" is supported.
  - Allowed values: `GBP`

### PaymentOpenToCaptureAmount

- `amount` (string, required) — The amount as a string representation of a decimal number, rounded to 2 decimal places.
- `currency` (enum, required) — The currency in ISO 4217 format. Only "GBP" is supported.
  - Allowed values: `GBP`

### Refund

- `amount` (Money, required)
- `requestId` (string, optional) — A unique request ID, required (in conjunction with `merchantReference`) for safe retries. It is recommended that the merchant generate a UUID for each unique refund.
- `merchantReference` (string, optional) — The merchant's corresponding refund ID or reference, required (in conjunction with `requestId`) for safe retries.
- `refundId` (string, optional) — The unique, Clearpay-generated refund ID.
- `refundedAt` (string, optional) — A UTC timestamp of the refund creation time, in ISO 8601 format.
- `refundMerchantReference` (string, optional) — A unique reference for the individual refund event. If provided, the value will appear in the daily settlement file as "Payment Event ID". In most cases, this would hold the same value as the `merchantReference`.

### OrderDetails

- `consumer` (Consumer, required)
- `billing` (Contact, optional)
- `shipping` (Contact, optional)
- `courier` (ShippingCourier, optional)
- `items` (list of Item, optional)
- `discounts` (list of Discount, optional)
- `taxAmount` (Money, optional)
- `shippingAmount` (Money, optional)

### PaymentEvent

- `id` (string, optional) — The unique, Clearpay-generated event ID.
- `created` (string, optional) — A UTC timestamp of the event creation time, in ISO 8601 format.
- `expires` (string, optional, nullable) — A UTC timestamp of the "AUTH_APPROVED" event expiration time, in ISO 8601 format. Null for other event types.
- `type` (enum, optional) — The event type.
  - Allowed values: `AUTH_APPROVED`, `AUTH_DECLINED`, `CAPTURED`, `CAPTURE_DECLINED`, `VOIDED`, `EXPIRED`
- `amount` (Money, optional)
- `paymentEventMerchantReference` (string, optional, nullable) — A unique reference for an individual payment capture event. If provided on Capture Payment, the value will appear in the daily settlement file as "Payment Event ID".

### Money

- `amount` (string, required) — The amount as a string representation of a decimal number, rounded to 2 decimal places.
- `currency` (enum, required) — The currency in ISO 4217 format. Only "GBP" is supported.
  - Allowed values: `GBP`

### Consumer

- `givenNames` (string, required) — The consumer's first name and any middle names. Limited to 128 characters.
- `surname` (string, required) — The consumer's last name. Limited to 128 characters.
- `email` (string, required) — The consumer's email address. Limited to 128 characters.
- `phoneNumber` (string, optional) — The consumer's phone number. Limited to 32 characters.

### Contact

- `name` (string, optional) — Full name of contact. Limited to 255 characters.
- `line1` (string, optional) — First line of the address. Limited to 128 characters.
- `line2` (string, optional) — Second line of the address. Limited to 128 characters.
- `area1` (string, optional) — UK postal town or EU Suburb or Town. Limited to 128 characters.
- `area2` (string, optional) — UK village or local area, EU Province. Limited to 128 characters.
- `region` (string, optional) — UK county, EU region. Limited to 128 characters.
- `postcode` (string, optional) — Postal code. Limited to 128 characters.
- `countryCode` (string, optional) — The two-character ISO 3166-1 country code.
- `phoneNumber` (string, optional) — The phone number, in E.123 format. Limited to 32 characters.

### ShippingCourier

- `shippedAt` (string, optional) — The time at which the order was shipped, in ISO 8601 format.
- `name` (string, optional) — The name of the courier. Limited to 128 characters.
- `tracking` (string, optional) — The tracking number provided by the courier. Limited to 128 characters.
- `priority` (enum, optional) — The shipping priority. If provided, must be either "STANDARD" or "EXPRESS".
  - Allowed values: `STANDARD`, `EXPRESS`

### Item

- `name` (string, required) — Product name. Limited to 255 characters.
- `quantity` (integer, required) — The quantity of the item, stored as a signed 32-bit integer.
- `sku` (string, optional) — Product SKU. Limited to 128 characters.
- `pageUrl` (string, optional) — The canonical URL for the item's Product Detail Page. Limited to 2048 characters.
- `imageUrl` (string, optional) — A URL for a web-optimised photo of the item, suitable for use directly as the `src` attribute of an `img` tag. Limited to 2048 characters.
- `price` (Money, optional)
- `categories` (list of list of string, optional) — An array of arrays to accommodate multiple categories that apply to the item. Each array represents a hierarchical path to a category, with the left-most category being the top-level parent category.
- `estimatedShipmentDate` (string, optional) — The estimated date when the order will be shipped, in `YYYY-MM` or `YYYY-MM-DD` format.

### Discount

- `displayName` (string, required) — A display name for the discount. Limited to 128 characters.
- `amount` (Money, optional)

## Examples

### Payment successfully approved

**Request**

```json
{
  "token": "string"
}
```

**Response**

```json
{
  "id": "12345678",
  "token": "ltqdpjhbqu3veqikk95g7p3fhvcchfvtlsiobah3u4l5nln8gii9",
  "status": "APPROVED",
  "created": "2019-01-01T00:00:00.000Z",
  "originalAmount": {
    "amount": "100.00",
    "currency": "GBP"
  },
  "openToCaptureAmount": {
    "amount": "0.00",
    "currency": "GBP"
  },
  "paymentState": "CAPTURED",
  "merchantReference": "merchantOrderId-1234",
  "refunds": [],
  "orderDetails": {
    "consumer": {
      "givenNames": "Joe",
      "surname": "Consumer",
      "email": "test@example.com"
    }
  },
  "events": [
    {
      "id": "1OUR16OTqL3DgJ3ELlwKowU9v6K",
      "created": "2019-01-01T00:00:00.000Z",
      "expires": null,
      "type": "CAPTURED",
      "amount": {
        "amount": "100.00",
        "currency": "GBP"
      }
    }
  ]
}
```

**SDK Code**

```python Payment successfully approved
import requests

url = "https://global-api-sandbox.afterpay.com/v2/payments/capture"

payload = { "token": "string" }
headers = {
    "User-Agent": "User-Agent"
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers, auth=("<username>", "<password>"))

print(response.json())
```

```javascript Payment successfully approved
const url = 'https://global-api-sandbox.afterpay.com/v2/payments/capture';
const credentials = btoa("<username>:<password>");

const options = {
  method: 'POST',
  headers: {
    'User-Agent': 'User-Agent',
    Authorization: `Basic ${credentials}`,
    'Content-Type': 'application/json'
  },
  body: '{"token":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Payment successfully approved
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://global-api-sandbox.afterpay.com/v2/payments/capture"

	payload := strings.NewReader("{\n  \"token\": \"string\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("User-Agent", "User-Agent")
	req.SetBasicAuth("<username>", "<password>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Payment successfully approved
require 'uri'
require 'net/http'

url = URI("https://global-api-sandbox.afterpay.com/v2/payments/capture")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["User-Agent"] = 'User-Agent'
request.basic_auth("<username>", "<password>")
request["Content-Type"] = 'application/json'
request.body = "{\n  \"token\": \"string\"\n}"

response = http.request(request)
puts response.read_body
```

```java Payment successfully approved
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://global-api-sandbox.afterpay.com/v2/payments/capture")
  .header("User-Agent", "User-Agent")
  .basicAuth("<username>", "<password>")
  .header("Content-Type", "application/json")
  .body("{\n  \"token\": \"string\"\n}")
  .asString();
```

```php Payment successfully approved
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://global-api-sandbox.afterpay.com/v2/payments/capture', [
  'body' => '{
  "token": "string"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'User-Agent' => 'User-Agent',
  ],
    'auth' => ['<username>', '<password>'],
]);

echo $response->getBody();
```

```csharp Payment successfully approved
using RestSharp;
using RestSharp.Authenticators;

var client = new RestClient("https://global-api-sandbox.afterpay.com/v2/payments/capture");
client.Authenticator = new HttpBasicAuthenticator("<username>", "<password>");
var request = new RestRequest(Method.POST);
request.AddHeader("User-Agent", "User-Agent");

request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"token\": \"string\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Payment successfully approved
import Foundation

let credentials = Data("<username>:<password>".utf8).base64EncodedString()

let headers = [
  "User-Agent": "User-Agent",
  "Authorization": "Basic \(credentials)",
  "Content-Type": "application/json"
]
let parameters = ["token": "string"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://global-api-sandbox.afterpay.com/v2/payments/capture")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Payment declined by Clearpay

**Request**

```json
{
  "token": "string"
}
```

**Response**

```json
{
  "id": "12345679",
  "token": "ltqdpjhbqu3veqikk95g7p3fhvcchfvtlsiobah3u4l5nln8gii9",
  "status": "DECLINED",
  "created": "2019-01-01T00:00:00.000Z",
  "originalAmount": {
    "amount": "100.00",
    "currency": "GBP"
  },
  "openToCaptureAmount": {
    "amount": "0.00",
    "currency": "GBP"
  },
  "paymentState": "CAPTURE_DECLINED",
  "merchantReference": "merchantOrderId-1234",
  "refunds": [],
  "orderDetails": {
    "consumer": {
      "givenNames": "Joe",
      "surname": "Consumer",
      "email": "test@example.com"
    }
  },
  "events": [
    {
      "id": "1OUR16OTqL3DgJ3ELlwKowU9v6K",
      "created": "2019-01-01T00:00:00.000Z",
      "expires": null,
      "type": "CAPTURE_DECLINED",
      "amount": {
        "amount": "100.00",
        "currency": "GBP"
      }
    }
  ]
}
```

**SDK Code**

```python Payment declined by Clearpay
import requests

url = "https://global-api-sandbox.afterpay.com/v2/payments/capture"

payload = { "token": "string" }
headers = {
    "User-Agent": "User-Agent"
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers, auth=("<username>", "<password>"))

print(response.json())
```

```javascript Payment declined by Clearpay
const url = 'https://global-api-sandbox.afterpay.com/v2/payments/capture';
const credentials = btoa("<username>:<password>");

const options = {
  method: 'POST',
  headers: {
    'User-Agent': 'User-Agent',
    Authorization: `Basic ${credentials}`,
    'Content-Type': 'application/json'
  },
  body: '{"token":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Payment declined by Clearpay
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://global-api-sandbox.afterpay.com/v2/payments/capture"

	payload := strings.NewReader("{\n  \"token\": \"string\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("User-Agent", "User-Agent")
	req.SetBasicAuth("<username>", "<password>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Payment declined by Clearpay
require 'uri'
require 'net/http'

url = URI("https://global-api-sandbox.afterpay.com/v2/payments/capture")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["User-Agent"] = 'User-Agent'
request.basic_auth("<username>", "<password>")
request["Content-Type"] = 'application/json'
request.body = "{\n  \"token\": \"string\"\n}"

response = http.request(request)
puts response.read_body
```

```java Payment declined by Clearpay
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://global-api-sandbox.afterpay.com/v2/payments/capture")
  .header("User-Agent", "User-Agent")
  .basicAuth("<username>", "<password>")
  .header("Content-Type", "application/json")
  .body("{\n  \"token\": \"string\"\n}")
  .asString();
```

```php Payment declined by Clearpay
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://global-api-sandbox.afterpay.com/v2/payments/capture', [
  'body' => '{
  "token": "string"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'User-Agent' => 'User-Agent',
  ],
    'auth' => ['<username>', '<password>'],
]);

echo $response->getBody();
```

```csharp Payment declined by Clearpay
using RestSharp;
using RestSharp.Authenticators;

var client = new RestClient("https://global-api-sandbox.afterpay.com/v2/payments/capture");
client.Authenticator = new HttpBasicAuthenticator("<username>", "<password>");
var request = new RestRequest(Method.POST);
request.AddHeader("User-Agent", "User-Agent");

request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"token\": \"string\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Payment declined by Clearpay
import Foundation

let credentials = Data("<username>:<password>".utf8).base64EncodedString()

let headers = [
  "User-Agent": "User-Agent",
  "Authorization": "Basic \(credentials)",
  "Content-Type": "application/json"
]
let parameters = ["token": "string"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://global-api-sandbox.afterpay.com/v2/payments/capture")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```