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

# My Account

> This section details the APIs used to build the "My Account" area of your storefront, allowing logged-in customers to manage their profile, view past orders, handle returns or cancellations, update addresses, track loyalty points, and manage their reviews.

My Account is a logged-in experience. Use a session accessor and protect account routes at the framework's request boundary where possible.

Typical structure:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
/account
/account/profile
/account/addresses
/account/orders
/account/orders/[order-number]
/account/loyalty
/account/reviews
```

## Route protection

A route guard should distinguish authentication state from an upstream API failure.

* anonymous session → redirect to login or open authentication
* logged-in session → render account content
* token/session failure → recover session or require login
* transient Commerce Engine failure → show retry/error state, not an automatic logout

For SSR frameworks, use the request-bound server accessor. Avoid placing all account data in the root layout; keep it in the protected route boundary.

## Identity helpers

Many customer and order SDK methods resolve the current user or customer from the active session:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data: addresses } = await sdk.customer.listAddresses();
const { data: orders } = await sdk.order.listOrders();
const { data: loyalty } = await sdk.customer.getLoyaltyDetails();
```

Do not pass browser-supplied identity parameters when a session-aware overload exists.

Auth profile methods can require an explicit user ID:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const userId = await sdk.getUserId();
if (!userId) throw new Error("Login required");
```

B2B stores can have multiple users under one customer. Use `getUserId()` and `getCustomerId()` according to the operation contract rather than assuming they are always interchangeable.

## Profile

Retrieve the current user:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const userId = await sdk.getUserId();
if (!userId) throw new Error("Login required");

const { data, error } = await sdk.auth.getUserDetails({ id: userId });
if (error) throw new Error(error.message);

const user = data?.user;
```

Update editable fields:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.auth.updateUserDetails(
  { id: userId },
  {
    first_name: firstName,
    last_name: lastName,
  },
);

if (error) throw new Error(error.message);
```

Email or phone changes can require a separate OTP verification action. Retrieve the exact current operation contracts before implementing those flows.

### Profile UX

* show which contact methods are verified
* preserve form input on validation failure
* disable duplicate submissions
* update local/session user state from the returned data
* do not expose internal IDs unnecessarily

## Address book

List saved addresses:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.customer.listAddresses();
if (error) throw new Error(error.message);

const addresses = data?.addresses ?? [];
```

Create an address:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.customer.createAddress({
  first_name: "Asha",
  last_name: "Sharma",
  email: "asha@example.com",
  phone: "9876543210",
  country_code: "+91",
  address_line1: "123 Market Road",
  address_line2: "",
  city: "Mumbai",
  state: "Maharashtra",
  pincode: "400001",
  country: "India",
});

if (error) throw new Error(error.message);
```

Confirm the exact input fields with the LLM-first operation and request type. Country requirements vary.

Update and delete using the current operation signatures. After mutation:

* invalidate the address list
* preserve default billing/shipping constraints
* check whether an active subscription or other feature references the address before deletion if the API exposes such a restriction
* show a confirmation for destructive actions

During checkout, link a saved address ID to the cart rather than copying a stale address object where the operation supports IDs.

<Frame caption="Address book lifecycle">
  <iframe title="Address book lifecycle" allowFullScreen width="100%" height="760" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20UI%20as%20Account%20UI%0A%20%20%20%20participant%20SDK%20as%20Session%20Customer%20SDK%0A%20%20%20%20participant%20CE%20as%20Commerce%20Engine%20API%0A%20%20%20%20User-%3E%3EUI%3A%20Opens%20Address%20Book%0A%20%20%20%20UI-%3E%3ESDK%3A%20listAddresses%28%29%0A%20%20%20%20SDK-%3E%3ECE%3A%20GET%20addresses%20for%20current%20session%20user%0A%20%20%20%20CE--%3E%3ESDK%3A%20Saved%20addresses%0A%20%20%20%20SDK--%3E%3EUI%3A%20Render%20list%0A%20%20%20%20alt%20Add%20address%0A%20%20%20%20%20%20%20%20User-%3E%3EUI%3A%20Submits%20new%20address%0A%20%20%20%20%20%20%20%20UI-%3E%3ESDK%3A%20createAddress%28address%29%0A%20%20%20%20%20%20%20%20SDK-%3E%3ECE%3A%20POST%20address%0A%20%20%20%20%20%20%20%20CE--%3E%3ESDK%3A%20Created%20address%0A%20%20%20%20%20%20%20%20SDK--%3E%3EUI%3A%20Insert%20or%20refetch%0A%20%20%20%20else%20Edit%20address%0A%20%20%20%20%20%20%20%20User-%3E%3EUI%3A%20Saves%20changes%0A%20%20%20%20%20%20%20%20UI-%3E%3ESDK%3A%20updateAddress%28address_id%2C%20changes%29%0A%20%20%20%20%20%20%20%20SDK-%3E%3ECE%3A%20PUT%20address%0A%20%20%20%20%20%20%20%20CE--%3E%3ESDK%3A%20Updated%20address%0A%20%20%20%20%20%20%20%20SDK--%3E%3EUI%3A%20Replace%20cached%20address%0A%20%20%20%20else%20Delete%20address%0A%20%20%20%20%20%20%20%20User-%3E%3EUI%3A%20Confirms%20deletion%0A%20%20%20%20%20%20%20%20UI-%3E%3ESDK%3A%20deleteAddress%28address_id%29%0A%20%20%20%20%20%20%20%20SDK-%3E%3ECE%3A%20DELETE%20address%0A%20%20%20%20%20%20%20%20CE--%3E%3ESDK%3A%20Success%0A%20%20%20%20%20%20%20%20SDK--%3E%3EUI%3A%20Remove%20or%20refetch%0A%20%20%20%20end" />
</Frame>

## Order history

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.order.listOrders({
  page: 1,
  limit: 10,
  sort_by: JSON.stringify({ order_date: "desc" }),
});

if (error) throw new Error(error.message);

const orders = data?.orders ?? [];
```

Use pagination and status filters for larger histories. A card should normally show:

* order number
* order date
* current status
* payable/paid amount and currency
* a representative item image
* shipment or payment attention state where relevant

Do not expose order data solely because a user knows an order number; the request-bound session must own the order.

## Order detail

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error, response } = await sdk.order.getOrderDetails({
  order_number: orderNumber,
});

if (response?.status === 404) {
  // Confirmed not found or not accessible for this session.
}

if (error) throw new Error(error.message);
```

Render:

* ordered items and quantities
* billing and shipping addresses
* pricing, discounts, tax, shipping, and payment totals
* payment state
* fulfilment and shipment state
* cancellation/refund state

An order can have multiple shipments:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data: shipmentData, error } =
  await sdk.order.listOrderShipments({
    order_number: orderNumber,
  });

if (error) throw new Error(error.message);
const shipments = shipmentData?.shipments ?? [];
```

Show each shipment's items, status, tracking URL, AWB/tracking number, and estimated delivery when present.

## Payment status and retry

A failed payment can remain retryable:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.order.getPaymentStatus(orderNumber);
if (error) throw new Error(error.message);
```

Show Retry only when the response says `is_retry_available` is true. Use the same provider-specific payment payload rules as checkout and verify the final result through payment-status polling.

Do not trust old redirect parameters when rendering order payment state.

## Cancellation

Fetch the latest order detail immediately before showing or executing cancellation. Show the action only when `is_cancellation_allowed` is true.

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data: orderData, error: orderDetailError } =
  await sdk.order.getOrderDetails({
    order_number: orderNumber,
  });

if (orderDetailError) throw new Error(orderDetailError.message);

const order = orderData?.order;
if (!order) throw new Error("Order could not be retrieved");

if (order.is_cancellation_allowed) {
  const { data, error } = await sdk.order.cancelOrder(
    { order_number: order.order_number },
    {
      cancellation_reason: reason,
      refund_mode: "original_payment_mode",
      feedback,
    },
  );

  if (error) throw new Error(error.message);
}
```

Retrieve the current cancellation body contract before implementation. If bank transfer is supported, collect and handle bank details through the approved secure flow rather than an improvised text field.

After success, invalidate order detail, order history, payment, shipment, and refund queries.

<Frame caption="Order history and conditional cancellation">
  <iframe title="Order history and conditional cancellation" allowFullScreen width="100%" height="780" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20UI%20as%20Account%20UI%0A%20%20%20%20participant%20SDK%20as%20Session%20Order%20SDK%0A%20%20%20%20participant%20CE%20as%20Commerce%20Engine%20API%0A%20%20%20%20User-%3E%3EUI%3A%20Opens%20My%20Orders%0A%20%20%20%20UI-%3E%3ESDK%3A%20listOrders%28page%2C%20status%29%0A%20%20%20%20SDK-%3E%3ECE%3A%20GET%20%2Forders%20for%20session%20user%0A%20%20%20%20CE--%3E%3ESDK%3A%20Orders%20%2B%20pagination%0A%20%20%20%20SDK--%3E%3EUI%3A%20Render%20order%20history%0A%20%20%20%20User-%3E%3EUI%3A%20Opens%20an%20order%0A%20%20%20%20UI-%3E%3ESDK%3A%20getOrderDetails%28order_number%29%0A%20%20%20%20SDK-%3E%3ECE%3A%20GET%20%2Forders%2F%7Border_number%7D%0A%20%20%20%20CE--%3E%3ESDK%3A%20Order%20detail%20%2B%20cancellation%20flag%0A%20%20%20%20SDK--%3E%3EUI%3A%20Render%20items%2C%20shipments%2C%20payment%2C%20totals%0A%20%20%20%20alt%20Cancellation%20allowed%0A%20%20%20%20%20%20%20%20User-%3E%3EUI%3A%20Confirms%20reason%20and%20refund%20mode%0A%20%20%20%20%20%20%20%20UI-%3E%3ESDK%3A%20cancelOrder%28order_number%2C%20request%29%0A%20%20%20%20%20%20%20%20SDK-%3E%3ECE%3A%20POST%20%2Forders%2F%7Border_number%7D%2Fcancel%0A%20%20%20%20%20%20%20%20CE--%3E%3ESDK%3A%20Updated%20cancelled%20order%0A%20%20%20%20%20%20%20%20SDK--%3E%3EUI%3A%20Replace%20state%20and%20invalidate%20lists%0A%20%20%20%20else%20Cancellation%20not%20allowed%0A%20%20%20%20%20%20%20%20UI--%3E%3EUser%3A%20Hide%20cancellation%20and%20show%20support%20guidance%0A%20%20%20%20end" />
</Frame>

## Returns

Customer-initiated storefront returns are not currently the default supported flow described by the Commerce Engine skills. Returns are managed by store administrators through the Admin Portal, while customers can cancel an eligible order before the cancellation window closes.

Do not generate a “Request Return” form unless the store has a verified custom return API or workflow. Explain the store's support route and show refund/return status supplied by the order APIs.

## Refunds and payments

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const [paymentsResult, refundsResult] = await Promise.all([
  sdk.order.listOrderPayments({ order_number: orderNumber }),
  sdk.order.listOrderRefunds({ order_number: orderNumber }),
]);

if (paymentsResult.error) throw new Error(paymentsResult.error.message);
if (refundsResult.error) throw new Error(refundsResult.error.message);

const payments = paymentsResult.data?.payments ?? [];
const refunds = refundsResult.data?.refunds ?? [];
```

Present transaction state without exposing provider secrets or raw sensitive gateway payloads.

## Loyalty

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.customer.getLoyaltyDetails();
if (error) throw new Error(error.message);

const loyalty = data?.loyalty;
```

A loyalty page can show:

* current tier
* available/redeemable balance
* total earned and redeemed
* expiry where supplied
* activity history

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data: activityData, error } =
  await sdk.customer.listLoyaltyPointsActivity({
    page: 1,
    limit: 20,
  });

if (error) throw new Error(error.message);
const activity = activityData?.loyalty_points_activity ?? [];
```

Use the returned currency/value rules; do not assume one loyalty point equals one currency unit.

## Reviews

List the customer's existing reviews and eligible purchases:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data, error } = await sdk.customer.listCustomerReviews();
if (error) throw new Error(error.message);

const reviews = data?.reviews ?? [];
const readyForReview = data?.ready_for_review ?? [];
```

The response can include submitted reviews and items ready for review. A review submission is a catalog session write and can require product, order, rating, and media context according to the operation contract.

Prevent duplicate submissions and show moderation/publishing state where returned.

## Notification preferences and profile image

These features use auth profile operations and may require explicit user IDs or multipart uploads.

* retrieve current preferences before editing
* separate transactional requirements from optional marketing consent
* preserve channel-specific consent
* validate image type/size before upload
* remove cached profile image after replacement/deletion

Use exact operation contracts instead of inferring multipart field names.

## Data fetching and cache boundaries

* server-render stable account summaries where the framework supports request sessions
* use client queries for interactive tabs and mutations
* do not cache one user's account response globally
* key caches by operation and authenticated session where necessary
* remove protected data immediately after logout
* refetch order/cart state after login because the anonymous cart can merge

## Empty and failure states

| Page | Valid empty state |
| - | - |
| Addresses | No saved addresses; offer Add address |
| Orders | No purchases yet; link to catalog |
| Loyalty | Program disabled or no activity |
| Reviews | No submitted or eligible reviews |
| Shipments | Order not yet shipped |
| Refunds | No refund initiated |

Keep valid empty states separate from authentication or upstream errors.

## Accessibility

* use headings and landmarks across account sections
* identify current navigation tab
* announce mutation success/failure
* require confirmation for delete/cancel actions
* return focus after dialogs close
* make shipment timelines and statuses understandable without colour alone
* expose tracking links with descriptive labels

## Production checklist

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
[ ] account routes protected at request/session boundary
[ ] auth failure distinguished from upstream error
[ ] session overloads used instead of browser-supplied IDs
[ ] user vs customer identity handled deliberately
[ ] protected data removed after logout
[ ] address mutations invalidate saved-address state
[ ] order list paginated
[ ] order access scoped to current session
[ ] multiple shipments supported
[ ] cancellation shown only when currently allowed
[ ] retry shown only when payment says it is available
[ ] no unverified storefront return form generated
[ ] money, loyalty, payment, and refund values use returned contracts
[ ] empty, loading, error, and destructive-action states tested
```

<Card title="Orders skill and exact contracts" icon="robot" href="https://llm-docs.commercengine.io/sdk/storefront">
  Use the orders skill for lifecycle decisions and retrieve exact methods/types from the LLM-first reference.
</Card>


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