feat: align integration configuration endpoints with api suite v1.0.0
This commit is contained in:
parent
fe524a719d
commit
54565d9b6d
@ -9,6 +9,8 @@ Source checked: Uber Eats "Integration Configuration Flows" section shared by yo
|
|||||||
- Uses merchant token (`authorization_code` / `eats.pos_provisioning`)
|
- Uses merchant token (`authorization_code` / `eats.pos_provisioning`)
|
||||||
- Store activation via POS data:
|
- Store activation via POS data:
|
||||||
- `POST /api/v1/uber/stores/{storeId}/pos-data`
|
- `POST /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
|
- Retrieve integration configuration:
|
||||||
|
- `GET /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
- Store integration update/deactivation:
|
- Store integration update/deactivation:
|
||||||
- `PATCH /api/v1/uber/stores/{storeId}/pos-data`
|
- `PATCH /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
- Store de-provision:
|
- Store de-provision:
|
||||||
@ -26,6 +28,5 @@ Source checked: Uber Eats "Integration Configuration Flows" section shared by yo
|
|||||||
## Pending
|
## Pending
|
||||||
|
|
||||||
- Strong store mapping workflow (location-data assisted matching UI flow)
|
- Strong store mapping workflow (location-data assisted matching UI flow)
|
||||||
- Typed POS data schema once exact request fields are finalized from endpoint reference
|
- Strict nested schema validation for deeper webhook config object variants
|
||||||
- Automated post-provisioning follow-up actions (e.g., mandatory menu upload jobs)
|
- Automated post-provisioning follow-up actions (e.g., mandatory menu upload jobs)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
# 03 Integration Configuration Suite 1.0.0 Audit
|
||||||
|
|
||||||
|
Source checked: "Uber Eats Integration Activation & Configuration API Suite (1.0.0)" shared by you.
|
||||||
|
|
||||||
|
## Endpoint Coverage
|
||||||
|
|
||||||
|
- Activate Integration:
|
||||||
|
- `POST /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
|
- Uses merchant OAuth token (`eats.pos_provisioning`) via `merchantId`
|
||||||
|
- Update Integration Configuration:
|
||||||
|
- `PATCH /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
|
- Uses app token with `eats.store` scope
|
||||||
|
- Retrieve Integration Configuration:
|
||||||
|
- `GET /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
|
- Uses app token with `eats.store` scope
|
||||||
|
- Remove Integration Configuration:
|
||||||
|
- `DELETE /api/v1/uber/stores/{storeId}/pos-data`
|
||||||
|
- Uses app token with `eats.store` scope
|
||||||
|
|
||||||
|
## Schema Alignment
|
||||||
|
|
||||||
|
- Added typed request schema fields for `pos_data`:
|
||||||
|
- `allowed_customer_requests`
|
||||||
|
- `integrator_brand_id`
|
||||||
|
- `integrator_store_id`
|
||||||
|
- `is_order_manager`
|
||||||
|
- `merchant_store_id`
|
||||||
|
- `require_manual_acceptance`
|
||||||
|
- `store_configuration_data`
|
||||||
|
- `webhooks_config`
|
||||||
|
- `integration_enabled` (PATCH)
|
||||||
|
|
||||||
|
## Pending
|
||||||
|
|
||||||
|
- Add stricter nested object typing for all `webhooks_config` variants when final examples are shared.
|
||||||
|
|
||||||
@ -629,6 +629,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"get": {
|
||||||
|
"summary": "Retrieve integration configuration for selected store (GET /pos_data)",
|
||||||
|
"tags": [
|
||||||
|
"Uber Provisioning"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "storeId",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Store integration configuration retrieved"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"patch": {
|
"patch": {
|
||||||
"summary": "Update integration settings for selected store (PATCH /pos_data)",
|
"summary": "Update integration settings for selected store (PATCH /pos_data)",
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@ -662,7 +662,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"merchantId\": \"{{merchantId}}\",\n \"posData\": {\n \"partner_store_id\": \"POS_STORE_001\",\n \"integration_enabled\": true,\n \"store_configuration_data\": {}\n }\n}"
|
"raw": "{\n \"merchantId\": \"{{merchantId}}\",\n \"posData\": {\n \"allowed_customer_requests\": {\n \"allow_single_use_items_requests\": false,\n \"allow_special_instruction_requests\": false\n },\n \"integrator_brand_id\": \"app-brand-1jj9th32\",\n \"integrator_store_id\": \"app-store-001\",\n \"is_order_manager\": true,\n \"merchant_store_id\": \"UberStore1\",\n \"require_manual_acceptance\": false,\n \"store_configuration_data\": \"v1-config\",\n \"webhooks_config\": {\n \"webhooks_version\": \"1.0.0\"\n }\n }\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
||||||
@ -680,6 +680,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Get POS Data",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "x-api-key",
|
||||||
|
"value": "{{apiKey}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
||||||
|
"host": [
|
||||||
|
"{{baseUrl}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"v1",
|
||||||
|
"uber",
|
||||||
|
"stores",
|
||||||
|
"{{storeId}}",
|
||||||
|
"pos-data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Patch POS Data (Enable/Disable)",
|
"name": "Patch POS Data (Enable/Disable)",
|
||||||
"request": {
|
"request": {
|
||||||
@ -696,7 +722,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"merchantId\": \"{{merchantId}}\",\n \"posData\": {\n \"integration_enabled\": false\n }\n}"
|
"raw": "{\n \"posData\": {\n \"integration_enabled\": false,\n \"require_manual_acceptance\": false\n }\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
||||||
@ -722,16 +748,8 @@
|
|||||||
{
|
{
|
||||||
"key": "x-api-key",
|
"key": "x-api-key",
|
||||||
"value": "{{apiKey}}"
|
"value": "{{apiKey}}"
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Type",
|
|
||||||
"value": "application/json"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"body": {
|
|
||||||
"mode": "raw",
|
|
||||||
"raw": "{\n \"merchantId\": \"{{merchantId}}\"\n}"
|
|
||||||
},
|
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
"raw": "{{baseUrl}}/api/v1/uber/stores/{{storeId}}/pos-data",
|
||||||
"host": [
|
"host": [
|
||||||
|
|||||||
@ -239,9 +239,37 @@ async function setHolidayHours(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createPosData(req, res) {
|
async function createPosData(req, res) {
|
||||||
|
const allowedCustomerRequestsSchema = z
|
||||||
|
.object({
|
||||||
|
allow_single_use_items_requests: z.boolean().optional(),
|
||||||
|
allow_special_instruction_requests: z.boolean().optional()
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
|
const webhooksConfigSchema = z
|
||||||
|
.object({
|
||||||
|
order_release_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
schedule_order_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
delivery_status_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
webhooks_version: z.string().optional()
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
|
const posDataSchema = z.object({
|
||||||
|
allowed_customer_requests: allowedCustomerRequestsSchema,
|
||||||
|
integrator_brand_id: z.string().optional(),
|
||||||
|
integrator_store_id: z.string().optional(),
|
||||||
|
is_order_manager: z.boolean().optional(),
|
||||||
|
merchant_store_id: z.string().optional(),
|
||||||
|
require_manual_acceptance: z.boolean().optional(),
|
||||||
|
store_configuration_data: z.string().optional(),
|
||||||
|
webhooks_config: webhooksConfigSchema,
|
||||||
|
integration_enabled: z.boolean().optional()
|
||||||
|
});
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
merchantId: z.string().min(1),
|
merchantId: z.string().min(1),
|
||||||
posData: z.any()
|
posData: posDataSchema
|
||||||
});
|
});
|
||||||
const payload = schema.parse(req.body);
|
const payload = schema.parse(req.body);
|
||||||
const data = await proxyService.createPosData({
|
const data = await proxyService.createPosData({
|
||||||
@ -252,14 +280,51 @@ async function createPosData(req, res) {
|
|||||||
return res.json({ success: true, data });
|
return res.json({ success: true, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getPosData(req, res) {
|
||||||
|
const data = await proxyService.getPosData({
|
||||||
|
storeId: req.params.storeId
|
||||||
|
});
|
||||||
|
return res.json({ success: true, data });
|
||||||
|
}
|
||||||
|
|
||||||
async function patchPosData(req, res) {
|
async function patchPosData(req, res) {
|
||||||
|
const allowedCustomerRequestsSchema = z
|
||||||
|
.object({
|
||||||
|
allow_single_use_items_requests: z.boolean().optional(),
|
||||||
|
allow_special_instruction_requests: z.boolean().optional()
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
|
const webhooksConfigSchema = z
|
||||||
|
.object({
|
||||||
|
order_release_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
schedule_order_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
delivery_status_webhooks: z.record(z.string(), z.any()).optional(),
|
||||||
|
webhooks_version: z.string().optional()
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
|
const posDataSchema = z
|
||||||
|
.object({
|
||||||
|
allowed_customer_requests: allowedCustomerRequestsSchema,
|
||||||
|
integrator_brand_id: z.string().optional(),
|
||||||
|
integrator_store_id: z.string().optional(),
|
||||||
|
is_order_manager: z.boolean().optional(),
|
||||||
|
merchant_store_id: z.string().optional(),
|
||||||
|
require_manual_acceptance: z.boolean().optional(),
|
||||||
|
store_configuration_data: z.string().optional(),
|
||||||
|
webhooks_config: webhooksConfigSchema,
|
||||||
|
integration_enabled: z.boolean().optional()
|
||||||
|
})
|
||||||
|
.refine((value) => Object.keys(value).length > 0, {
|
||||||
|
message: "posData must include at least one updatable field"
|
||||||
|
});
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
merchantId: z.string().min(1),
|
posData: posDataSchema
|
||||||
posData: z.any()
|
|
||||||
});
|
});
|
||||||
const payload = schema.parse(req.body);
|
const payload = schema.parse(req.body);
|
||||||
const data = await proxyService.patchPosData({
|
const data = await proxyService.patchPosData({
|
||||||
merchantId: payload.merchantId,
|
|
||||||
storeId: req.params.storeId,
|
storeId: req.params.storeId,
|
||||||
payload: payload.posData
|
payload: payload.posData
|
||||||
});
|
});
|
||||||
@ -267,12 +332,7 @@ async function patchPosData(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deletePosData(req, res) {
|
async function deletePosData(req, res) {
|
||||||
const schema = z.object({
|
|
||||||
merchantId: z.string().min(1)
|
|
||||||
});
|
|
||||||
const payload = schema.parse(req.body);
|
|
||||||
const data = await proxyService.deletePosData({
|
const data = await proxyService.deletePosData({
|
||||||
merchantId: payload.merchantId,
|
|
||||||
storeId: req.params.storeId
|
storeId: req.params.storeId
|
||||||
});
|
});
|
||||||
return res.json({ success: true, data });
|
return res.json({ success: true, data });
|
||||||
@ -298,6 +358,7 @@ module.exports = {
|
|||||||
getHolidayHours,
|
getHolidayHours,
|
||||||
setHolidayHours,
|
setHolidayHours,
|
||||||
createPosData,
|
createPosData,
|
||||||
|
getPosData,
|
||||||
patchPosData,
|
patchPosData,
|
||||||
deletePosData
|
deletePosData
|
||||||
};
|
};
|
||||||
|
|||||||
@ -354,28 +354,37 @@ async function createPosData({ merchantId, storeId, payload }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function patchPosData({ merchantId, storeId, payload }) {
|
async function getPosData({ storeId }) {
|
||||||
|
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
|
||||||
|
return callUberApi({
|
||||||
|
method: "GET",
|
||||||
|
uberPath,
|
||||||
|
wrapperRoute: "/api/v1/uber/stores/:storeId/pos-data",
|
||||||
|
authMode: "app",
|
||||||
|
scopes: AUTH_SCOPES.STORE
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function patchPosData({ storeId, payload }) {
|
||||||
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
|
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
|
||||||
return callUberApi({
|
return callUberApi({
|
||||||
merchantId,
|
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
uberPath,
|
uberPath,
|
||||||
body: payload,
|
body: payload,
|
||||||
wrapperRoute: "/api/v1/uber/stores/:storeId/pos-data",
|
wrapperRoute: "/api/v1/uber/stores/:storeId/pos-data",
|
||||||
authMode: "merchant",
|
authMode: "app",
|
||||||
scopes: AUTH_SCOPES.POS_PROVISIONING
|
scopes: AUTH_SCOPES.STORE
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deletePosData({ merchantId, storeId }) {
|
async function deletePosData({ storeId }) {
|
||||||
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
|
const uberPath = interpolatePath(uberEndpoints.stores.posData, { storeId });
|
||||||
return callUberApi({
|
return callUberApi({
|
||||||
merchantId,
|
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
uberPath,
|
uberPath,
|
||||||
wrapperRoute: "/api/v1/uber/stores/:storeId/pos-data",
|
wrapperRoute: "/api/v1/uber/stores/:storeId/pos-data",
|
||||||
authMode: "merchant",
|
authMode: "app",
|
||||||
scopes: AUTH_SCOPES.POS_PROVISIONING
|
scopes: AUTH_SCOPES.STORE
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,6 +408,7 @@ module.exports = {
|
|||||||
getHolidayHours,
|
getHolidayHours,
|
||||||
setHolidayHours,
|
setHolidayHours,
|
||||||
createPosData,
|
createPosData,
|
||||||
|
getPosData,
|
||||||
patchPosData,
|
patchPosData,
|
||||||
deletePosData
|
deletePosData
|
||||||
};
|
};
|
||||||
|
|||||||
@ -307,6 +307,19 @@ router.put("/uber/stores/hours", asyncHandler(controller.updateHours));
|
|||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Store provisioned
|
* description: Store provisioned
|
||||||
|
* get:
|
||||||
|
* summary: Retrieve integration configuration for selected store (GET /pos_data)
|
||||||
|
* tags:
|
||||||
|
* - Uber Provisioning
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: storeId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Store integration configuration retrieved
|
||||||
* patch:
|
* patch:
|
||||||
* summary: Update integration settings for selected store (PATCH /pos_data)
|
* summary: Update integration settings for selected store (PATCH /pos_data)
|
||||||
* tags:
|
* tags:
|
||||||
@ -335,6 +348,7 @@ router.put("/uber/stores/hours", asyncHandler(controller.updateHours));
|
|||||||
* description: Store integration removed
|
* description: Store integration removed
|
||||||
*/
|
*/
|
||||||
router.post("/uber/stores/:storeId/pos-data", asyncHandler(controller.createPosData));
|
router.post("/uber/stores/:storeId/pos-data", asyncHandler(controller.createPosData));
|
||||||
|
router.get("/uber/stores/:storeId/pos-data", asyncHandler(controller.getPosData));
|
||||||
router.patch("/uber/stores/:storeId/pos-data", asyncHandler(controller.patchPosData));
|
router.patch("/uber/stores/:storeId/pos-data", asyncHandler(controller.patchPosData));
|
||||||
router.delete("/uber/stores/:storeId/pos-data", asyncHandler(controller.deletePosData));
|
router.delete("/uber/stores/:storeId/pos-data", asyncHandler(controller.deletePosData));
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user