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

# Local Pickup Options

> Offer in-store / curbside pickup at merchant-owned locations as a delivery option

# Local Pickup Options

`local_pickup_options` functions return a list of **merchant-owned pickup
locations** (store, warehouse, kiosk) that the customer can choose
instead of having the order shipped. Use it for:

* Buy-online-pickup-in-store (BOPIS).
* Curbside pickup at a specific retail address.
* "Pick up at our warehouse" for B2B customers.

For carrier-operated parcel lockers / partner pickup points (e.g.
DHL Packstation, UPS Access Point) use
[`pickup_point_options`](/functions/pickup-point-options) instead.

<Note>
  **Dispatch is live; the customer-facing UI is pending.** Installed
  `local_pickup_options` functions **fire on every cart verification**
  (consuming your daily execution quota), and their results are returned in
  the verifyCart response as `localPickupOptions[]`. What's still pending
  is the checkout UI consumer that lets the customer pick one of these
  options — until it ships, returned options are not yet shown to
  customers.
</Note>

## Manifest

```json theme={null}
{
  "type": "local_pickup_options",
  "handle": "store-pickup",
  "title": "In-store pickup",
  "entrypoint": "dist/local-pickup.wasm",
  "inputFields": {
    "shippingAddress": {
      "country": true,
      "city": true,
      "zip": true
    }
  }
}
```

`inputFields` is an **object of booleans** (or nested objects), never an
array — each leaf must be `true`/`false`. Requesting a field as an array of
names fails install validation with a 400. See [Input Fields](/functions/input-fields).

Per-shop cap: **5** active `local_pickup_options` apps.

WASM execution timeout: 1500ms (configurable via
`WASM_TIMEOUT_LOCAL_PICKUP_OPTIONS`).

## Input

```typescript theme={null}
interface LocalPickupOptionsFunctionInput {
  cart: {
    items: CartItem[];        // same line shape as other function types
    totalPrice: number;       // Subtotal in display currency
    itemCount: number;        // Sum of quantities
    currency: string;         // e.g. "INR", "USD"
    localization?: { country: string; language: string };
    metafields?: MetafieldBag;
  };
  shippingAddress: {
    firstName?: string;
    lastName?: string;
    address1?: string;
    address2?: string;
    city?: string;
    province?: string;
    country?: string;         // country as entered — NOT `countryCode`
    zip?: string;             // NOT `postalCode`
    phone?: string;
  };
  currency: string;           // ISO-4217 of the cart presentment currency
  settings: Record<string, any>;  // Merchant-configured values from the install
}

interface CartItem {
  id: string;                 // lineItemId
  variantId: string;
  productId: string;
  title: string;
  quantity: number;
  price: number;              // Effective unit price (display currency)
  originalPrice: number;
}
```

<Note>
  There is **no** `cart.cost`, no `countryCode` / `postalCode`, and no
  `latitude` / `longitude` on the shipping address — country arrives as
  `country` and the postal code as `zip`.
</Note>

## Output

```typescript theme={null}
interface LocalPickupOptionsFunctionOutput {
  pickupOptions: Array<{
    id: string;             // stable id; surfaces on the order
    title: string;          // shown in checkout, e.g. "Downtown Store"
    address: {
      address1?: string;
      address2?: string;
      city?: string;
      province?: string;
      countryCode?: string;
      postalCode?: string;
      latitude?: number;
      longitude?: number;
    };
    hours?: string;         // free-text, e.g. "Mon–Fri 9–6, Sat 10–4"
    distance?: number;      // straight-line km from shippingAddress
    fee?: number;           // surcharge in cart currency (default 0)
  }>;
}
```

Return an empty `pickupOptions: []` to opt out of offering pickup for
this cart (e.g. when the cart contains items not stocked at any pickup
location).

## Example — Two retail locations, filtered by destination

```javascript theme={null}
const LOCATIONS = [
  {
    id: 'store-downtown',
    title: 'Downtown Store',
    country: 'US',
    address: {
      address1: '123 Market St',
      city: 'San Francisco',
      province: 'CA',
      countryCode: 'US',
      postalCode: '94103',
    },
    hours: 'Mon-Fri 9-6, Sat 10-4',
  },
  {
    id: 'store-mission',
    title: 'Mission Store',
    country: 'US',
    address: {
      address1: '456 Valencia St',
      city: 'San Francisco',
      province: 'CA',
      countryCode: 'US',
      postalCode: '94110',
    },
    hours: 'Daily 10-8',
  },
];

export default function main(input) {
  const ship = input.shippingAddress;
  // Country arrives as `country` (no `countryCode`), postal code as `zip`.
  // No latitude/longitude is provided — if you need distance sorting,
  // geocode `ship.zip` / `ship.city` via your own service.
  const country = ship?.country;

  const pickupOptions = LOCATIONS.filter(
    (loc) => !country || loc.country === country,
  ).map((loc) => ({
    id: loc.id,
    title: loc.title,
    address: loc.address,
    hours: loc.hours,
    fee: 0,
  }));

  return { pickupOptions };
}
```

## Persistence

The options your function returns are **computed and merged into the
verifyCart response only** — they are not persisted to the order. There
is no `additionalFields.localPickupOptions` field, and the order's
shipping address is not rewritten to a merchant location. As noted at the
top of this page, the checkout consumer that would let a customer select
one of these options ships in the delivery-options release.

## When customers see what

<Note>
  As noted at the top of this page, the options returned by
  `local_pickup_options` functions are **not yet shown to customers**.
  Today the checkout shipping step only renders native
  warehouse-backed pickup (options where `sourceKind === 'warehouse'`);
  app-supplied options (`source: 'local_pickup'`) are excluded until the
  delivery-options consumer is enabled. There is no
  `order_ready_for_pickup` email topic.
</Note>

## See also

* [Pickup Point Options](/functions/pickup-point-options) — carrier
  parcel lockers / partner pickup points.
* [Shipping Rate](/functions/shipping-rate) — custom shipping rates
  alongside merchant zones.
* [Input field selection](/functions/input-fields) — trim the input
  payload to just the address fields you read.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.