Documentation

Customer account

Customer profile, addresses, payment methods, tickets, messages, wishlist, and dashboard.

The customer account API at /client-data/* is the surface a customer portal calls. It covers profile, addresses, payment methods, support tickets, messages, push notifications, wishlist, and the dashboard rollup. Every call is scoped to the authenticated customer — there's no way to read or write another customer's data through this API.

Dashboard

GET/client-data/dashboardJWT
GET/client-data/allJWT

dashboard returns a curated rollup: counts of orders, pending tickets, unread messages, wallet balance, recent activity. Use it to populate a customer portal landing page in one round-trip. all returns the full bundle — every collection the customer has data in. Heavier, used on first sign-in or when refreshing local cache.

Profile

GET/client-data/profileJWT
PUT/client-data/profileJWT

Standard profile fields (name, phone, language, timezone, about). The PUT accepts a partial — send only fields you're changing.

Verification

GET/client-data/verification/statusJWT
POST/client-data/verification/email/sendJWT
POST/client-data/verification/email/verifyJWT
POST/client-data/verification/phone/sendJWT
POST/client-data/verification/phone/verifyJWT

Email and phone verification flows. send issues a code; verify confirms it. Status returns the current verification state for both.

Orders

GET/client-data/ordersJWT
GET/client-data/orders/:orderIdJWT

Paginated. Filter by status, sort by any field, and the response always returns the customer's own orders only — there's no cross-customer view.

Payment methods

GET/client-data/payment-methodsJWT
POST/client-data/payment-methodsJWT
DELETE/client-data/payment-methods/:paymentMethodIdJWT
PUT/client-data/payment-methods/:paymentMethodId/defaultJWT

Stripe-tokenised cards (and PayPal billing agreements). The POST accepts a Stripe paymentMethodId (created client-side via Stripe Elements); the platform attaches it to the customer's Stripe Customer object and stores a reference. The full card number never touches AppEngine.

// after createPaymentMethod() with Stripe Elements
await fetch('/api/client-data/payment-methods', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${customerJwt}` },
  body: JSON.stringify({
    paymentMethodId: 'pm_abc',
    setAsDefault: true,
  }),
});

Addresses

GET/client-data/addressesJWT
POST/client-data/addressesJWT
DELETE/client-data/addresses/:addressIdJWT
POST/client-data/addresses/autocompleteJWT
GET/client-data/addresses/place/:placeIdJWT

autocomplete uses Google Places (configured via the integrations module) for typeahead. The POST upserts — if the body contains an id, that record is updated; otherwise a new address is created.

Tickets

GET/client-data/ticketsJWT
GET/client-data/tickets/:ticketNumberJWT
POST/client-data/ticketsJWT
POST/client-data/tickets/with-attachmentsJWT
PUT/client-data/ticketsJWT

Customer-side ticket creation and lookup. The staff side lives in CRM tickets. Customers can attach files via with-attachments (multipart upload).

Messages and conversations

GET/client-data/messagesJWT
GET/client-data/conversationsJWT
POST/client-data/messagesJWT
PUT/client-data/messages/:messageId/status/:statusJWT

Direct messages between the customer and staff (or experts). conversations returns distinct threads; messages returns messages within a thread, paginated. Status updates (read, archived) are per-message.

Notifications and push

GET/client-data/notificationsJWT
POST/client-data/notifications/push-tokenJWT

Notifications are in-app messages. Push tokens are FCM/APNS device tokens registered for mobile push. The platform broadcasts notifications to the right channels via the Sync notification processor.

Wishlist

GET/client-data/wishlistJWT
POST/client-data/wishlist/:productIdJWT
DELETE/client-data/wishlist/:productIdJWT

Per-customer saved-products list. Used by the storefront UI for the heart icon on product cards.

Reservations

GET/client-data/reservationsJWT
GET/client-data/reservations/:reservationIdJWT
POST/client-data/reservationsJWT
PUT/client-data/reservationsJWT
DELETE/client-data/reservations/:reservationIdJWT
POST/client-data/reservations/available-slotsJWT

Customer-side reservation booking — picks slots, books, modifies, cancels. Same machinery as the staff reservations endpoints, scoped to the customer.

Files

GET/client-data/filesJWT
POST/client-data/files/uploadJWT
DELETE/client-data/files/:pathJWT

Per-customer file storage. Used for ticket attachments, profile photos, ID uploads. Files live under the customer's namespace in S3 (or the configured object store).

Benefits

GET/client-data/benefitsJWT
POST/client-data/benefits/enrollJWT
GET/client-data/benefits/enrollmentsJWT

Customer-side enrollment in benefit programmes (student discount, military, AAA, employer). Pricing automatically applies the benefit at checkout once approved.

Transactions

GET/client-data/transactionsJWT

Filter by status, payment method, date range. Returns the customer's own transactions only. For wallet and payout-side transactions, see Customer finance and wallet.

Every endpoint here resolves the principal via @CurrentCustomerOrUser(). If a User principal calls a customer endpoint, the response is scoped to the user's own customer record (if they have one) — there's no impersonation by default.