> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/checkout/api-guide

# Checkout API Guide

<a id="creating-a-checkout-session"></a>

## Creating a Checkout Session

A [`Checkout`](/api-reference/checkout/objects/checkout.md) object can be created for logged-in users and for anonymous (guest) users.

To create a [`Checkout`](/api-reference/checkout/objects/checkout.md) object, use the [`checkoutCreate`](/api-reference/checkout/mutations/checkout-create.md) mutation.

-   If the call is made by an [authenticated user](/api-usage/authentication.md), the created checkout will be assigned to that user.
    
-   If the call is not made by an authenticated user, the created checkout will not have a user assigned. A user email is not required at this stage, but it must be provided before adding a promo code, creating a payment, or completing the checkout.
    

[`Checkout.channel.countries`](/api-reference/channels/objects/channel.md#countries) provides a list of countries to which shipping is available, derived from all shipping methods assigned to the checkout's channel. This can be useful for rendering a country picker in the checkout view.

**Mutation**

```graphql
mutation CheckoutCreate($input: CheckoutCreateInput!) {
  checkoutCreate(input: $input) {
    checkout {
      id
      totalPrice {
        gross {
          amount
          currency
        }
      }
      isShippingRequired
      shippingMethods {
        id
        name
        active
        message
      }
      availableCollectionPoints {
        id
        name
        clickAndCollectOption
      }
      availablePaymentGateways {
        id
        name
        config {
          field
          value
        }
      }
    }
    errors {
      field
      code
    }
  }
}
```

**Variables**

```json
{
  "input": {
    "channel": "default-channel",
    "email": "customer@example.com",
    "lines": [
      {
        "quantity": 1,
        "variantId": "UHJvZHVjdFZhcmlhbnQ6Mjk3"
      }
    ],
    "shippingAddress": {
      "firstName": "John",
      "lastName": "Doe",
      "streetAddress1": "1470  Pinewood Avenue",
      "city": "Michigan",
      "postalCode": "49855",
      "country": "US",
      "countryArea": "MI"
    },
    "billingAddress": {
      "firstName": "John",
      "lastName": "Doe",
      "streetAddress1": "1470  Pinewood Avenue",
      "city": "Michigan",
      "postalCode": "49855",
      "country": "US",
      "countryArea": "MI"
    }
  }
}
```

**Result**

```json
{
  "data": {
    "checkoutCreate": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZmE5ZjBkMjYtMWM3NC00MDgyLTk3MzktYTIxOGE2NzVjMDZk",
        "totalPrice": {
          "gross": {
            "amount": 20,
            "currency": "USD"
          }
        },
        "isShippingRequired": true,
        "shippingMethods": [
          {
            "id": "U2hpcHBpbmdNZXRob2Q6MTM=",
            "name": "UPS",
            "active": true,
            "message": ""
          },
          {
            "id": "U2hpcHBpbmdNZXRob2Q6MTI=",
            "name": "DHL",
            "active": false,
            "message": "Not available."
          }
        ],
        "availableCollectionPoints": [
          {
            "id": "V2FyZWhvdXNlOjU0NjliNWQ3LThmOGUtNGVmOS1iMGQxLWNhYWZmYTg4MjI1OQ==",
            "name": "Local Store"
            "clickAndCollectOption": "LOCAL"
          },
          {
            "id": "=V2FyZWhvdXNlOjU0NjliNWQ3LThmOGUtNGVmOS1iMGQxLWNhYWZmYTg4MjI1OA==",
            "name": "Company HQ"
            "clickAndCollectOption": "ALL"
          }
        ],
        "availablePaymentGateways": [
          {
            "id": "app.saleor.adyen",
            "name": "Adyen",
            "config": []
          }
        ]
      },
      "errors": []
    }
  }
}
```

<a id="set-email"></a>

## Set Email

When an anonymous checkout has been created without an email, the email must be set using [`CheckoutEmailUpdate`](/api-reference/checkout/mutations/checkout-email-update.md) before creating payment and completing the checkout.

**Mutation**

```graphql
mutation CheckoutEmailUpdate($id: ID, $email: String!) {
  checkoutEmailUpdate(id: $id, email: $email) {
    checkout {
      id
      email
    }
    errors {
      field
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZmE5ZjBkMjYtMWM3NC00MDgyLTk3MzktYTIxOGE2NzVjMDZk",
  "email": "test_customer@example.com"
}
```

**Result**

```json
{
  "data": {
    "checkoutEmailUpdate": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZmE5ZjBkMjYtMWM3NC00MDgyLTk3MzktYTIxOGE2NzVjMDZk",
        "email": "test_customer@example.com"
      },
      "errors": []
    }
  }
}
```

<a id="managing-lines"></a>

## Managing Lines

To add an item to the cart, use [`checkoutLinesAdd`](/api-reference/checkout/mutations/checkout-lines-add.md). The total price will be updated automatically.

See also [`checkoutLinesDelete`](/api-reference/checkout/mutations/checkout-lines-delete.md) and [`checkoutLinesUpdate`](/api-reference/checkout/mutations/checkout-lines-update.md).

If the quantity is changed to **`0`**, it will be removed from the checkout.

**Mutation**

```graphql
mutation CheckoutLinesAdd($id: ID, $lines: [CheckoutLineInput!]!) {
  checkoutLinesAdd(id: $id, lines: $lines) {
    checkout {
      lines {
        id
        variant {
          name
        }
        quantity
      }
      totalPrice {
        gross {
          currency
          amount
        }
      }
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZmE5ZjBkMjYtMWM3NC00MDgyLTk3MzktYTIxOGE2NzVjMDZk",
  "lines": [
    {
      "quantity": 1,
      "variantId": "UHJvZHVjdFZhcmlhbnQ6Mjc0"
    }
  ]
}
```

**Response**

```json
{
  "data": {
    "checkoutLinesAdd": {
      "checkout": {
        "lines": [
          {
            "id": "Q2hlY2tvdXRMaW5lOjI1Mw=="
            "variant": {
              "name": "XL"
            },
            "quantity": 1
          }
        ],
        "totalPrice": {
          "gross": {
            "currency": "USD",
            "amount": 5
          }
        }
      }
    }
  }
}
```

<a id="creating-two-lines-using-a-single-variant"></a>

### Creating Two Lines Using a Single Variant

By default, if a single variant is added multiple times, the quantity of the variant is increased without adding a new line. To add the same variant as a separate line, use the `forceNewLine` flag.

When `forceNewLine` is not used and the variant exists in multiple lines, **Saleor will create a new line with the provided quantity**.

**Mutation**

```graphql
mutation CheckoutLinesAdd($id: ID, $lines: [CheckoutLineInput!]!) {
  checkoutLinesAdd(id: $id, lines: $lines) {
    checkout {
      lines {
        id
        variant {
          name
        }
        quantity
      }
      totalPrice {
        gross {
          currency
          amount
        }
      }
    }
  }
}
```

**Variables**

```json
{
 "id": "Q2hlY2tvdXQ6ZmE5ZjBkMjYtMWM3NC00MDgyLTk3MzktYTIxOGE2NzVjMDZk",
 "lines": [
   {
     "quantity": 1,
     "variantId": "UHJvZHVjdFZhcmlhbnQ6Mjc0",
     "forceNewLine": true
   },
   {
     "quantity": 2,
     "variantId": "UHJvZHVjdFZhcmlhbnQ6Mjc0"
   }
 ]
}
```

**Response**

```json
{
 "data": {
   "checkoutLinesAdd": {
     "checkout": {
       "lines": [
         {
           "id": "Q2hlY2tvdXRMaW5lOjI1Mw==",
           "variant": {
             "name": "XL"
           },
           "quantity": 1
         },
         {
           "id": "Q2hlY2tvdXRMaW5lOjI1Mw==",
           "variant": {
             "name": "XL"
           },
           "quantity": 2
         }
       ],
       "totalPrice": {
         "gross": {
           "currency": "USD",
           "amount": 15
         }
       }
     }
   }
 }
}
```

<a id="setting-custom-line-prices"></a>

### Setting Custom Line Prices

This feature is **only available for apps** with `HANDLE_CHECKOUTS` permission.

The variant price of any item in the checkout can be overridden. The provided price will be treated as the base price of the variant. Applying a voucher or sale in the checkout will be applied on top of the overridden price.

The custom price can be set with the `price` field in the [`CheckoutLineInput`](/api-reference/checkout/inputs/checkout-line-input.md) in the following mutations:

-   [`checkoutCreate`](/api-reference/checkout/mutations/checkout-create.md),
-   [`checkoutLinesAdd`](/api-reference/checkout/mutations/checkout-lines-add.md) – when adding a variant that already exists in the checkout, the corresponding line gets overridden – the quantity is incremented and the price is updated.
-   [`checkoutLinesUpdate`](/api-reference/checkout/mutations/checkout-lines-update.md) – overrides the existing line with the price provided in the mutation.

**GraphQL**

```graphql
mutation CheckoutLinesAdd($id: ID, $lines: [CheckoutLineInput!]!) {
  checkoutLinesAdd(id: $id, lines: $lines) {
    checkout {
      id
      lines {
        variant {
          id
        }
        quantity
        totalPrice {
          gross {
            amount
            currency
          }
          net {
            amount
            currency
          }
        }
      }
    }
    errors {
      field
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
  "lines": [
    {
      "quantity": 1,
      "variantId": "UHJvZHVjdFZhcmlhbnQ6MzA2",
      "price": 16.22
    }
  ]
}
```

**Response**

```json
{
  "data": {
    "checkoutLinesAdd": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
        "lines": [
          {
            "variant": {
              "id": "UHJvZHVjdFZhcmlhbnQ6MzA2"
            },
            "quantity": 2,
            "totalPrice": {
              "gross": {
                "amount": 32.44,
                "currency": "USD"
              },
              "net": {
                "amount": 32.44,
                "currency": "USD"
              }
            }
          }
        ]
      },
      "errors": []
    }
  }
}
```

<a id="explaining-the-override-with-a-reason"></a>

#### Explaining the Override with a Reason

**Added in Saleor 3.23.**

An app can attach an optional `priceOverrideReason` to a custom price to record **why** the variant price was overridden (for debugging and auditing). Like `price`, the field is **only available for apps** with `HANDLE_CHECKOUTS` permission and is accepted on [`CheckoutLineInput`](/api-reference/checkout/inputs/checkout-line-input.md) and [`CheckoutLineUpdateInput`](/api-reference/checkout/inputs/checkout-line-update-input.md) in `checkoutCreate`, `checkoutLinesAdd`, and `checkoutLinesUpdate`.

The reason must be backed by a price override. It can be set only together with a `price`, or on a line that already has an override (a reason-only update in `checkoutLinesUpdate`). Providing a reason without a current or incoming override fails with the [`CheckoutErrorCode.PRICE_OVERRIDE_REASON_WITHOUT_OVERRIDE`](/api-reference/checkout/enums/checkout-error-code.md) error.

The reason is tied to the price-setting operation:

-   Setting a new `price` **without** a reason clears any previously stored reason.
-   Clearing the `price` clears the reason as well.
-   Blank or whitespace-only values are stored as no reason (`null`).

The stored reason is exposed on the [`CheckoutLine.priceOverrideReason`](/api-reference/checkout/objects/checkout-line.md) field (readable with `MANAGE_CHECKOUTS` or `HANDLE_CHECKOUTS`). When the checkout is completed, the reason is copied onto the resulting [`OrderLine.priceOverrideReason`](/api-reference/orders/objects/order-line.md) field (readable with `MANAGE_ORDERS`).

**GraphQL**

```graphql
mutation CheckoutLinesAdd($id: ID, $lines: [CheckoutLineInput!]!) {
  checkoutLinesAdd(id: $id, lines: $lines) {
    checkout {
      id
      lines {
        variant {
          id
        }
        quantity
        priceOverrideReason
      }
    }
    errors {
      field
      code
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
  "lines": [
    {
      "quantity": 1,
      "variantId": "UHJvZHVjdFZhcmlhbnQ6MzA2",
      "price": 16.22,
      "priceOverrideReason": "Loyalty program price match"
    }
  ]
}
```

**Response**

```json
{
  "data": {
    "checkoutLinesAdd": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
        "lines": [
          {
            "variant": {
              "id": "UHJvZHVjdFZhcmlhbnQ6MzA2"
            },
            "quantity": 1,
            "priceOverrideReason": "Loyalty program price match"
          }
        ]
      },
      "errors": []
    }
  }
}
```

<a id="update-shipping-and-billing-address"></a>

## Update Shipping and Billing Address

Use [`checkoutShippingAddressUpdate`](/api-reference/checkout/mutations/checkout-shipping-address-update.md) and [`checkoutBillingAddressUpdate`](/api-reference/checkout/mutations/checkout-billing-address-update.md) mutations to set the destination address.

Keep in mind that address affects the availability of the products.

Read more about [shipping and billing](/developer/checkout/address.md) in checkout.

**Mutation**

```graphql
mutation checkoutShippingAddressUpdate($checkoutId: ID!, $shippingAddress: AddressInput!) {
  checkoutShippingAddressUpdate(
    id: $checkoutId
    shippingAddress: $shippingAddress
  ) {
    checkout {
      id
      shippingAddress {
        ...AddressFragment
      }
      billingAddress {
        ...AddressFragment
      }
    }
  }
}

fragment AddressFragment on Address {
  id
  city
  phone
  postalCode
  companyName
  cityArea
  streetAddress1
  streetAddress2
  countryArea
  country {
    country
    code
  }
  firstName
  lastName
}
```

**Variables**

```json
{
  "checkoutId": "Q2hlY2tvdXQ6MDk1MmNiNWUtMzZkYi00YTQ5LThhN2MtZjAyNGE2M2Y1NzNj",
  "shippingAddress": {
    "city": "New York",
    "cityArea": "",
    "companyName": "",
    "country": "US",
    "countryArea": "NY",
    "firstName": "First Name",
    "lastName": "Last Name",
    "phone": "",
    "postalCode": "10019",
    "streetAddress1": "11 W 53rd St, New York, NY",
    "streetAddress2": ""
  }
}
```

**Response**

```json
{
  "data": {
    "checkoutShippingAddressUpdate": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6MDk1MmNiNWUtMzZkYi00YTQ5LThhN2MtZjAyNGE2M2Y1NzNj",
        "shippingAddress": {
          "id": "QWRkcmVzczoxMjc=",
          "city": "NEW YORK",
          "phone": "",
          "postalCode": "10019",
          "companyName": "",
          "cityArea": "",
          "streetAddress1": "11 W 53rd St, New York, NY",
          "streetAddress2": "",
          "countryArea": "NY",
          "country": {
            "country": "United States of America",
            "code": "US",
            "__typename": "CountryDisplay"
          },
          "firstName": "First Name",
          "lastName": "Last Name",
          "__typename": "Address"
        },
        "billingAddress": {
          "id": "QWRkcmVzczoxMjg=",
          "city": "NEW YORK",
          "phone": "",
          "postalCode": "10019",
          "companyName": "",
          "cityArea": "",
          "streetAddress1": "11 W 53rd St, New York, NY",
          "streetAddress2": "",
          "countryArea": "NY",
          "country": {
            "country": "United States of America",
            "code": "US",
            "__typename": "CountryDisplay"
          },
          "firstName": "First Name",
          "lastName": "Last Name",
          "__typename": "Address"
        }
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 2,
      "maximumAvailable": 50000
    }
  }
}
```

<a id="update-delivery-method"></a>

## Update Delivery Method

Checkout supports two types of delivery: shipping methods and click & collect points. Use `checkout.delivery` to read the currently assigned delivery method.

<a id="shipping-methods"></a>

### Shipping Methods

Call [`deliveryOptionsCalculate`](/api-reference/shipping/mutations/delivery-options-calculate.md) to get an up-to-date list of available shipping methods. This explicitly triggers the `SHIPPING_LIST_METHODS_FOR_CHECKOUT` and `CHECKOUT_FILTER_SHIPPING_METHODS` webhooks. Use the `id` from each `deliveries` entry as `deliveryMethodId` in the next step.

Learn more about [delivery methods](/developer/checkout/address.md#selecting-the-delivery-method), [delivery method problems](/developer/checkout/problems.md#checkoutproblemdeliverymethodstale), and [how Saleor returns shipping methods](/developer/shipping/shipping-methods-in-orders.md#how-saleor-selects-shipping-methods).

**Mutation**

```graphql
mutation DeliveryOptionsCalculate($id: ID!) {
  deliveryOptionsCalculate(id: $id) {
    deliveries {
      id
      shippingMethod {
        name
        active
        price {
          amount
        }
      }
    }
    errors {
      field
      message
      code
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw"
}
```

**Result**

```json
{
  "data": {
    "deliveryOptionsCalculate": {
      "deliveries": [
        {
          "id": "Q2hlY2tvdXREZWxpdmVyeTozODgwOGU5ZC0wMDVlLTQ1YjQtOTU1MC1mZjAyM2YzZGZlMDM=",
          "shippingMethod": {
            "name": "Registered priority",
            "active": true,
            "price": {
              "amount": 42.89
            }
          }
        },
        {
          "id": "Q2hlY2tvdXREZWxpdmVyeToxMzc0NTU3Mi0xMGMxLTRiNmItYTY5MC04Y2ZjZTNhYzk0NTQ=",
          "shippingMethod": {
            "name": "[EXTERNAL] Provider - Economy",
            "active": true,
            "price": {
              "amount": 10
            }
          }
        }
      ],
      "errors": []
    }
  }
}
```

<a id="click--collect-points"></a>

### Click & Collect Points

For click & collect, query `checkout.availableCollectionPoints` to list available warehouses. Use the warehouse `id` as `deliveryMethodId` in the next step.

**Query**

```graphql
query Checkout($id: ID!) {
  checkout(id: $id) {
    availableCollectionPoints {
      id
      name
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw"
}
```

**Result**

```json
{
  "data": {
    "checkout": {
      "availableCollectionPoints": [
        {
          "id": "V2FyZWhvdXNlOjE1Zjk1Y2JhLTA1YjktNDM4Yi04MTM2LTkwZGQ2MWUzZjk1MA==",
          "name": "Europe"
        },
        {
          "id": "V2FyZWhvdXNlOjVlNGMwZjM3LWRmMzktNDJhMC05YTc4LTRmYTJiODBlM2ZkZA==",
          "name": "Asia"
        }
      ]
    }
  }
}
```

<a id="assign-delivery-method"></a>

### Assign Delivery Method

Below example shows the mutation call to assign the delivery method:

**Mutation**

```graphql
mutation CheckoutDeliveryMethodUpdate($id: ID, $deliveryMethodId: ID) {
  checkoutDeliveryMethodUpdate(
    id: $id, deliveryMethodId: $deliveryMethodId)
  {
    errors {
      message
      field
    }
    checkout {
      delivery {
        id
        shippingMethod {
          id
          name
        }
      }
    }
    __typename
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
  "deliveryMethodId": "U2hpcHBpbmdNZXRob2Q6MTU="
}
```

**Response**

```json
{
  "data": {
    "checkoutDeliveryMethodUpdate": {
      "errors": [],
      "checkout": {
        "delivery": {
          "id": "RGVsaXZlcnk6ZmVkZXg=",
          "shippingMethod": {
            "id": "U2hpcHBpbmdNZXRob2Q6MTU=",
            "name": "FedEx"
          }
        }
      },
      "__typename": "CheckoutDeliveryMethodUpdate"
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 0,
      "maximumAvailable": 50000
    }
  }
}
```

<a id="apply-a-promo-code"></a>

## Apply a Promo Code

Use [`checkoutAddPromoCode`](/api-reference/checkout/mutations/checkout-add-promo-code.md) to add a voucher code or gift card to a checkout.

For more details, see the [vouchers](/developer/discounts/vouchers.md) and [gift cards](/developer/gift-cards.md) guides.

**Mutation**

```graphql
mutation CheckoutAddPromoCode($id: ID, $promoCode: String!) {
  checkoutAddPromoCode(id: $id, promoCode: $promoCode) {
    checkout {
      id
      discount {
        amount
        currency
      }
      totalPrice {
        gross {
          amount
          currency
        }
      }
      voucherCode
      giftCards{
        last4CodeChars
      }
    }
    errors {
      field
      code
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm",
  "promoCode": "WELCOME10"
}
```

**Response**

```json
{
  "data": {
    "checkoutAddPromoCode": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm",
        "discount": {
          "amount": 40,
          "currency": "USD"
        },
        "totalPrice": {
          "gross": {
            "amount": 40,
            "currency": "USD"
          }
        },
        "voucherCode": "WELCOME10",
        "giftCards": []
      },
      "errors": []
    }
  }
}
```

<a id="attach-customer-to-checkout"></a>

## Attach Customer to Checkout

Use [`checkoutCustomerAttach`](/api-reference/checkout/mutations/checkout-customer-attach.md) to assign a user to an anonymous checkout.

-   When called by a logged-in customer, provide the `checkoutId`.
-   When called by an App, provide `checkoutId` and `customerId`, require the `IMPERSONATE_USER` permission.

**Mutation**

```graphql
mutation CheckoutCustomerAttach($id: ID, $customerId: ID) {
  checkoutCustomerAttach(id: $id, customerId: $customerId) {
    checkout {
      id
      email
      user {
        id
        email
      }
    }
    errors {
      field
      code
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm",
  "customerId": "VXNlcjoxNA=="
}
```

**Response**

```json
{
  "data": {
    "checkoutCustomerAttach": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm",
        "email": "gary.fisher@example.com",
        "user": {
          "id": "VXNlcjoxNA==",
          "email": "gary.fisher@example.com"
        }
      },
      "errors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 1,
      "maximumAvailable": 50000
    }
  }
}
```

<a id="detach-customer-from-checkout"></a>

## Detach Customer from Checkout

Use [`checkoutCustomerDetach`](/api-reference/checkout/mutations/checkout-customer-detach.md) to remove the assigned user from a checkout.

**Mutation**

```graphql
mutation CheckoutCustomerDetach($id: ID) {
  checkoutCustomerDetach(id: $id) {
    checkout {
      id
      email
      user {
        id
      }
    }
    errors {
      field
      code
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm"
}
```

**Response**

```json
{
  "data": {
    "checkoutCustomerDetach": {
      "checkout": {
        "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm",
        "email": "gary.fisher@example.com",
        "user": null
      },
      "errors": []
    }
  }
}
```

<a id="completing-checkout"></a>

## Completing checkout

Checkout can be completed if all [requirements are satisfied](/developer/checkout/lifecycle.md#completing-checkout).

When the checkout is fully paid, the [`CHECKOUT_FULLY_PAID`](/api-reference/webhooks/enums/webhook-event-type-async-enum.md#checkout-fully-paid) webhook will be triggered.

**Mutation**

```graphql
mutation CheckoutComplete($id: ID) {
  checkoutComplete(id: $id) {
    order {
      id
      status
    }
    errors {
      field
      message
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6ZDYyNzk4OTgtNmE2My00NTk3LWFhYTktMTVhOWEwN2I1MzFm"
}
```

**Result**

```json
{
  "data": {
    "checkoutComplete": {
      "order": {
        "id": "T3JkZXI6MjU=",
        "status": "UNFULFILLED"
      },
      "errors": []
    }
  }
}
```
