Merchant by id
In one line: once the app knows which store a tap lands on, this is the call that loads that store's screen — and it's actually the store detail endpoint,
GET /stores/{id}.
When you'd use this
Any banner tap that lands on a store — a store banner, or a nearest_branch banner that
Nearest store resolved to a store id — ends with "open this store." The app then
needs that store's details to draw the screen. That's what this call returns.
The name "Merchant by id" is historical: there is no live endpoint by that name. Use store detail.
Example: finishing a banner tap
Ids and names below are illustrative.
- The customer taps a
nearest_branchbanner for Burger Bros. Nearest store returns store1874. - The app calls
GET /api/v2/client/stores/1874. - The response describes Burger Bros JBR. The app renders the store screen.
- The response also contains a
merchant_id, say310. Don't feed that back into Nearest store — it's a different kind of id (see Watch out). If you need to resolve this brand's nearest branch again, use the banner'snearest_branch_merchant_id(42).
What if it's different?
- Nearest store returned
null. Don't call this endpoint at all — the tap is a no-op. - The store id is unknown or the store is inactive. Not documented yet — see the matching item under Banners › Not documented yet.
How to call it
GET /api/v2/client/stores/{id}
Endpoint:
GET /api/v2/client/stores/{id}— OpenAPI operationClientStoresController_getStoreDetailinopenapi/order-v2-client.json, where the exact request and response fields live.
{id}is a store id — from astorebanner'smerchant_idfield, or from Nearest store's result.- Render the store screen from the response.
Watch out
- "Merchant id" means three different things in this module. The store response's
merchant_id, a banner'smerchant_id, and a banner'snearest_branch_merchant_idare three different ids. Only the last one works with Nearest store. - Mixing them up fails silently. Sent to Nearest store, a wrong id returns
200with anullstore id. Sent here, a non-store id may load an unrelated store, since the id ranges overlap. When a ticket says "merchant id," ask which one.
Details (for backend)
Everything below is the reasoning and the exact rules — read it when you're changing this endpoint or debugging a surprising result.
A naming note
There is no live client endpoint literally named "merchant by id." A route matching that
description exists in the codebase — GET locate/merchants/:id in
ClientMerchantsController (src/modules/client/merchants/merchants.controller.ts,
getMerchantDetail → MerchantsService.getAhsanMerchantDetail) — but the controller is commented
out of the client app's module wiring:
// ClientMerchantsController, // Ignore APIs not used yet
(src/modules/client/client.module.ts, near the ClientMerchantsModule import.) It is not mounted,
not reachable, and does not appear in the committed OpenAPI snapshot, so there is no OpenAPI operation
to point to for it.
The endpoint that actually plays this role for the client app is store detail (GET /api/v2/client/stores/{id}, above). Module: src/modules/client/stores/,
ClientStoresController.getStoreDetail → ClientStoresService.getStoreDetail
(src/modules/client/stores/stores.service.ts). It's keyed on a store id, not a merchants.id, but
its response is where the "merchant" identity that the rest of this module cares about actually
shows up — see below.
The merchant_id hazard
The store-detail response includes a merchant_id field. It is stores.collection_id, not
merchants.id — the response is built by formatStoreDetailResponse
(src/shared/helper/mapping-store-response.ts), whose legacyApiMerchantId option defaults to
false, meaning merchant_id is populated from store.collection_id:
merchant_id: (legacyApiMerchantId ? store?.merchantId : store?.collection_id)?.toString(),
GET /stores/{id} calls formatStoreDetailResponse without passing that option, so it always takes
the collection_id branch.
This is the same collision documented on Nearest store:
"brand" in the client API is a collection, and the field kept the old name merchant_id. Two
different id spaces wear the same label:
Where you see merchant_id | What it actually is |
|---|---|
Store detail (this endpoint), store list, GET /stores/branches?merchantId= | stores.collection_id |
A banner object's merchant_id (see Banners) | the banner's own store_id |
A banner's nearest_branch_merchant_id | the real merchants.id |
None of these produce an error when used in the wrong place — a collection_id or a banner's
store_id passed to Nearest store's :merchantId path param just resolves to no
match (200, store_id: null). Whenever a task or a bug report says "merchant id," pin down which
of these three it means before writing a query or a client call.
Not documented yet
- Whether the dead
locate/merchants/:idroute is planned to come back, or is safe to delete — nothing in the branch history or docs read for this page says either way.