# Checkout Actions API

Checkout actions allow you to programmatically control the checkout flow.

## Navigation Actions

### actions.checkout.openCheckout()

```typescript
openCheckout(): void
```

Opens the checkout drawer or navigates to checkout page.

```javascript
window.LiquidCommerce.elements.actions.checkout.openCheckout();
```

### actions.checkout.closeCheckout()

```typescript
closeCheckout(): void
```

Closes the checkout drawer.

```javascript
window.LiquidCommerce.elements.actions.checkout.closeCheckout();
```

### actions.checkout.toggleCheckout()

```typescript
toggleCheckout(): void
```

Toggles checkout open/closed.

```javascript
window.LiquidCommerce.elements.actions.checkout.toggleCheckout();
```

### actions.checkout.exitCheckout()

```typescript
exitCheckout(): void
```

Navigates away from checkout (requires `exitUrl` configuration).

```javascript
window.LiquidCommerce.elements.actions.checkout.exitCheckout();
```

## Product Actions

### actions.checkout.addProduct()

```typescript
addProduct(params: IAddProductParams[], openCheckout?: boolean): Promise<void>
```

Add products and open checkout in one call. Products are added to the cart (via the cart action, or directly when none is wired up), then checkout is prepared and opened. For a checkout without a cart session, use `addAnonymousProduct`.

`IAddProductParams.engravingLines?: string[]` — optional engraving. Same rules as [`actions.cart.addProduct()`](./cart-actions.md#actionscartaddproduct): invalid input is ignored, blanks stripped, lines clamped to the product's `maxLines` / `maxCharsPerLine`, and engraving is dropped (without failing) when the product, variant, or fulfillment doesn't support it.

```javascript
await window.LiquidCommerce.elements.actions.checkout.addProduct([
  {
    identifier: '00619947000020',
    fulfillmentType: 'shipping',
    quantity: 1
  }
], true);  // Open checkout after adding

// With engraving
await window.LiquidCommerce.elements.actions.checkout.addProduct([
  {
    identifier: '00619947000020',
    fulfillmentType: 'shipping',
    quantity: 1,
    engravingLines: ['For Dad']
  }
], true);
```

### actions.checkout.addAnonymousProduct()

```typescript
addAnonymousProduct(
  params: IAnonymousCheckoutAddProductParams
): Promise<IAnonymousCheckoutAddProductResponse>
```

Add a product to checkout without requiring a cart session. Used for direct-to-checkout flows.

**Parameters** (`IAnonymousCheckoutAddProductParams`):

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `location` | `ILocation` | Yes | `{ address: IAddressAddress; coordinates: IAddressCoordinates }` |
| `items` | `IAnonymousCheckoutAddProductItem[]` | No | Products to add: `{ identifier, fulfillmentType, quantity }`. Provide `items` **or** `cartItems`. |
| `cartItems` | `ICartUpdateItem[]` | No | Pre-resolved cart line items: `{ id?, partNumber, quantity, fulfillmentId, engravingLines? }` (alternative to `items`). |
| `promoCode` | `string` | No | Promo code applied while creating the anonymous checkout. |

```javascript
const result = await window.LiquidCommerce.elements.actions.checkout
  .addAnonymousProduct({
    items: [
      { identifier: '00619947000020', fulfillmentType: 'shipping', quantity: 1 }
    ],
    location: {
      address: { one: '123 Main St', two: '', city: 'New York', state: 'NY', zip: '10001', country: 'US' },
      coordinates: { latitude: 40.7128, longitude: -74.006 }
    },
    promoCode: 'WELCOME10'  // optional
  });
```

**Returns** (`IAnonymousCheckoutAddProductResponse`):

```typescript
interface IAnonymousCheckoutAddProductResponse {
  checkout: ICheckoutPrepare | null;        // the prepared checkout (see below), or null on failure
  unavailableItems: IAnonymousCheckoutUnavailableItem[];
}

interface IAnonymousCheckoutUnavailableItem {
  identifier: string;
  productName: string | null;
  fulfillmentType: FulfillmentType;         // 'shipping' | 'onDemand'
  reason: 'product_not_available' | 'fulfillment_not_available';
}

interface ICheckoutPrepare {
  token: string;
  cartId: string;
  customer: ICheckoutCustomer;
  isGift: boolean;
  billingSameAsShipping: boolean;
  payment?: string;
  giftOptions: ICheckoutGiftRecipient;
  marketingPreferences: ICheckoutMarketingPreferences;
  shippingAddress: ICheckoutShippingAddress;
  billingAddress: ICheckoutBilling;
  promoCode: ICheckoutPromoCode | null;
  amounts: ICheckoutAmounts;
  giftCards: ICheckoutGiftCard[];
  presale: ICheckoutPresale | null;
  itemsQuantity: number;
  items: Record<string /* cart item ID */, ICheckoutItem>;
  retailers: Record<string /* retailer ID */, ICheckoutRetailer>;
  events: ICheckoutEvent[];
}
```

## Promo & Gift Card Actions

### actions.checkout.applyPromoCode()

```typescript
applyPromoCode(promoCode: string): Promise<void>
```

Apply a promo code during checkout.

```javascript
await window.LiquidCommerce.elements.actions.checkout.applyPromoCode('WELCOME10');
```

### actions.checkout.removePromoCode()

```typescript
removePromoCode(): Promise<void>
```

Remove the active promo code.

```javascript
await window.LiquidCommerce.elements.actions.checkout.removePromoCode();
```

### actions.checkout.applyGiftCard()

```typescript
applyGiftCard(code: string): Promise<void>
```

Apply a gift card.

```javascript
await window.LiquidCommerce.elements.actions.checkout.applyGiftCard('GIFT-1234-5678-9012');
```

### actions.checkout.removeGiftCard()

```typescript
removeGiftCard(code: string): Promise<void>
```

Remove a gift card.

```javascript
await window.LiquidCommerce.elements.actions.checkout.removeGiftCard('GIFT-1234-5678-9012');
```

## Toggle Actions

### actions.checkout.toggleIsGift()

```typescript
toggleIsGift(active?: boolean): Promise<void>
```

Enable/disable gift mode.

```javascript
// Enable
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(true);

// Disable
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(false);

// Toggle
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift();
```

### actions.checkout.toggleBillingSameAsShipping()

```typescript
toggleBillingSameAsShipping(active?: boolean): Promise<void>
```

Set whether billing address matches shipping.

```javascript
// Use shipping address for billing
await window.LiquidCommerce.elements.actions.checkout.toggleBillingSameAsShipping(true);

// Use different billing address
await window.LiquidCommerce.elements.actions.checkout.toggleBillingSameAsShipping(false);
```

### actions.checkout.toggleMarketingPreferences()

```typescript
toggleMarketingPreferences(field: 'canEmail' | 'canSms', active: boolean): Promise<void>
```

Set marketing opt-in preferences.

```javascript
// Opt into email marketing
await window.LiquidCommerce.elements.actions.checkout.toggleMarketingPreferences('canEmail', true);

// Opt into SMS marketing
await window.LiquidCommerce.elements.actions.checkout.toggleMarketingPreferences('canSms', true);
```

## Form Update Actions

### actions.checkout.updateCustomerInfo()

```typescript
updateCustomerInfo(params: Record<CustomerFieldName, string>): void
```

Pre-fill customer information.

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`
- `birthDate`, `addressTwo`
- `company`

```javascript
window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  birthDate: '1990-01-01',
  addressTwo: 'Apt 4B',
  company: 'Acme Corp'
});
```

### actions.checkout.updateBillingInfo()

```typescript
updateBillingInfo(params: Record<BillingFieldName, string>): void
```

Pre-fill billing address.

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`, `company`
- `addressOne`, `addressTwo`
- `city`, `state`, `zipCode`

```javascript
window.LiquidCommerce.elements.actions.checkout.updateBillingInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  company: 'Acme Corp',
  addressOne: '123 Main St',
  addressTwo: 'Apt 4B',
  city: 'New York',
  state: 'NY',
  zipCode: '10001'
});
```

### actions.checkout.updateGiftInfo()

```typescript
updateGiftInfo(params: Record<GiftFieldName, string>): void
```

Pre-fill gift recipient information.

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`
- `message`, `addressTwo`

```javascript
window.LiquidCommerce.elements.actions.checkout.updateGiftInfo({
  firstName: 'Jane',
  lastName: 'Smith',
  email: 'jane@example.com',
  phone: '+15559876543',
  addressTwo: 'Suite 200',
  message: 'Happy Birthday!',
});
```

## Payment Method

### actions.checkout.setSavedPaymentMethod()

```typescript
setSavedPaymentMethod(params: {
  id: string;
  card: {
    brand: string;
    last4: string;
    expMonth?: string | number;
    expYear?: string | number;
  };
}): void
```

Pre-select a saved payment method for the checkout. When set, the payment step renders a read-only card summary (e.g. `Visa ending in 4242`) instead of the Stripe card form, and the shopper places the order without re-entering card details. The `id` is bound to the checkout when the payment form is saved.

`id` must be a payment method the backend already holds for the checkout's customer (for example, a card fetched server-side and handed to the page). If the backend does not recognize the `id` for this checkout's customer, saving the payment step fails with an error (`The selected payment method could not be applied to this checkout.`) and the order cannot be placed — pass only a payment method confirmed to belong to the customer. The `card` fields are used only to render the summary. It can be set at any time — before opening checkout, or while it is open — and the payment step updates accordingly. The selection persists across a cart reset within the session.

```javascript
window.LiquidCommerce.elements.actions.checkout.setSavedPaymentMethod({
  id: 'pm_123',
  card: { brand: 'Visa', last4: '4242', expMonth: '12', expYear: '30' }
});
```

### actions.checkout.clearSavedPaymentMethod()

```typescript
clearSavedPaymentMethod(): void
```

Remove a previously set saved payment method, restoring the Stripe card-entry form.

```javascript
window.LiquidCommerce.elements.actions.checkout.clearSavedPaymentMethod();
```

## Data Retrieval

### actions.checkout.getDetails()

```typescript
getDetails(): ICheckoutDetailsEventData
```

Retrieve current checkout information.

```javascript
const checkout = window.LiquidCommerce.elements.actions.checkout.getDetails();

console.log(`Cart ID: ${checkout.cartId}`);
console.log(`Total: $${checkout.amounts.total / 100}`);
console.log(`Items: ${checkout.itemCount}`);
console.log(`Is Gift: ${checkout.isGift}`);
```

**Returns:**

```typescript
interface ICheckoutDetailsEventData {
  token: string;
  cartId: string;
  isGift: boolean;
  billingSameAsShipping: boolean;
  marketingPreferences: {
    canEmail: boolean;
    canSms: boolean;
  };
  hasPromoCode: boolean;
  hasGiftCards: boolean;
  amounts: ICheckoutAmounts;
  itemCount: number;
  items: Record<string, ICheckoutItem>;
}
```

### actions.checkout.getProductAvailabilityByState()

```typescript
getProductAvailabilityByState(
  identifiers: string[],
  state?: string
): Promise<IProductAvailabilityResponse>
```

Check product availability across states from the checkout context.

```javascript
const availability = await window.LiquidCommerce.elements.actions.checkout
  .getProductAvailabilityByState(['00619947000020'], 'CA');
```

| Parameter     | Type     | Required | Description                          |
|---------------|----------|----------|--------------------------------------|
| `identifiers` | string[] | Yes      | Array of product UPCs, SKUs, or IDs  |
| `state`       | string   | No       | Two-letter state code (e.g., `'NY'`) |

## Use Cases

### Pre-fill for Logged-In Users

```javascript
window.addEventListener('lce:actions.checkout_opened', () => {
  if (userIsLoggedIn) {
    window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
      firstName: currentUser.firstName,
      lastName: currentUser.lastName,
      email: currentUser.email,
      phone: currentUser.phone
    });
  }
});
```

### Track Checkout Progress

```javascript
window.addEventListener('lce:actions.checkout_customer_information_updated', () => {
  gtag('event', 'checkout_progress', { step: 'customer_info' });
});

window.addEventListener('lce:actions.checkout_submit_started', () => {
  gtag('event', 'checkout_progress', { step: 'payment' });
});

window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
  const { orderNumber, orderTotal } = event.detail.data;
  
  gtag('event', 'purchase', {
    transaction_id: orderNumber,
    value: orderTotal / 100,
    currency: 'USD'
  });
});
```

### Gift Flow

```javascript
document.getElementById('gift-checkbox').addEventListener('change', async (e) => {
  await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(e.target.checked);
  
  if (e.target.checked) {
    showGiftForm();
  } else {
    hideGiftForm();
  }
});
```

### Auto-Apply Campaign Codes

```javascript
const params = new URLSearchParams(window.location.search);
const campaignCode = params.get('promo');

if (campaignCode) {
  window.addEventListener('lce:actions.checkout_opened', async () => {
    try {
      await window.LiquidCommerce.elements.actions.checkout.applyPromoCode(campaignCode);
    } catch (error) {
      console.log('Invalid campaign code');
    }
  });
}
```

## Events

Checkout actions trigger numerous events. See [Checkout Events](../../guides/events.md#checkout-events) for complete list.

Key events:
- `checkout_opened`, `checkout_closed`
- `checkout_customer_information_updated`
- `checkout_submit_started`, `checkout_submit_completed`, `checkout_submit_failed`
- `checkout_promo_code_applied`, `checkout_promo_code_failed`
- `checkout_gift_card_applied`, `checkout_gift_card_failed`

## See Also

- [Checkout Component Guide](../../guides/checkout-component.md)
- [Checkout Events](../../guides/events.md#checkout-events)
- [Cart Actions](./cart-actions.md)
