Skip to content

Template pages ​

Most of the app's secondary screens are template pages. Their layout is fixed and their content is published, not built: the app fetches the live content for its platform and renders it. What a brand controls on these pages is the theme — colours, type, imagery. It does not control which fields appear or what order they come in, because the calls behind each page decide that.

Nothing here is a profile page in particular. The profile hub is one of them, and so are the pages a shopper reaches from an order.

Template pageWhat it showsWorks without an account
Profile hubName, avatar, points, tierNo
Edit profileThe editable account fieldsNo
Refer a friendReferral link and QR codeNo
Find usStore locator mapYes
Get in touchContact formYes
Order historyPast ordersNo
Order detailOne order, plus cancel and pay againNo

Three of the branches off the hub are customer-only. The store locator and the contact form work on the brand token alone, so they are the only two a "Skip for now" guest can use.

Stages ​

API calls by stage ​

StageActionAPI callAuth
1Profile page loadsGET /api/v1/mobile/user-detailCustomer
1Points / tier shown on the hubGET /api/v1/mobile/loyalty/customer, or GET /api/v2/brand/mobile/loyalty/points for a brand on the points ledgerCustomer
2aUsername typedGET /api/v1/user/mobile/available/username — username query paramCustomer
2aAvatar pickedPOST /api/v1/user/mobile/uploadImage — multipart/form-data, max 10 MB; feed the returned url into user_profileCustomer
2bSave ChangesPUT /api/v1/mobile/details/update — every field optional, so send only what changedCustomer
3Refer a friend popupGET /api/v1/mobile/loyalty/referred lists the user's referrals; GET /api/v1/mobile/loyalty/referral-transactions lists what it earnedCustomer
3Redeeming someone else's codePOST /api/v1/mobile/loyalty/refer — referralCode. This is the receiving side, not the sharing sideCustomer
4Find us / MapGET /api/v1/mobile/listed/hubs — lat + lng (must be sent together), show_on_nearest, search, state, country, limit/offsetBrand
5bSubmit the contact formPOST /api/v1/mobile/contact-us — email and message required, plus firstName, lastName, emailType, phoneNumberBrand
6Order history loadsGET /api/v1/mobile/orders — withLineItems defaults to false, so a list that shows products needs it setCustomer
7Order detailGET /api/v1/mobile/order/:orderId — scoped to the callerCustomer
7aCancel orderPUT /api/v1/mobile/order/cancel/:orderId — the body is an empty payload; the order id is in the pathCustomer
7bPay againPOST /api/v1/mobile/payment/link/:paymentGatewayId with the existing orderId in the bodyCustomer

Cancel and pay again are the same two calls as checkout ​

Neither is a special endpoint. An order is created before any money moves, so an order that was never paid is a normal row waiting for a payment, and payment/link takes an orderId — passing the old one produces a fresh hosted link against the same order. That is all "pay again" is.

order/cancel/:orderId is equally plain: a PUT with an empty payload. What it refuses to cancel is not stated in the mobile set — no status enum is documented on the mobile order endpoints — so treat a success: false as the answer rather than gating the button on a status the client guessed.

Both leave the app for the gateway on the pay-again path, which has the same missing return path as the payment flow — there is no callback in the mobile set, so on return the app re-reads the order.

GET /api/v1/mobile/user-detail returns referral.referral_code and a composed referral_link (the brand level's referral_rule.referral_link + the code).

It appears only when both are true: the customer's brand_level.referral_rule is non-empty, and isLoyaltyUser is set. For a brand with no referral rule there is no link at all, so the app should hide "Refer a friend" rather than open an empty popup. The QR image is client-generated; there is no QR endpoint.

Field mapping for the contact form ​

Form fieldSends asNote
NamefirstName / lastNameThe endpoint has no single name field
EmailemailRequired
Describe reasonmessageRequired
Reason for contactemailTypeAn optional free-form string — no enum constrains it. The whole payload is passed through to the admin notification template, so whatever you send is what the brand's inbox shows

Paths ​

Edit profile Home → Profile Page → Edit Profile Page → first name, last name, username, email, phone number → Save Changes

Refer a friend Home → Profile Page → Refer a friend → referral link + QR code popup

Find us Home → Profile Page → Find us → Map

Contact us Home → Profile Page → Contact us → Get in Touch Page → name, email, reason for contact, describe reason → Submit

Orders Home → Profile Page → Your orders → Order History → Order Detail → Cancel order or Pay again

Open questions ​

  • After Save Changes — back to the profile page, stay on the edit page, or a confirmation toast? Diagram assumes return to profile.
  • Changing email or phone usually needs re-verification (an OTP step like signup uses). Not defined here, and no endpoint covers it: details/update changes email and phoneNumber outright with no verification step. The only OTP-guarded identity endpoints are the account merge and deactivation flows.
  • Username uniqueness check — inline as they type, or only on save? The available/username endpoint supports either.
  • Refer a friend popup: what actions does it offer besides showing the link — copy, native share sheet?
  • Map: in-app map view or handoff to an external maps app? Either way the pin data comes from listed/hubs.
  • "Reason for contact" — free text or a dropdown of preset reasons? If it becomes a dropdown, the values are the app's own; there is no enum for them.
  • Contact form fields duplicate data already on the profile. Prefill from the account? user-detail has everything needed.
  • No path defined for what happens after Submit. The endpoint returns a message string, not a record, so there is nothing to show a reference number from.
  • Which orders may be cancelled, and until when? Undocumented on the mobile side. Same for whether cancelling a paid order refunds it — no refund endpoint exists in the mobile set.
  • Pay again needs a gateway id, and the order does not say which gateway the first attempt used. Re-running payment/gateways and letting the customer pick again is the only documented route.
  • Notification preferences via GET/PUT /api/v1/user/mobile/preferences would be a template page too. It is not in the flow yet.
  • Users who arrived via "Skip for now" have no account. Stages 1, 2, 3, 6 and 7 all 401 without a customer JWT; stages 4 and 5 work.

Batch platform, Shopify app and API documentation