Appearance
Profile page (web)
The signed-in customer's own page: who they are, their points and level, and the settings they can change. It is one page rather than a journey, so it has no player. The tables list every call it integrates, grouped by what the page is doing.
Loading the page
| Section | API call | Access |
|---|---|---|
| Name, email, phone, avatar, username, bio | GET /api/v1/user/detail | Origin + Brand key + Customer |
| Points and level | The same call — user_points and brand_level | |
| Referral link | The same call — referral_link | |
| Points history | GET /api/v1/user/loyalty/point_transaction | Origin + Brand key + Customer |
| Saved addresses | GET /api/v1/user/address | Origin + Brand key + Customer |
| Notification preferences | GET /api/v1/user/preferences | Origin + Brand key + Customer |
| Order history | GET /api/v1/user/orders | Origin + Customer |
| Collection | See the collectible page |
GET /api/v1/user/detail returns most of the page in one response:
user_pointsis folded into one object:total,points_earnedandtotal_order, plus one key per brand holding that brand's balance.brand_levelis the customer's tier, with its thresholds andwallet_image.total_tradescounts completed trades in both directions.addresses,user_documentsandshopify_gift_cards(codes decrypted) are included.
user_points, brand_level and referral_link are deleted from the response when the customer is not a loyalty user (isLoyaltyUser false). The page has to treat them as optional. The call also only finds a verified account. An account that has registered but not verified its OTP gets User not found, even with a valid token.
Editing the page
| Action | API call | Access |
|---|---|---|
| Save name, email, phone, birthday, gender, bio | PUT /api/v1/user/details/update | Origin + Brand key + Customer |
| Check a username before saving it | GET /api/v1/user/available/username?username= | Origin + Customer + Brand key |
| Upload an avatar | PUT /api/v1/user/uploadImage (multipart), then send result.url as user_profile | Origin + Brand key + Customer |
| Add / edit / remove an address | POST /api/v1/user/address/add, PUT …/update/:addressId, DELETE …/delete/:addressId | Origin + Brand key + Customer |
| Change a notification preference | PUT /api/v1/user/preference | Origin + Brand key + Customer |
| Change the password | The password reset flow — not details/update, see below | As that flow states |
| Close the account | GET /api/v1/user/deactivate sends an OTP, then POST /api/v1/user/deactivate/confirmation with otp | Origin + Brand key + Customer |
What the API forces onto this page
- Never send
passwordtodetails/update. The validator accepts it, but the update writes the value without hashing it. Password login compares against an argon2 or SHA-256 hash, so the customer's password stops working. Offer password changes through the reset flow. - Replace the stored token after every save.
details/updatereturns a newtoken, because the customer token carries the email, phone, names, avatar, bio and username. If the page keeps the old token, those claims stay stale. - Email and phone changes are not re-verified. The update refuses one already used by another verified customer of the brand (Email or PhoneNumber is already taken.). Otherwise it saves it directly, with no OTP. An email containing
+is refused. - Check the username first. The update does not check whether a username is taken. The column is unique, so a taken username fails as a database error rather than a readable message.
available/usernamechecks across all brands, because the uniqueness does too. - Upload with PUT, not POST.
PUT /api/v1/user/uploadImagestores the file on Cloudinary and returns a publicurl, which is whatuser_profileholds. The POST on the same path stores a private/api/v1/files/link meant for receipts and IDs. The PUT replies withstatus: true, notsuccess. fullNamefollows the names. On every save, the customer record rebuildsfullNamefrom the storedfirstNameandlastName. SendingfullNameon its own has no effect on a customer who has either name. Edit the two name fields instead.- The primary address cannot be deleted. Make another address primary first.
- Every save is a loyalty event.
details/updatelogs a profile-update event with the changed field names. A profile-completion campaign can move on it, so the page should re-read campaign progress after saving. See Earn and spend. open_to_tradeandshow_collections_for_tradeare on this payload too. They are trading switches; the storefront has no trading calls.