Appearance
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 page | What it shows | Works without an account |
|---|---|---|
| Profile hub | Name, avatar, points, tier | No |
| Edit profile | The editable account fields | No |
| Refer a friend | Referral link and QR code | No |
| Find us | Store locator map | Yes |
| Get in touch | Contact form | Yes |
| Order history | Past orders | No |
| Order detail | One order, plus cancel and pay again | No |
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
| Stage | Action | API call | Auth |
|---|---|---|---|
| 1 | Profile page loads | GET /api/v1/mobile/user-detail | Customer |
| 1 | Points / tier shown on the hub | GET /api/v1/mobile/loyalty/customer, or GET /api/v2/brand/mobile/loyalty/points for a brand on the points ledger | Customer |
| 2a | Username typed | GET /api/v1/user/mobile/available/username — username query param | Customer |
| 2a | Avatar picked | POST /api/v1/user/mobile/uploadImage — multipart/form-data, max 10 MB; feed the returned url into user_profile | Customer |
| 2b | Save Changes | PUT /api/v1/mobile/details/update — every field optional, so send only what changed | Customer |
| 3 | Refer a friend popup | GET /api/v1/mobile/loyalty/referred lists the user's referrals; GET /api/v1/mobile/loyalty/referral-transactions lists what it earned | Customer |
| 3 | Redeeming someone else's code | POST /api/v1/mobile/loyalty/refer — referralCode. This is the receiving side, not the sharing side | Customer |
| 4 | Find us / Map | GET /api/v1/mobile/listed/hubs — lat + lng (must be sent together), show_on_nearest, search, state, country, limit/offset | Brand |
| 5b | Submit the contact form | POST /api/v1/mobile/contact-us — email and message required, plus firstName, lastName, emailType, phoneNumber | Brand |
| 6 | Order history loads | GET /api/v1/mobile/orders — withLineItems defaults to false, so a list that shows products needs it set | Customer |
| 7 | Order detail | GET /api/v1/mobile/order/:orderId — scoped to the caller | Customer |
| 7a | Cancel order | PUT /api/v1/mobile/order/cancel/:orderId — the body is an empty payload; the order id is in the path | Customer |
| 7b | Pay again | POST /api/v1/mobile/payment/link/:paymentGatewayId with the existing orderId in the body | Customer |
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.
The referral link comes from user-detail — conditionally
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 field | Sends as | Note |
|---|---|---|
| Name | firstName / lastName | The endpoint has no single name field |
email | Required | |
| Describe reason | message | Required |
| Reason for contact | emailType | An 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/updatechangesemailandphoneNumberoutright 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/usernameendpoint 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-detailhas 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/gatewaysand letting the customer pick again is the only documented route. - Notification preferences via
GET/PUT /api/v1/user/mobile/preferenceswould 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.