feat: add typed store integration endpoints for status and holiday hours

This commit is contained in:
MOHAN 2026-03-29 17:54:23 +05:30
parent 8f58a64bc8
commit 1474781c08
8 changed files with 557 additions and 0 deletions

View File

@ -0,0 +1,27 @@
# 04 Store Integration Audit
Source checked: Uber Eats "Store Integration" section shared by you.
## Implemented Now
- Retrieve all stores:
- `GET /api/v1/uber/stores`
- Retrieve store by ID:
- `GET /api/v1/uber/stores/{storeId}`
- Retrieve and set online/offline store status:
- `GET /api/v1/uber/stores/{storeId}/status`
- `POST /api/v1/uber/stores/{storeId}/status`
- Retrieve and set date-specific holiday hours:
- `GET /api/v1/uber/stores/{storeId}/holiday-hours`
- `POST /api/v1/uber/stores/{storeId}/holiday-hours`
## Existing Before
- Store hours update route (`PUT /api/v1/uber/stores/hours`)
- Provisioning routes and store discovery via merchant auth flow
## Pending
- Exact status payload schema hardening once official request examples are finalized
- Extended store settings endpoints not yet included in shared doc dump

View File

@ -7,3 +7,11 @@ Uber Eats store-focused integrations:
- Holiday/special hours
- Operational metadata sync
Typed routes available:
- `GET /api/v1/uber/stores`
- `GET /api/v1/uber/stores/{storeId}`
- `GET /api/v1/uber/stores/{storeId}/status`
- `POST /api/v1/uber/stores/{storeId}/status`
- `GET /api/v1/uber/stores/{storeId}/holiday-hours`
- `POST /api/v1/uber/stores/{storeId}/holiday-hours`

View File

@ -280,6 +280,19 @@
}
}
},
"/api/v1/uber/stores": {
"get": {
"summary": "Retrieve all stores provisioned to developer account",
"tags": [
"Uber Stores"
],
"responses": {
"200": {
"description": "Stores retrieved"
}
}
}
},
"/api/v1/uber/stores/provisionable": {
"get": {
"summary": "Retrieve stores associated with merchant OAuth token",
@ -303,6 +316,117 @@
}
}
},
"/api/v1/uber/stores/{storeId}": {
"get": {
"summary": "Retrieve store details by store ID",
"tags": [
"Uber Stores"
],
"parameters": [
{
"in": "path",
"name": "storeId",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Store retrieved"
}
}
}
},
"/api/v1/uber/stores/{storeId}/status": {
"get": {
"summary": "Retrieve store online/offline status",
"tags": [
"Uber Stores"
],
"parameters": [
{
"in": "path",
"name": "storeId",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Store status retrieved"
}
}
},
"post": {
"summary": "Set store online/offline status",
"tags": [
"Uber Stores"
],
"parameters": [
{
"in": "path",
"name": "storeId",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Store status updated"
}
}
}
},
"/api/v1/uber/stores/{storeId}/holiday-hours": {
"get": {
"summary": "Retrieve store holiday hours",
"tags": [
"Uber Stores"
],
"parameters": [
{
"in": "path",
"name": "storeId",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Holiday hours retrieved"
}
}
},
"post": {
"summary": "Set store holiday hours",
"tags": [
"Uber Stores"
],
"parameters": [
{
"in": "path",
"name": "storeId",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Holiday hours updated"
}
}
}
},
"/api/v1/uber/orders/{orderId}/action": {
"post": {
"summary": "Trigger order action (accept, deny, ready, cancel)",

View File

@ -230,6 +230,175 @@
}
}
},
{
"name": "List Stores (App)",
"request": {
"method": "GET",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores"
]
}
}
},
{
"name": "Get Store By ID",
"request": {
"method": "GET",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores",
"{{storeId}}"
]
}
}
},
{
"name": "Get Store Status",
"request": {
"method": "GET",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/status",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores",
"{{storeId}}",
"status"
]
}
}
},
{
"name": "Set Store Status",
"request": {
"method": "POST",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"status\": \"OFFLINE\",\n \"reason\": \"maintenance\"\n}"
},
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/status",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores",
"{{storeId}}",
"status"
]
}
}
},
{
"name": "Get Holiday Hours",
"request": {
"method": "GET",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/holiday-hours",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores",
"{{storeId}}",
"holiday-hours"
]
}
}
},
{
"name": "Set Holiday Hours",
"request": {
"method": "POST",
"header": [
{
"key": "x-api-key",
"value": "{{apiKey}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"holiday_hours\": []\n}"
},
"url": {
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/holiday-hours",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"v1",
"uber",
"stores",
"{{storeId}}",
"holiday-hours"
]
}
}
},
{
"name": "Create POS Data (Provision)",
"request": {

View File

@ -14,6 +14,8 @@ module.exports = {
stores: {
list: "/v1/eats/stores",
getById: "/v1/eats/stores/{storeId}",
status: "/v1/eats/stores/{storeId}/status",
holidayHours: "/v1/eats/stores/{storeId}/holiday_hours",
updateHours: "/v1/eats/stores/{storeId}/hours",
inventory: "/v1/eats/stores/{storeId}/inventory",
posData: "/v1/eats/stores/{storeId}/pos_data"

View File

@ -115,6 +115,55 @@ async function listProvisionableStores(req, res) {
return res.json({ success: true, data });
}
async function listStores(req, res) {
const data = await proxyService.listStores({
query: req.query
});
return res.json({ success: true, data });
}
async function getStoreById(req, res) {
const data = await proxyService.getStoreById({
storeId: req.params.storeId
});
return res.json({ success: true, data });
}
async function getStoreStatus(req, res) {
const data = await proxyService.getStoreStatus({
storeId: req.params.storeId
});
return res.json({ success: true, data });
}
async function setStoreStatus(req, res) {
const schema = z.object({
status: z.string().optional(),
reason: z.string().optional()
});
const payload = schema.partial().parse(req.body || {});
const data = await proxyService.setStoreStatus({
storeId: req.params.storeId,
payload
});
return res.json({ success: true, data });
}
async function getHolidayHours(req, res) {
const data = await proxyService.getHolidayHours({
storeId: req.params.storeId
});
return res.json({ success: true, data });
}
async function setHolidayHours(req, res) {
const data = await proxyService.setHolidayHours({
storeId: req.params.storeId,
payload: req.body || {}
});
return res.json({ success: true, data });
}
async function createPosData(req, res) {
const schema = z.object({
merchantId: z.string().min(1),
@ -164,6 +213,12 @@ module.exports = {
orderAction,
updateHours,
listProvisionableStores,
listStores,
getStoreById,
getStoreStatus,
setStoreStatus,
getHolidayHours,
setHolidayHours,
createPosData,
patchPosData,
deletePosData

View File

@ -215,6 +215,74 @@ async function listProvisionableStores({ merchantId, query }) {
});
}
async function listStores({ query }) {
return callUberApi({
method: "GET",
uberPath: uberEndpoints.stores.list,
query,
wrapperRoute: "/api/v1/uber/stores",
authMode: "app",
scopes: AUTH_SCOPES.STORE
});
}
async function getStoreById({ storeId }) {
const uberPath = interpolatePath(uberEndpoints.stores.getById, { storeId });
return callUberApi({
method: "GET",
uberPath,
wrapperRoute: "/api/v1/uber/stores/:storeId",
authMode: "app",
scopes: AUTH_SCOPES.STORE
});
}
async function getStoreStatus({ storeId }) {
const uberPath = interpolatePath(uberEndpoints.stores.status, { storeId });
return callUberApi({
method: "GET",
uberPath,
wrapperRoute: "/api/v1/uber/stores/:storeId/status",
authMode: "app",
scopes: AUTH_SCOPES.STORE
});
}
async function setStoreStatus({ storeId, payload }) {
const uberPath = interpolatePath(uberEndpoints.stores.status, { storeId });
return callUberApi({
method: "POST",
uberPath,
body: payload,
wrapperRoute: "/api/v1/uber/stores/:storeId/status",
authMode: "app",
scopes: AUTH_SCOPES.STORE_STATUS_WRITE
});
}
async function getHolidayHours({ storeId }) {
const uberPath = interpolatePath(uberEndpoints.stores.holidayHours, { storeId });
return callUberApi({
method: "GET",
uberPath,
wrapperRoute: "/api/v1/uber/stores/:storeId/holiday-hours",
authMode: "app",
scopes: AUTH_SCOPES.STORE
});
}
async function setHolidayHours({ storeId, payload }) {
const uberPath = interpolatePath(uberEndpoints.stores.holidayHours, { storeId });
return callUberApi({
method: "POST",
uberPath,
body: payload,
wrapperRoute: "/api/v1/uber/stores/:storeId/holiday-hours",
authMode: "app",
scopes: AUTH_SCOPES.STORE
});
}
async function createPosData({ merchantId, storeId, payload }) {
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
return callUberApi({
@ -262,6 +330,12 @@ module.exports = {
orderAction,
updateStoreHours,
listProvisionableStores,
listStores,
getStoreById,
getStoreStatus,
setStoreStatus,
getHolidayHours,
setHolidayHours,
createPosData,
patchPosData,
deletePosData

View File

@ -69,6 +69,19 @@ router.get("/uber/menu", asyncHandler(controller.getMenu));
*/
router.get("/uber/orders", asyncHandler(controller.listOrders));
/**
* @openapi
* /api/v1/uber/stores:
* get:
* summary: Retrieve all stores provisioned to developer account
* tags:
* - Uber Stores
* responses:
* 200:
* description: Stores retrieved
*/
router.get("/uber/stores", asyncHandler(controller.listStores));
/**
* @openapi
* /api/v1/uber/stores/provisionable:
@ -88,6 +101,91 @@ router.get("/uber/orders", asyncHandler(controller.listOrders));
*/
router.get("/uber/stores/provisionable", asyncHandler(controller.listProvisionableStores));
/**
* @openapi
* /api/v1/uber/stores/{storeId}:
* get:
* summary: Retrieve store details by store ID
* tags:
* - Uber Stores
* parameters:
* - in: path
* name: storeId
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Store retrieved
*/
router.get("/uber/stores/:storeId", asyncHandler(controller.getStoreById));
/**
* @openapi
* /api/v1/uber/stores/{storeId}/status:
* get:
* summary: Retrieve store online/offline status
* tags:
* - Uber Stores
* parameters:
* - in: path
* name: storeId
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Store status retrieved
* post:
* summary: Set store online/offline status
* tags:
* - Uber Stores
* parameters:
* - in: path
* name: storeId
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Store status updated
*/
router.get("/uber/stores/:storeId/status", asyncHandler(controller.getStoreStatus));
router.post("/uber/stores/:storeId/status", asyncHandler(controller.setStoreStatus));
/**
* @openapi
* /api/v1/uber/stores/{storeId}/holiday-hours:
* get:
* summary: Retrieve store holiday hours
* tags:
* - Uber Stores
* parameters:
* - in: path
* name: storeId
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Holiday hours retrieved
* post:
* summary: Set store holiday hours
* tags:
* - Uber Stores
* parameters:
* - in: path
* name: storeId
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Holiday hours updated
*/
router.get("/uber/stores/:storeId/holiday-hours", asyncHandler(controller.getHolidayHours));
router.post("/uber/stores/:storeId/holiday-hours", asyncHandler(controller.setHolidayHours));
/**
* @openapi
* /api/v1/uber/orders/{orderId}/action: