repzo 1.0.289 → 1.0.291

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,349 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Repzo API - Geo Zone
4
+ version: 1.0.0
5
+ description: |
6
+ A **Geo Zone** is a named geographic area defined by a single GeoJSON
7
+ polygon. Zones are assigned to reps (via the rep's `assigned_geo_zones`
8
+ array — currently capped at one zone per rep) so the mobile app can
9
+ enforce location policies — e.g. whether a rep may start the day or
10
+ start a visit while outside their zone.
11
+
12
+ **Who uses it.** Admins manage zones from the back office and assign
13
+ them through the `rep` service. The mobile app reads zones (with the
14
+ incremental `from_updatedAt` cursor) to evaluate policies offline.
15
+
16
+ **Multi-tenancy & lifecycle.** Records are scoped by
17
+ `company_namespace[]` (injected from session — never sent in the body)
18
+ and use **soft-delete** via `disabled: true`. `name` is unique per
19
+ namespace among non-deleted zones. A zone that is still assigned to one
20
+ or more reps **cannot be disabled or deleted** — the request is rejected
21
+ with `400` naming the assigned reps; reassign them first.
22
+
23
+ **Validation.** A zone cannot be saved without a `name` and a valid
24
+ polygon: the polygon needs at least one closed linear ring of 4+
25
+ `[longitude, latitude]` positions (first and last must match, longitude
26
+ in ±180, latitude in ±90). Violations return a `400` naming the failing
27
+ ring.
28
+
29
+ **Key relationships.** Referenced by `rep.assigned_geo_zones`. The
30
+ `editor` audit object (who created / last updated the zone) is stamped
31
+ server-side from the session token.
32
+ servers:
33
+ - url: https://sv.api.repzo.me
34
+ security:
35
+ - ApiKeyAuth: []
36
+ - JwtAuth: []
37
+ paths:
38
+ /geo-zone:
39
+ get:
40
+ summary: Find geo zones
41
+ operationId: findGeoZones
42
+ parameters:
43
+ - in: query
44
+ name: _id
45
+ description: Filter by zone `_id`. Pass once or as `?_id[]=...` for multiple.
46
+ schema:
47
+ oneOf:
48
+ - type: string
49
+ - type: array
50
+ items: { type: string }
51
+ - in: query
52
+ name: name
53
+ description: Exact-match on zone name. Pass once or as `?name[]=...` for multiple.
54
+ schema:
55
+ oneOf:
56
+ - type: string
57
+ - type: array
58
+ items: { type: string }
59
+ - in: query
60
+ name: search
61
+ description: Case-insensitive substring search on `name`.
62
+ schema: { type: string }
63
+ example: north
64
+ - in: query
65
+ name: disabled
66
+ description: Include disabled (soft-deleted) zones. Defaults to `false`.
67
+ schema: { type: boolean, default: false }
68
+ - in: query
69
+ name: inject_assigned_reps
70
+ description: |
71
+ When truthy, each returned zone is enriched with an
72
+ `assigned_reps[]` array (`_id`, `name`) of the active reps whose
73
+ `assigned_geo_zones` contains it.
74
+ schema: { type: boolean, default: false }
75
+ - in: query
76
+ name: from_updatedAt
77
+ description: Cursor — zones updated on or after this Unix timestamp (ms). Used by the mobile app for incremental sync.
78
+ schema: { type: number }
79
+ - in: query
80
+ name: to_updatedAt
81
+ description: Cursor — zones updated on or before this Unix timestamp (ms).
82
+ schema: { type: number }
83
+ - in: query
84
+ name: from_createdAt
85
+ description: Cursor — zones created on or after this Unix timestamp (ms).
86
+ schema: { type: number }
87
+ - in: query
88
+ name: to_createdAt
89
+ description: Cursor — zones created on or before this Unix timestamp (ms).
90
+ schema: { type: number }
91
+ - in: query
92
+ name: per_page
93
+ description: Page size. Defaults to the server's configured pagination limit.
94
+ schema: { type: integer, minimum: 1, maximum: 500 }
95
+ example: 50
96
+ - in: query
97
+ name: page
98
+ description: 1-indexed page number.
99
+ schema: { type: integer, minimum: 1 }
100
+ example: 1
101
+ responses:
102
+ "200":
103
+ description: A paginated list of geo zones matching the filter.
104
+ content:
105
+ application/json:
106
+ schema:
107
+ $ref: "#/components/schemas/GeoZoneFindResult"
108
+ post:
109
+ summary: Create a geo zone
110
+ operationId: createGeoZone
111
+ requestBody:
112
+ required: true
113
+ content:
114
+ application/json:
115
+ schema:
116
+ $ref: "#/components/schemas/GeoZoneCreateBody"
117
+ responses:
118
+ "201":
119
+ description: The newly-created geo zone. `editor` is stamped from the session token.
120
+ content:
121
+ application/json:
122
+ schema:
123
+ $ref: "#/components/schemas/GeoZoneSchema"
124
+ "400":
125
+ description: |
126
+ Validation failure — missing `name`, missing polygon, or an
127
+ invalid polygon (open ring, fewer than 4 positions, out-of-range
128
+ coordinates). The message names the failing ring. Also returned
129
+ when the zone name already exists in the namespace.
130
+ /geo-zone/{id}:
131
+ get:
132
+ summary: Get a geo zone by ID
133
+ operationId: getGeoZone
134
+ parameters:
135
+ - in: path
136
+ name: id
137
+ required: true
138
+ schema: { type: string }
139
+ - in: query
140
+ name: inject_assigned_reps
141
+ description: When truthy, the zone is enriched with an `assigned_reps[]` array (`_id`, `name`).
142
+ schema: { type: boolean, default: false }
143
+ responses:
144
+ "200":
145
+ description: The geo zone document for the given `_id`.
146
+ content:
147
+ application/json:
148
+ schema:
149
+ $ref: "#/components/schemas/GeoZoneSchema"
150
+ put:
151
+ summary: Update a geo zone
152
+ operationId: updateGeoZone
153
+ description: |
154
+ Partial update — only the fields present in the body are changed.
155
+ `polygon`, when sent, replaces the zone's polygon and is validated
156
+ like create. Setting `disabled: true` deactivates the zone and is
157
+ **rejected with `400` while any rep is still assigned to it**;
158
+ reassign those reps first.
159
+ parameters:
160
+ - in: path
161
+ name: id
162
+ required: true
163
+ schema: { type: string }
164
+ requestBody:
165
+ required: true
166
+ content:
167
+ application/json:
168
+ schema:
169
+ $ref: "#/components/schemas/GeoZoneUpdateBody"
170
+ responses:
171
+ "200":
172
+ description: The geo zone document after the update is applied.
173
+ content:
174
+ application/json:
175
+ schema:
176
+ $ref: "#/components/schemas/GeoZoneSchema"
177
+ "400":
178
+ description: Zone not found, polygon validation failure, or the zone is being disabled while reps are still assigned to it.
179
+ delete:
180
+ summary: Remove a geo zone (soft-delete)
181
+ operationId: removeGeoZone
182
+ description: |
183
+ Soft-deletes the zone (`disabled: true`). Rejected with `400` while
184
+ any rep is still assigned to it — the error names the assigned reps;
185
+ reassign them to another zone first.
186
+ parameters:
187
+ - in: path
188
+ name: id
189
+ required: true
190
+ schema: { type: string }
191
+ responses:
192
+ "200":
193
+ description: "The geo zone document after soft-deletion (`disabled: true`)."
194
+ content:
195
+ application/json:
196
+ schema:
197
+ $ref: "#/components/schemas/GeoZoneSchema"
198
+ "400":
199
+ description: Zone not found, or the zone is still assigned to one or more reps.
200
+ components:
201
+ securitySchemes:
202
+ ApiKeyAuth:
203
+ type: apiKey
204
+ in: header
205
+ name: api-key
206
+ description: |
207
+ Server-issued API key. Also accepted via the `x-api-key` header or the
208
+ `?apiKey=` query parameter as fallbacks.
209
+ JwtAuth:
210
+ type: apiKey
211
+ in: header
212
+ name: Authorization
213
+ description: |
214
+ Raw JWT in the `Authorization` header — **no `Bearer ` prefix**. Obtained from
215
+ `POST /authenticate` (admin / rep / client login).
216
+ schemas:
217
+ GeoZoneFindResult:
218
+ type: object
219
+ description: Paginated list of geo zones.
220
+ properties:
221
+ data:
222
+ type: array
223
+ items:
224
+ $ref: "#/components/schemas/GeoZoneSchema"
225
+ total_result: { type: number }
226
+ current_count: { type: number }
227
+ total_pages: { type: number }
228
+ current_page: { type: number }
229
+ per_page: { type: number }
230
+ first_page_url: { type: string }
231
+ last_page_url: { type: string }
232
+ next_page_url: { type: string, nullable: true }
233
+ prev_page_url: { type: string, nullable: true }
234
+ path: { type: string }
235
+ GeoZoneSchema:
236
+ type: object
237
+ description: Geo zone document as stored.
238
+ properties:
239
+ _id: { type: string }
240
+ name:
241
+ {
242
+ type: string,
243
+ description: Unique per namespace among non-deleted zones.,
244
+ }
245
+ description: { type: string }
246
+ polygon:
247
+ $ref: "#/components/schemas/GeoZonePolygon"
248
+ disabled:
249
+ { type: boolean, description: Soft-delete / deactivation flag. }
250
+ editor:
251
+ $ref: "#/components/schemas/GeoZoneEditor"
252
+ assigned_reps:
253
+ type: array
254
+ description: "Present only when the request sent `inject_assigned_reps=true` — the active reps assigned to this zone."
255
+ items:
256
+ type: object
257
+ properties:
258
+ _id: { type: string }
259
+ name: { type: string }
260
+ company_namespace:
261
+ type: array
262
+ items: { type: string }
263
+ description: Tenant key set on save from session.
264
+ createdAt: { type: string, format: date-time }
265
+ updatedAt: { type: string, format: date-time }
266
+ __v: { type: number }
267
+ GeoZonePolygon:
268
+ type: object
269
+ description: |
270
+ A GeoJSON Polygon. `coordinates` is an array of linear rings; the
271
+ first ring is the outer boundary, any further rings are holes.
272
+ required: [coordinates]
273
+ properties:
274
+ type:
275
+ type: string
276
+ enum: [Polygon]
277
+ default: Polygon
278
+ coordinates:
279
+ type: array
280
+ minItems: 1
281
+ description: |
282
+ Array of linear rings. Each ring is an array of at least 4
283
+ positions and must be closed (first position equals the last).
284
+ Positions are ordered as **longitude, latitude** (longitude
285
+ first) — longitude in [-180, 180], latitude in [-90, 90].
286
+ items:
287
+ type: array
288
+ minItems: 4
289
+ description: "A closed linear ring of `[longitude, latitude]` positions."
290
+ items:
291
+ type: array
292
+ minItems: 2
293
+ maxItems: 2
294
+ items: { type: number }
295
+ example:
296
+ - - [35.910, 31.954]
297
+ - [35.930, 31.954]
298
+ - [35.930, 31.970]
299
+ - [35.910, 31.954]
300
+ GeoZoneEditor:
301
+ type: object
302
+ description: Audit stamp of who created / last updated the zone. Set server-side from the session token — never sent by the client.
303
+ properties:
304
+ _id: { type: string }
305
+ type: { type: string, enum: [admin, rep, tenant, client] }
306
+ name: { type: string }
307
+ rep: { type: string }
308
+ admin: { type: string }
309
+ client: { type: string }
310
+ tenant: { type: string }
311
+ GeoZoneCreateBody:
312
+ type: object
313
+ description: |
314
+ Body for creating a geo zone. The `editor` audit stamp is stamped
315
+ server-side from the session token (not accepted on create). The tenant
316
+ key (`company_namespace`) is normally injected from session and can be
317
+ omitted — it is optional here for integration / cross-namespace callers.
318
+ The soft-delete flag (`disabled`) defaults to `false`.
319
+ required:
320
+ - name
321
+ - polygon
322
+ properties:
323
+ name:
324
+ type: string
325
+ description: Zone name — required and unique per namespace among non-deleted zones.
326
+ description: { type: string }
327
+ polygon:
328
+ $ref: "#/components/schemas/GeoZonePolygon"
329
+ company_namespace:
330
+ type: array
331
+ items: { type: string }
332
+ description: Tenant key — normally injected from session; optional, for cross-namespace callers.
333
+ GeoZoneUpdateBody:
334
+ type: object
335
+ description: |
336
+ Body for updating a geo zone — only the fields present are changed.
337
+ The tenant key (`company_namespace`) is derived from session. The
338
+ `editor` audit stamp is normally refreshed server-side but may be
339
+ provided (optional).
340
+ properties:
341
+ name: { type: string }
342
+ description: { type: string }
343
+ polygon:
344
+ $ref: "#/components/schemas/GeoZonePolygon"
345
+ disabled:
346
+ type: boolean
347
+ description: "Soft-delete / deactivation flag. Setting `true` is rejected while any rep is still assigned to this zone."
348
+ editor:
349
+ $ref: "#/components/schemas/GeoZoneEditor"
package/src/oas/rep.yaml CHANGED
@@ -106,6 +106,13 @@ paths:
106
106
  items:
107
107
  type: string
108
108
  - type: string
109
+ assigned_geo_zones:
110
+ description: Filter by assigned geo-zone `_id`s.
111
+ oneOf:
112
+ - type: array
113
+ items:
114
+ type: string
115
+ - type: string
109
116
  lines:
110
117
  oneOf:
111
118
  - type: array
@@ -140,6 +147,12 @@ paths:
140
147
  items:
141
148
  type: string
142
149
  - type: string
150
+ assigned_shift:
151
+ oneOf:
152
+ - type: array
153
+ items:
154
+ type: string
155
+ - type: string
143
156
  media:
144
157
  oneOf:
145
158
  - type: array
@@ -164,6 +177,8 @@ paths:
164
177
  "cover_photo",
165
178
  "assigned_plan",
166
179
  "assigned_retail_execution_templates",
180
+ "assigned_geo_zones",
181
+ "assigned_shift",
167
182
  "warehouse",
168
183
  ]
169
184
  withProductLines:
@@ -285,6 +300,10 @@ paths:
285
300
  type: boolean
286
301
  "permissions.rep_can_create_skip_geofence_at_visit_end_approval_request":
287
302
  type: boolean
303
+ "permissions.rep_can_start_visit_out_of_geofence":
304
+ type: boolean
305
+ "permissions.rep_can_create_approval_request_to_start_visit_out_of_geofence":
306
+ type: boolean
288
307
  "permissions.rep_can_create_credit_invoice_for_cash_client":
289
308
  type: boolean
290
309
  "permissions.rep_can_view_client_credit_limit":
@@ -317,6 +336,12 @@ paths:
317
336
  type: boolean
318
337
  "permissions.rep_must_end_day_after_specific_time":
319
338
  type: boolean
339
+ "permissions.rep_must_start_day_within_shift_window":
340
+ type: boolean
341
+ "permissions.rep_must_end_day_within_shift_window":
342
+ type: boolean
343
+ "permissions.rep_can_start_day_on_non_working_day":
344
+ type: boolean
320
345
  "permissions.rep_can_create_negative_invoice":
321
346
  type: boolean
322
347
  "settings.rep_must_end_day_after":
@@ -348,6 +373,12 @@ paths:
348
373
  type: boolean
349
374
  "settings.watermark_coordinates":
350
375
  type: boolean
376
+ "settings.start_day_minutes_before_shift_start":
377
+ type: number
378
+ "settings.start_day_minutes_after_shift_start":
379
+ type: number
380
+ "settings.end_day_minutes_before_shift_end":
381
+ type: number
351
382
  description: Query parameters for filtering reps
352
383
  responses:
353
384
  "200":
@@ -672,6 +703,12 @@ components:
672
703
  rep_can_create_skip_geofence_at_visit_end_approval_request:
673
704
  type: boolean
674
705
  description: Can rep create skip geofence at visit end approval request
706
+ rep_can_start_visit_out_of_geofence:
707
+ type: boolean
708
+ description: Can rep start a visit while outside their geofence / geo zone
709
+ rep_can_create_approval_request_to_start_visit_out_of_geofence:
710
+ type: boolean
711
+ description: Can rep create an approval request to start a visit while out of geofence
675
712
  rep_can_create_credit_invoice_for_cash_client:
676
713
  type: boolean
677
714
  description: Can rep create credit invoice for cash client
@@ -720,6 +757,15 @@ components:
720
757
  rep_must_end_day_after_specific_time:
721
758
  type: boolean
722
759
  description: Rep must end day after specific time
760
+ rep_must_start_day_within_shift_window:
761
+ type: boolean
762
+ description: When true, the rep may only open the day within the configured window around the assigned shift start.
763
+ rep_must_end_day_within_shift_window:
764
+ type: boolean
765
+ description: When true, the rep may only end the day from the configured offset before the assigned shift end.
766
+ rep_can_start_day_on_non_working_day:
767
+ type: boolean
768
+ description: When false, opening a day on an assigned-shift day off is rejected.
723
769
  rep_can_create_negative_invoice:
724
770
  type: boolean
725
771
  description: Rep can create negative invoice
@@ -785,6 +831,11 @@ components:
785
831
  items:
786
832
  type: string
787
833
  description: Assigned targets
834
+ assigned_geo_zones:
835
+ type: array
836
+ items:
837
+ type: string
838
+ description: "`_id`s of the geo zones assigned to this rep (ref `geo-zone`) — currently at most one."
788
839
  lines:
789
840
  type: array
790
841
  items:
@@ -838,6 +889,10 @@ components:
838
889
  items:
839
890
  type: string
840
891
  description: Assigned retail execution templates
892
+ assigned_shift:
893
+ type: string
894
+ nullable: true
895
+ description: "`_id` of the day-shift assigned to this rep (ref `day-shift`). `null` when unassigned."
841
896
  customFields:
842
897
  type: object
843
898
  additionalProperties:
@@ -903,6 +958,24 @@ components:
903
958
  type: string
904
959
  pattern: "^[0-9]{1,2}:[0-9]{2}$"
905
960
  description: Time rep must end day after (HH:MM format)
961
+ start_day_minutes_before_shift_start:
962
+ type: number
963
+ minimum: 0
964
+ maximum: 240
965
+ default: 0
966
+ description: Minutes before the assigned shift start from which the rep may open the day.
967
+ start_day_minutes_after_shift_start:
968
+ type: number
969
+ minimum: 0
970
+ maximum: 240
971
+ default: 0
972
+ description: Minutes after the assigned shift start until which the rep may open the day when shift-window enforcement is enabled.
973
+ end_day_minutes_before_shift_end:
974
+ type: number
975
+ minimum: 0
976
+ maximum: 240
977
+ default: 0
978
+ description: Minutes before the assigned shift end from which the rep may close the day when shift-window enforcement is enabled.
906
979
  integration_meta:
907
980
  type: object
908
981
  additionalProperties: true
@@ -1122,6 +1195,12 @@ components:
1122
1195
  rep_can_create_skip_geofence_at_visit_end_approval_request:
1123
1196
  type: boolean
1124
1197
  description: Can rep create skip geofence at visit end approval request
1198
+ rep_can_start_visit_out_of_geofence:
1199
+ type: boolean
1200
+ description: Can rep start a visit while outside their geofence / geo zone
1201
+ rep_can_create_approval_request_to_start_visit_out_of_geofence:
1202
+ type: boolean
1203
+ description: Can rep create an approval request to start a visit while out of geofence
1125
1204
  rep_can_create_credit_invoice_for_cash_client:
1126
1205
  type: boolean
1127
1206
  description: Can rep create credit invoice for cash client
@@ -1170,6 +1249,15 @@ components:
1170
1249
  rep_must_end_day_after_specific_time:
1171
1250
  type: boolean
1172
1251
  description: Rep must end day after specific time
1252
+ rep_must_start_day_within_shift_window:
1253
+ type: boolean
1254
+ description: When true, the rep may only open the day within the configured window around the assigned shift start.
1255
+ rep_must_end_day_within_shift_window:
1256
+ type: boolean
1257
+ description: When true, the rep may only end the day from the configured offset before the assigned shift end.
1258
+ rep_can_start_day_on_non_working_day:
1259
+ type: boolean
1260
+ description: When false, opening a day on an assigned-shift day off is rejected.
1173
1261
  rep_can_create_negative_invoice:
1174
1262
  type: boolean
1175
1263
  description: Rep can create negative invoice
@@ -1235,6 +1323,11 @@ components:
1235
1323
  items:
1236
1324
  type: string
1237
1325
  description: Assigned targets
1326
+ assigned_geo_zones:
1327
+ type: array
1328
+ items:
1329
+ type: string
1330
+ description: "`_id`s of the geo zones assigned to this rep (ref `geo-zone`) — currently at most one."
1238
1331
  lines:
1239
1332
  type: array
1240
1333
  items:
@@ -1288,6 +1381,10 @@ components:
1288
1381
  items:
1289
1382
  type: string
1290
1383
  description: Assigned retail execution templates
1384
+ assigned_shift:
1385
+ type: string
1386
+ nullable: true
1387
+ description: "`_id` of the day-shift to assign to this rep (ref `day-shift`). Must reference an existing, active shift in the caller's namespace. Send `null` to clear the assignment."
1291
1388
  customFields:
1292
1389
  type: object
1293
1390
  additionalProperties:
@@ -1353,6 +1450,24 @@ components:
1353
1450
  type: string
1354
1451
  pattern: "^[0-9]{1,2}:[0-9]{2}$"
1355
1452
  description: Time rep must end day after (HH:MM format)
1453
+ start_day_minutes_before_shift_start:
1454
+ type: number
1455
+ minimum: 0
1456
+ maximum: 240
1457
+ default: 0
1458
+ description: Minutes before the assigned shift start from which the rep may open the day.
1459
+ start_day_minutes_after_shift_start:
1460
+ type: number
1461
+ minimum: 0
1462
+ maximum: 240
1463
+ default: 0
1464
+ description: Minutes after the assigned shift start until which the rep may open the day when shift-window enforcement is enabled.
1465
+ end_day_minutes_before_shift_end:
1466
+ type: number
1467
+ minimum: 0
1468
+ maximum: 240
1469
+ default: 0
1470
+ description: Minutes before the assigned shift end from which the rep may close the day when shift-window enforcement is enabled.
1356
1471
  integration_meta:
1357
1472
  type: object
1358
1473
  additionalProperties: true
@@ -1562,6 +1677,12 @@ components:
1562
1677
  rep_can_create_skip_geofence_at_visit_end_approval_request:
1563
1678
  type: boolean
1564
1679
  description: Can rep create skip geofence at visit end approval request
1680
+ rep_can_start_visit_out_of_geofence:
1681
+ type: boolean
1682
+ description: Can rep start a visit while outside their geofence / geo zone
1683
+ rep_can_create_approval_request_to_start_visit_out_of_geofence:
1684
+ type: boolean
1685
+ description: Can rep create an approval request to start a visit while out of geofence
1565
1686
  rep_can_create_credit_invoice_for_cash_client:
1566
1687
  type: boolean
1567
1688
  description: Can rep create credit invoice for cash client
@@ -1610,6 +1731,15 @@ components:
1610
1731
  rep_must_end_day_after_specific_time:
1611
1732
  type: boolean
1612
1733
  description: Rep must end day after specific time
1734
+ rep_must_start_day_within_shift_window:
1735
+ type: boolean
1736
+ description: When true, the rep may only open the day within the configured window around the assigned shift start.
1737
+ rep_must_end_day_within_shift_window:
1738
+ type: boolean
1739
+ description: When true, the rep may only end the day from the configured offset before the assigned shift end.
1740
+ rep_can_start_day_on_non_working_day:
1741
+ type: boolean
1742
+ description: When false, opening a day on an assigned-shift day off is rejected.
1613
1743
  rep_can_create_negative_invoice:
1614
1744
  type: boolean
1615
1745
  description: Rep can create negative invoice
@@ -1675,6 +1805,11 @@ components:
1675
1805
  items:
1676
1806
  type: string
1677
1807
  description: Assigned targets
1808
+ assigned_geo_zones:
1809
+ type: array
1810
+ items:
1811
+ type: string
1812
+ description: "`_id`s of the geo zones assigned to this rep (ref `geo-zone`) — currently at most one."
1678
1813
  lines:
1679
1814
  type: array
1680
1815
  items:
@@ -1728,6 +1863,10 @@ components:
1728
1863
  items:
1729
1864
  type: string
1730
1865
  description: Assigned retail execution templates
1866
+ assigned_shift:
1867
+ type: string
1868
+ nullable: true
1869
+ description: "`_id` of the day-shift to assign to this rep (ref `day-shift`). Must reference an existing, active shift in the caller's namespace. Send `null` to clear the assignment."
1731
1870
  customFields:
1732
1871
  type: object
1733
1872
  additionalProperties:
@@ -1793,6 +1932,24 @@ components:
1793
1932
  type: string
1794
1933
  pattern: "^[0-9]{1,2}:[0-9]{2}$"
1795
1934
  description: Time rep must end day after (HH:MM format)
1935
+ start_day_minutes_before_shift_start:
1936
+ type: number
1937
+ minimum: 0
1938
+ maximum: 240
1939
+ default: 0
1940
+ description: Minutes before the assigned shift start from which the rep may open the day.
1941
+ start_day_minutes_after_shift_start:
1942
+ type: number
1943
+ minimum: 0
1944
+ maximum: 240
1945
+ default: 0
1946
+ description: Minutes after the assigned shift start until which the rep may open the day when shift-window enforcement is enabled.
1947
+ end_day_minutes_before_shift_end:
1948
+ type: number
1949
+ minimum: 0
1950
+ maximum: 240
1951
+ default: 0
1952
+ description: Minutes before the assigned shift end from which the rep may close the day when shift-window enforcement is enabled.
1796
1953
  integration_meta:
1797
1954
  type: object
1798
1955
  additionalProperties: true