# Create a checkout

`POST https://app.shuttleglobal.com/c/api/instances/{instance_key}/checkouts`

Create a hosted checkout session. The checkout accepts all parameters from the
Create Payment API (except `payment_method`), plus additional options that control
the checkout UX.

The response includes a checkout `id` (nonce) which you embed on your page via shuttle.js:

```html
<div data-shuttle-checkout="CHECKOUT_ID" data-shuttle-style="INLINE"></div>
<script src="https://app.shuttleglobal.com/shuttle-1.4.X.js"></script>
```

## Authentication

- basicAuth: Basic Authentication using secret key
- bearerAuth: OAuth 2.0 Bearer Token Authentication

## Request body (`application/json`), required

- `checkout` (object, required)
  - `options` (object): Checkout options. Includes all fields from the Create Payment API (except `payment_method`) plus UX-specific options for the hosted checkout experience.
    - `currency` (string, required): The currency in ISO format (e.g., USD, EUR, GBP)
    - `amount` (string): The payment amount as a string without commas, using '.' as decimal separator. Required in the standard case. Optional when `charges` is provided — if omitted, it is derived from the sum of `charges[].amount`; if supplied, it must equal that sum.
    - `alt_key` (string): Your unique reference for the payment (e.g., order ID)
    - `description` (string): Descriptive text for the payment
    - `nonce` (string): Unique string to prevent duplicate submissions within 24 hours
    - `action` (string): Payment action type. * `PAYMENT` — take the payment immediately. * `AUTH` — reserve the funds without capturing. Capture later via the Activity view or the Capture API. * `TOKENISE` — store the customer's payment details without taking a payment. No transaction and no contract are created; the result is a payment method you can charge later via the Create Payment API. Note the spelling: the value is `TOKENISE`, not `TOKENIZE`. When using `TOKENISE`, omit `amount` and all scheduling fields (`frequency`, `occurrences`, `start_date`, `start_days`, `scheduled_date`, `scheduled_days`, `charges`) — the checkout takes no payment, so there is nothing to schedule. `save_card` is redundant, as storing the card is the whole operation. Keep `currency`: it determines which payment methods are offered. The stored payment method is delivered on the `PAYMENT_METHOD.ACTIVE` webhook. Only payment methods capable of the requested action are displayed. For example Apple Pay does not support `TOKENISE`, and ACH does not support `AUTH`. One of: `PAYMENT`, `AUTH`, `TOKENISE`.
    - `source` (string): Source of the payment. Use MOTO if staff is entering details on behalf of customer One of: `MOTO`, `ECOMMERCE`.
    - `account` (one of)
    - `gateway` (string): Gateway ID to process the payment through
    - `frequency` (string): Payment frequency for recurring payments. Cannot be used together with `charges`; to use scheduled charges, omit `frequency` or set it to `ONEOFF`. One of: `ONEOFF`, `WEEKLY`, `FORTNIGHTLY`, `BIMONTHLY`, `MONTHLY`, `QUARTERLY`, `BIANNUALLY`, `ANNUALLY`.
    - `occurrences` (integer): Number of payments for recurring payments (blank = forever)
    - `start_date` (string (date-time)): When to take first payment for recurring payments
    - `start_days` (integer): Days from now for first recurring payment
    - `scheduled_date` (string (date-time)): When to process one-time payment
    - `scheduled_days` (integer): Days from now for one-time payment
    - `charges` (array of object): Explicit schedule of charges for the contract. Use this when charge amounts or due dates vary between charges. All charges are created upfront at contract creation and the customer sees the full schedule in the hosted checkout. **When each charge is taken:** * `due: "now"` or a past timestamp (within the last 24 hours) — taken **synchronously** as part of contract creation. A decline blocks the whole contract creation. * `due` set to a future timestamp — taken **asynchronously** by the scheduler on the due date. The contract is created regardless of that later payment's outcome. To have the first charge run asynchronously, set its `due` to a future timestamp (even a few minutes ahead). **Constraints:** * Cannot be combined with `frequency` (must be omitted or `ONEOFF`). * Not supported with `action: AUTH`. * Each charge's `due` cannot be more than 24 hours in the past. * The top-level `amount` is optional when `charges` is provided. If you do provide `amount`, it must equal the sum of `charges[].amount`.
      - `alt_key` (string): Optional — your unique reference for this charge (e.g., instalment number or invoice line id). URL friendly string, max 64 chars (a-z0-9_-)
      - `amount` (string, required): The charge amount as a string without commas, using '.' as decimal separator. Must be greater than zero.
      - `due` (string, required): When this charge is due. Accepts either the literal string `"now"`, or an ISO 8601 timestamp. * `"now"` or a past timestamp (within the last 24 hours) — taken **synchronously** during contract creation. A decline blocks the whole contract creation. * Future timestamp — taken **asynchronously** by the scheduler on the due date. The contract is created regardless of that later payment's outcome. A timestamp more than 24 hours in the past is rejected.
    - `keep_active_until` (string (date-time)): Optional. Only relevant when the checkout creates a contract (a recurring `frequency` or a `charges` schedule). When set to a future date, the contract stays active until this date even after its final scheduled payment is collected, so mid-term amendments can still be applied. Once the date has passed and no balance is outstanding, the contract completes normally.
    - `contract` (string): Contract ID for one-time payment on existing contract
    - `legal_entity` (string): Legal entity ID or code processing the payment
    - `event_date` (string (date-time)): Event date associated with the payment
    - `metadata` (object): Custom key-value pairs stored on the contract
    - `shipping` (object): Shipping address for the order
      - `country` (string): Country code
      - `line1` (string): Address line 1
      - `line2` (string): Address line 2
      - `line3` (string): Address line 3
      - `line4` (string): City / Town
      - `line5` (string): Postcode / ZIP
      - `line6` (string): State / Region
    - `line_items` (array of object): The order basket. Optional, but required by BNPL providers and by some acquirers to qualify for Level 2 / Level 3 interchange rates on commercial cards. Include every line that makes up the payment `amount`, including shipping and tax lines.
      - `name` (string): Display name of the item. Shown to the customer in wallet sheets and BNPL baskets, and used as the item description for Level 2/3 data. Some gateways truncate this aggressively (Authorize.Net to 31 characters, Fat Zebra to 40), so keep it short.
      - `sku` (string): Your product code / SKU for the item. **PayPal only:** a line item whose `sku` is `shipping`, `handling` or `insurance` (case-insensitive) is removed from the basket and its `total_amount` is reported in the corresponding PayPal order breakdown field instead of as a basket line.
      - `description` (string): Longer description of the item, where `name` is not enough. Only used by gateways that accept a separate description field; those gateways fall back to `name` when this is omitted.
      - `quantity` (number): Number of units of this item.
      - `unit_of_measure` (string): Unit that `quantity` is expressed in — for example `each`, `hours`, `metres`. Used in Level 3 interchange data, where the card networks require it. Alphanumeric, maximum 12 characters; a longer or malformed value is replaced with `each`, as is an absent one.
      - `unit_price` (number): Gross price of a single unit, in major currency units, including tax.
      - `total_amount` (number): Gross total for the line, in major currency units, including tax and after any discount. See the discount formula above.
      - `total_tax` (number): Tax included in `total_amount` for this line, in major currency units. Send `0` for a tax-free line rather than omitting the field — several gateways sum this across the basket to report an order-level tax total.
      - `total_discount` (number): Explicit discount applied to this line, in major currency units. Only used by gateways that accept a discount amount per line (CyberSource, Worldpay). Other gateways derive the discount from `(quantity x unit_price) - total_amount`. Express the discount this way rather than as a negative line item. A negative line is not forwarded as Level 2/3 data.
      - `tax_rate` (number): Tax rate applied to this line, passed through unchanged. Only used by gateways that accept an explicit rate (currently CyberSource, which expects a decimal fraction — `0.2` for 20%). Where it is omitted, gateways that need a rate derive one from `total_tax` and `total_amount`.
      - `discount_rate` (number): Discount rate applied to this line, passed through unchanged. Only used by gateways that accept an explicit rate (currently CyberSource).
      - `item_url` (string (uri)): HTTPS URL of the product page for this item. Displayed by BNPL providers (Klarna, Affirm) in the basket they present to the customer.
      - `image_url` (string (uri)): HTTPS URL of a product image for this item. Displayed by BNPL providers (Klarna, Affirm) in the basket they present to the customer.
    - `hotel_data` (object): Hotel-specific data passed through to the payment gateway
    - `title` (string): Label displayed in the header of the checkout dialogue
    - `checkout_text` (string): Additional text displayed below the amount to describe the payment
    - `default_currency` (string): Default currency when currency is selectable (omit `currency` to allow selection)
    - `default_amount` (string): Default amount when amount is enterable (omit `amount` to allow entry)
    - `default_save_card` (boolean): Default state of the "save card" checkbox
    - `save_card` (boolean): Force saving (true) or not saving (false) the card. Overrides user choice
    - `disable_confirm` (boolean): Remove the confirmation step during checkout
    - `disable_receipt` (boolean): Dismiss dialogue on successful payment instead of showing a receipt
    - `force_add` (boolean): Only allow new payment methods, do not show saved payment methods
    - `force_payment_method` (boolean): Force creation of a new payment method even if a matching one exists
    - `hide_save_card_toggle` (boolean): Hide the "save card" checkbox from the user
    - `locale` (string): 2-letter language code or full locale (e.g., `en` or `en_US`). Defaults to browser locale
    - `timezone` (string): IANA timezone name to use for date/time display (e.g., `America/New_York`)
    - `logo_url` (string): HTTPS URL of a custom logo. Set to `false` to disable the logo
    - `logo_offset` (boolean): Display the logo larger, vertically centered around the top of the popup
    - `payment_method_type` (array of string): Restrict available payment types (e.g., `["CARDS"]` or `["ACH", "SEPA"]`)
    - `style` (string): `DEFAULT` presents a modal popup, `INLINE` renders within a specified div One of: `DEFAULT`, `INLINE`.
    - `success_url` (string (uri)): URL to redirect the user to after successful payment. Query parameters will be appended with payment details
    - `cancel_url` (string (uri)): URL to redirect the user to if payment is abandoned
    - `contracts` (array of string): Ids of the contracts the payment method captured by this checkout is attached to once it is active.

## Responses

### 200: Checkout session created

```json
{
  "nonce": "string",
  "checkout": {
    "id": "string",
    "nonce": "string",
    "options": {},
    "status": "BUILDING"
  }
}
```

### 400: Bad request - invalid parameters

```json
{
  "code": "string",
  "message": "string"
}
```

### 401: Unauthorised: the API key is missing or not valid

```json
{
  "code": "UNAUTHORIZED",
  "message": "Unauthorised"
}
```

## Example request

```sh
curl --request POST \
  --url https://app.shuttleglobal.com/c/api/instances/YOUR_INSTANCE_KEY/checkouts \
  --header 'Authorization: Basic <base64 of SECRET_KEY:>' \
  --header 'Content-Type: application/json' \
  --data '{
  "checkout": {
    "options": {
      "currency": "EUR",
      "amount": "100.00",
      "alt_key": "order_123",
      "description": "Invoice 1234",
      "action": "PAYMENT",
      "source": "ECOMMERCE",
      "frequency": "ONEOFF",
      "charges": [
        {
          "alt_key": "INSTALMENT_1",
          "amount": "100.00",
          "due": "now"
        },
        {
          "alt_key": "INSTALMENT_2",
          "amount": "50.00",
          "due": "2026-06-01T09:00:00Z"
        },
        {
          "alt_key": "INSTALMENT_3",
          "amount": "50.00",
          "due": "2026-07-01T09:00:00Z"
        }
      ],
      "line_items": [
        {
          "sku": "SHOE-10-BLK",
          "name": "Running shoes",
          "quantity": 2,
          "unit_price": 20,
          "total_amount": 40,
          "total_tax": 4
        },
        {
          "sku": "SHIPPING",
          "name": "Standard delivery",
          "quantity": 1,
          "unit_price": 4.99,
          "total_amount": 4.99,
          "total_tax": 0
        }
      ],
      "title": "Complete your purchase",
      "disable_receipt": false,
      "style": "DEFAULT"
    }
  }
}'
```

Reference page: https://docs.shuttleglobal.com/platforms/reference/operations/createcheckout/