> ## Documentation Index
> Fetch the complete documentation index at: https://docs.choosefloat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a checkout

> POST /api/checkouts — create a payment session and get the hosted payment URL.

Creates a checkout and returns the `payment_url` to redirect your shopper to. See the [accepting payments guide](/guides/accepting-payments) for how this call fits into the full flow.

<Note>
  Rate limited to **1 request per second** — comfortably above normal checkout traffic, but batch jobs should space their calls.
</Note>

## Request

Headers: `Authorization: Bearer <client_secret>`, `Content-Type: application/json`, and `X-Signature` ([request signing](/authentication#request-signing)).

<ParamField body="checkout" type="object" required>
  Wrapper object for all checkout fields.
</ParamField>

<ParamField body="checkout.amount" type="integer" required>
  Total payable amount in **pence**. Must fall inside a band in your [merchant config](/api-reference/get-config) `rules`, otherwise `422`.
</ParamField>

<ParamField body="checkout.currency" type="string" required>
  ISO 4217 code. Must match your merchant territory currency: `GBP`.
</ParamField>

<ParamField body="checkout.client_reference_id" type="string" required>
  Your identifier for this order or cart session. Echoed verbatim in the [callback](/guides/callbacks) — use it to reconcile.
</ParamField>

<ParamField body="checkout.notify_url" type="string (url)" required>
  Public HTTPS endpoint that receives the signed payment-result callback.
</ParamField>

<ParamField body="checkout.success_url" type="string (url)" required>
  Where the shopper's browser is sent after successful payment (unless your callback response supplies a [dynamic `redirect_url`](/guides/callbacks#dynamic-redirect-optional)).
</ParamField>

<ParamField body="checkout.cancel_url" type="string (url)" required>
  Where the shopper's browser is sent if they cancel.
</ParamField>

<ParamField body="checkout.customer" type="object" required>
  The shopper. Pre-fill as much as you have — it reduces friction on the payment page.

  <Expandable title="customer fields">
    <ParamField body="email" type="string (email)" required>
      Shopper's email address.
    </ParamField>

    <ParamField body="first_name" type="string">
      Max 255 characters.
    </ParamField>

    <ParamField body="last_name" type="string">
      Max 255 characters.
    </ParamField>

    <ParamField body="phone_number" type="string">
      Must match `^[+0-9][0-9.()/-]{7,25}$` — digits with optional leading `+` and common separators.
    </ParamField>

    <ParamField body="billing_address" type="string">
      Free-text billing address.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="checkout.line_items" type="array">
  Cart contents, shown on the shopper's payment summary.

  <Expandable title="line item fields">
    <ParamField body="name" type="string" required>
      Item display name.
    </ParamField>

    <ParamField body="amount" type="integer" required>
      Unit price in pence.
    </ParamField>

    <ParamField body="quantity" type="integer" required>
      Number of units.
    </ParamField>
  </Expandable>
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  BODY='{"checkout":{"amount":249900,"currency":"GBP","client_reference_id":"order-1001","notify_url":"https://example.com/float/notify","success_url":"https://example.com/orders/1001/success","cancel_url":"https://example.com/orders/1001/cancel","customer":{"first_name":"Eric","last_name":"Cartman","email":"eric.cartman@example.com","phone_number":"0101234567"},"line_items":[{"name":"Clyde Frog","amount":249900,"quantity":1}]}}'

  SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha512 -hmac "$FLOAT_SIGNING_KEY" -binary | base64)

  curl -X POST https://uat-secure.choosefloat.com/api/checkouts \
    -H "Authorization: Bearer $FLOAT_CLIENT_SECRET" \
    -H "Content-Type: application/json" \
    -H "X-Signature: $SIGNATURE" \
    -d "$BODY"
  ```

  ```ruby Ruby theme={null}
  require "net/http"
  require "openssl"
  require "json"

  body = {
    checkout: {
      amount: 249_900,
      currency: "GBP",
      client_reference_id: "order-1001",
      notify_url: "https://example.com/float/notify",
      success_url: "https://example.com/orders/1001/success",
      cancel_url: "https://example.com/orders/1001/cancel",
      customer: {
        first_name: "Eric",
        last_name: "Cartman",
        email: "eric.cartman@example.com",
        phone_number: "0101234567"
      },
      line_items: [{ name: "Clyde Frog", amount: 249_900, quantity: 1 }]
    }
  }.to_json

  uri = URI("https://uat-secure.choosefloat.com/api/checkouts")
  response = Net::HTTP.post(
    uri,
    body,
    "Authorization" => "Bearer #{ENV.fetch('FLOAT_CLIENT_SECRET')}",
    "Content-Type"  => "application/json",
    "X-Signature"   => OpenSSL::HMAC.base64digest("SHA512", ENV.fetch("FLOAT_SIGNING_KEY"), body)
  )

  payment_url = JSON.parse(response.body).dig("data", "payment_url")
  ```

  ```javascript Node.js theme={null}
  const crypto = require("crypto");

  const body = JSON.stringify({
    checkout: {
      amount: 249900,
      currency: "GBP",
      client_reference_id: "order-1001",
      notify_url: "https://example.com/float/notify",
      success_url: "https://example.com/orders/1001/success",
      cancel_url: "https://example.com/orders/1001/cancel",
      customer: {
        first_name: "Eric",
        last_name: "Cartman",
        email: "eric.cartman@example.com",
        phone_number: "0101234567",
      },
      line_items: [{ name: "Clyde Frog", amount: 249900, quantity: 1 }],
    },
  });

  const signature = crypto
    .createHmac("sha512", process.env.FLOAT_SIGNING_KEY)
    .update(body)
    .digest("base64");

  const response = await fetch("https://uat-secure.choosefloat.com/api/checkouts", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FLOAT_CLIENT_SECRET}`,
      "Content-Type": "application/json",
      "X-Signature": signature,
    },
    body,
  });

  const { data } = await response.json();
  // redirect the shopper to data.payment_url
  ```

  ```php PHP theme={null}
  $body = json_encode([
      'checkout' => [
          'amount'              => 249900,
          'currency'            => 'GBP',
          'client_reference_id' => 'order-1001',
          'notify_url'          => 'https://example.com/float/notify',
          'success_url'         => 'https://example.com/orders/1001/success',
          'cancel_url'          => 'https://example.com/orders/1001/cancel',
          'customer' => [
              'first_name'   => 'Eric',
              'last_name'    => 'Cartman',
              'email'        => 'eric.cartman@example.com',
              'phone_number' => '0101234567',
          ],
          'line_items' => [
              ['name' => 'Clyde Frog', 'amount' => 249900, 'quantity' => 1],
          ],
      ],
  ]);

  $signature = base64_encode(hash_hmac('sha512', $body, getenv('FLOAT_SIGNING_KEY'), true));

  $ch = curl_init('https://uat-secure.choosefloat.com/api/checkouts');
  curl_setopt_array($ch, [
      CURLOPT_POST           => true,
      CURLOPT_POSTFIELDS     => $body,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER     => [
          'Authorization: Bearer ' . getenv('FLOAT_CLIENT_SECRET'),
          'Content-Type: application/json',
          'X-Signature: ' . $signature,
      ],
  ]);

  $response = json_decode(curl_exec($ch), true);
  $paymentUrl = $response['data']['payment_url'];
  ```

  ```python Python theme={null}
  import base64, hashlib, hmac, json, os
  import requests

  body = json.dumps({
      "checkout": {
          "amount": 249900,
          "currency": "GBP",
          "client_reference_id": "order-1001",
          "notify_url": "https://example.com/float/notify",
          "success_url": "https://example.com/orders/1001/success",
          "cancel_url": "https://example.com/orders/1001/cancel",
          "customer": {
              "first_name": "Eric",
              "last_name": "Cartman",
              "email": "eric.cartman@example.com",
              "phone_number": "0101234567",
          },
          "line_items": [{"name": "Clyde Frog", "amount": 249900, "quantity": 1}],
      }
  }, separators=(",", ":"))

  signature = base64.b64encode(
      hmac.new(os.environ["FLOAT_SIGNING_KEY"].encode(), body.encode(), hashlib.sha512).digest()
  ).decode()

  response = requests.post(
      "https://uat-secure.choosefloat.com/api/checkouts",
      data=body,
      headers={
          "Authorization": f"Bearer {os.environ['FLOAT_CLIENT_SECRET']}",
          "Content-Type": "application/json",
          "X-Signature": signature,
      },
  )

  payment_url = response.json()["data"]["payment_url"]
  ```
</CodeGroup>

## Response

```json 200 theme={null}
{
  "data": {
    "id": "9b2f61c4-6c1e-4b7a-9a1d-3f2a8c0de111",
    "payment_url": "https://uat-secure.choosefloat.com/payments/9b2f61c4-6c1e-4b7a-9a1d-3f2a8c0de111"
  }
}
```

<ResponseField name="data.id" type="string (uuid)">
  The checkout ID. **Persist it** — it's required for [status lookups](/api-reference/get-checkout) and [refunds](/api-reference/create-refund).
</ResponseField>

<ResponseField name="data.payment_url" type="string (url)">
  The hosted payment page. Redirect the shopper here. The session is valid for roughly 30 minutes.
</ResponseField>

## Errors

| HTTP  | When                         | Example `detail`                                                        |
| ----- | ---------------------------- | ----------------------------------------------------------------------- |
| `400` | Signature mismatch           | `Request signature does not match...`                                   |
| `401` | Bad Bearer token             |                                                                         |
| `422` | Validation failure           | `Validation failed: Amount has to be between £100.00 and £1,000,000.00` |
| `422` | Wrong currency for territory | `Currency must match merchant territory currency GBP`                   |
