tango-app-api-audio-analytics 1.0.0

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.
package/COHORT_API.md ADDED
@@ -0,0 +1,513 @@
1
+ # Cohort API Documentation
2
+
3
+ ## Overview
4
+ The Cohort API manages cohort creation, retrieval, and analytics for the Tango Audio Analytics system. Cohorts are templates that define specific evaluation criteria and metrics for analyzing audio conversations.
5
+
6
+ ## Base URL
7
+ ```
8
+ https://testtangoretail-api.tangoeye.ai/v3/audio-analitics
9
+ ```
10
+
11
+ ## Database
12
+ - **Search Engine**: OpenSearch
13
+ - **Index Name**: `tango-audio-cohort`
14
+ - **Document ID**: Auto-generated UUID
15
+
16
+ ## Validation
17
+ All requests are validated using Joi schema validation from the `tango-app-api-middleware` package.
18
+
19
+ ---
20
+
21
+ ## Endpoints
22
+
23
+ ### 1. Create Cohort
24
+ Create a new cohort with defined metrics and contexts.
25
+
26
+ **Endpoint**
27
+ ```
28
+ POST /cohorts
29
+ ```
30
+
31
+ **Request Body**
32
+ ```json
33
+ {
34
+ "clientId": "11",
35
+ "cohortId": "cohort_photochromatic_001",
36
+ "cohortName": "Photochromatic",
37
+ "cohortDescription": "A strict evaluation of the photochromatic sales journey, focusing on pitch quality, technical accuracy, and customer sentiment",
38
+ "metrics": [
39
+ {
40
+ "metricId": "pitch_quality_001",
41
+ "metricName": "Standard Pitch Quality",
42
+ "metricDescription": "Identify which specific value propositions were explicitly used by the staff",
43
+ "hasContext": true,
44
+ "isNumneric": false,
45
+ "contexts": [
46
+ {
47
+ "contextName": "ONE_GLASS_ALL_NEEDS",
48
+ "priority": 2,
49
+ "description": "Convenience of one pair for all lighting"
50
+ },
51
+ {
52
+ "contextName": "TRAVEL_CONVENIENCE",
53
+ "priority": 2,
54
+ "description": "Specific benefits for bikers/commuters"
55
+ },
56
+ {
57
+ "contextName": "LIGHT_ADAPTATION",
58
+ "priority": 2,
59
+ "description": "Technical explanation of UV reaction"
60
+ },
61
+ {
62
+ "contextName": "REDUCES_EYE_STRAIN",
63
+ "priority": 2,
64
+ "description": "Glare and fatigue protection"
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ "metricId": "technical_depth_score_001",
70
+ "metricName": "Technical Depth Score",
71
+ "metricDescription": "A numeric evaluation of the staff's product knowledge during the pitch",
72
+ "hasContext": true,
73
+ "isNumneric": true,
74
+ "contexts": [
75
+ {
76
+ "minValue": 0,
77
+ "maxValue": 100
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "metricId": "customer_sentiment_001",
83
+ "metricName": "Initial Customer Sentiment",
84
+ "metricDescription": "The immediate reaction of the customer when the lens was introduced",
85
+ "hasContext": true,
86
+ "isNumneric": false,
87
+ "contexts": [
88
+ {
89
+ "contextName": "POSITIVE",
90
+ "priority": 2,
91
+ "description": "High interest or curiosity"
92
+ },
93
+ {
94
+ "contextName": "NEUTRAL",
95
+ "priority": 1,
96
+ "description": "Acknowledgment or price-focused only"
97
+ },
98
+ {
99
+ "contextName": "NEGATIVE",
100
+ "priority": 0,
101
+ "description": "Dismissive or disinterested"
102
+ }
103
+ ]
104
+ },
105
+ {
106
+ "metricId": "staff_responsiveness_001",
107
+ "metricName": "Staff Responsiveness",
108
+ "metricDescription": "How effectively were customer doubts addressed?",
109
+ "hasContext": true,
110
+ "isNumneric": false,
111
+ "contexts": [
112
+ {
113
+ "contextName": "FULLY_RESPONSIVE",
114
+ "priority": 2,
115
+ "description": "All doubts cleared with evidence"
116
+ },
117
+ {
118
+ "contextName": "PARTIALLY_RESPONSIVE",
119
+ "priority": 1,
120
+ "description": "Some doubts addressed, others ignored"
121
+ },
122
+ {
123
+ "contextName": "UNRESPONSIVE",
124
+ "priority": 0,
125
+ "description": "Customer doubts were dismissed"
126
+ }
127
+ ]
128
+ },
129
+ {
130
+ "metricId": "sales_outcome_001",
131
+ "metricName": "Final Sales Outcome",
132
+ "metricDescription": "The final commitment level reached at the end of the conversation",
133
+ "hasContext": true,
134
+ "isNumneric": false,
135
+ "contexts": [
136
+ {
137
+ "contextName": "BOUGHT_PHOTOCHROMATIC",
138
+ "priority": 2,
139
+ "description": "Customer agreed to the upgrade"
140
+ },
141
+ {
142
+ "contextName": "BOUGHT_SOMETHING_ELSE",
143
+ "priority": 0,
144
+ "description": "Bought standard lenses/frames only"
145
+ },
146
+ {
147
+ "contextName": "NO_SALE",
148
+ "priority": 0,
149
+ "description": "No purchase commitment"
150
+ }
151
+ ]
152
+ },
153
+ {
154
+ "metricId": "pitch_timing_summary_001",
155
+ "metricName": "Pitch Timing & Context",
156
+ "metricDescription": "Narrative summary of when and how the pitch was introduced",
157
+ "hasContext": false,
158
+ "isNumneric": false
159
+ }
160
+ ]
161
+ }
162
+ ```
163
+
164
+ **Response (201 Created)**
165
+ ```json
166
+ {
167
+ "status": "success",
168
+ "message": "Cohort created successfully",
169
+ "data": {
170
+ "cohortId": "cohort_photochromatic_001",
171
+ "cohortName": "Photochromatic",
172
+ "clientId": "11",
173
+ "documentId": "550e8400-e29b-41d4-a716-446655440000",
174
+ "createdAt": "2026-03-03T10:30:00Z",
175
+ "metricsCount": 6
176
+ },
177
+ "timestamp": "2026-03-03T10:30:00Z"
178
+ }
179
+ ```
180
+
181
+ **Validation Rules**
182
+ - `clientId`: Required, string
183
+ - `cohortId`: Required, string (alphanumeric, hyphens, underscores only)
184
+ - `cohortName`: Required, 3-100 characters
185
+ - `cohortDescription`: Required, 10-500 characters
186
+ - `metrics`: Required, array with 1-50 items
187
+ - Each metric must have: `metricId`, `metricName`, `metricDescription`, `hasContext`, `isNumneric`
188
+
189
+ ---
190
+
191
+ ### 2. Get Cohort by ID
192
+ Retrieve a specific cohort by its cohort ID.
193
+
194
+ **Endpoint**
195
+ ```
196
+ GET /cohorts/:cohortId
197
+ ```
198
+
199
+ **Example**
200
+ ```
201
+ GET /cohorts/cohort_photochromatic_001
202
+ ```
203
+
204
+ **Response (200 OK)**
205
+ ```json
206
+ {
207
+ "status": "success",
208
+ "data": {
209
+ "documentId": "550e8400-e29b-41d4-a716-446655440000",
210
+ "clientId": "11",
211
+ "cohortId": "cohort_photochromatic_001",
212
+ "cohortName": "Photochromatic",
213
+ "cohortDescription": "A strict evaluation...",
214
+ "metrics": [
215
+ {
216
+ "metricId": "pitch_quality_001",
217
+ "metricName": "Standard Pitch Quality",
218
+ "contexts": [...]
219
+ }
220
+ ],
221
+ "createdAt": "2026-03-03T10:30:00Z",
222
+ "updatedAt": "2026-03-03T10:30:00Z"
223
+ },
224
+ "timestamp": "2026-03-03T10:30:00Z"
225
+ }
226
+ ```
227
+
228
+ ---
229
+
230
+ ### 3. Get Cohorts by Client
231
+ Retrieve all cohorts for a specific client with pagination.
232
+
233
+ **Endpoint**
234
+ ```
235
+ GET /cohorts/client/:clientId?limit=10&offset=0
236
+ ```
237
+
238
+ **Query Parameters**
239
+ - `limit` (optional): Results per page (default: 10, max: 100)
240
+ - `offset` (optional): Pagination offset (default: 0)
241
+
242
+ **Example**
243
+ ```
244
+ GET /cohorts/client/11?limit=5&offset=0
245
+ ```
246
+
247
+ **Response (200 OK)**
248
+ ```json
249
+ {
250
+ "status": "success",
251
+ "data": [
252
+ {
253
+ "documentId": "550e8400-e29b-41d4-a716-446655440000",
254
+ "clientId": "11",
255
+ "cohortId": "cohort_photochromatic_001",
256
+ "cohortName": "Photochromatic",
257
+ "createdAt": "2026-03-03T10:30:00Z"
258
+ }
259
+ ],
260
+ "pagination": {
261
+ "total": 15,
262
+ "limit": 5,
263
+ "offset": 0,
264
+ "hasMore": true
265
+ },
266
+ "timestamp": "2026-03-03T10:30:00Z"
267
+ }
268
+ ```
269
+
270
+ ---
271
+
272
+ ### 4. Search Cohorts
273
+ Search for cohorts by multiple criteria (clientId, cohortId, or cohortName).
274
+
275
+ **Endpoint**
276
+ ```
277
+ POST /cohorts/search
278
+ ```
279
+
280
+ **Request Body**
281
+ ```json
282
+ {
283
+ "clientId": "11",
284
+ "cohortName": "Photochrom",
285
+ "limit": 10,
286
+ "offset": 0
287
+ }
288
+ ```
289
+
290
+ **Response (200 OK)**
291
+ ```json
292
+ {
293
+ "status": "success",
294
+ "data": [
295
+ {
296
+ "documentId": "550e8400-e29b-41d4-a716-446655440000",
297
+ "cohortId": "cohort_photochromatic_001",
298
+ "cohortName": "Photochromatic",
299
+ "clientId": "11",
300
+ "createdAt": "2026-03-03T10:30:00Z"
301
+ }
302
+ ],
303
+ "pagination": {
304
+ "total": 1,
305
+ "limit": 10,
306
+ "offset": 0,
307
+ "hasMore": false
308
+ },
309
+ "timestamp": "2026-03-03T10:30:00Z"
310
+ }
311
+ ```
312
+
313
+ ---
314
+
315
+ ### 5. Update Cohort
316
+ Update cohort name, description, or metrics.
317
+
318
+ **Endpoint**
319
+ ```
320
+ PUT /cohorts/:documentId
321
+ ```
322
+
323
+ **Request Body** (Partial update)
324
+ ```json
325
+ {
326
+ "cohortName": "Updated Photochromatic",
327
+ "cohortDescription": "Updated description",
328
+ "metrics": [...]
329
+ }
330
+ ```
331
+
332
+ **Response (200 OK)**
333
+ ```json
334
+ {
335
+ "status": "success",
336
+ "message": "Cohort updated successfully",
337
+ "data": {
338
+ "documentId": "550e8400-e29b-41d4-a716-446655440000",
339
+ "cohortName": "Updated Photochromatic",
340
+ "updatedAt": "2026-03-03T11:00:00Z"
341
+ },
342
+ "timestamp": "2026-03-03T11:00:00Z"
343
+ }
344
+ ```
345
+
346
+ ---
347
+
348
+ ### 6. Delete Cohort
349
+ Delete a cohort from OpenSearch.
350
+
351
+ **Endpoint**
352
+ ```
353
+ DELETE /cohorts/:documentId
354
+ ```
355
+
356
+ **Example**
357
+ ```
358
+ DELETE /cohorts/550e8400-e29b-41d4-a716-446655440000
359
+ ```
360
+
361
+ **Response (200 OK)**
362
+ ```json
363
+ {
364
+ "status": "success",
365
+ "message": "Cohort deleted successfully",
366
+ "timestamp": "2026-03-03T11:00:00Z"
367
+ }
368
+ ```
369
+
370
+ ---
371
+
372
+ ### 7. Get Cohort Analytics
373
+ Retrieve cohort analytics and metrics summary.
374
+
375
+ **Endpoint**
376
+ ```
377
+ GET /cohorts/:cohortId/analytics
378
+ ```
379
+
380
+ **Example**
381
+ ```
382
+ GET /cohorts/cohort_photochromatic_001/analytics
383
+ ```
384
+
385
+ **Response (200 OK)**
386
+ ```json
387
+ {
388
+ "status": "success",
389
+ "data": {
390
+ "cohortId": "cohort_photochromatic_001",
391
+ "cohortName": "Photochromatic",
392
+ "clientId": "11",
393
+ "totalMetrics": 6,
394
+ "metrics": [
395
+ {
396
+ "metricId": "pitch_quality_001",
397
+ "metricName": "Standard Pitch Quality",
398
+ "isNumneric": false,
399
+ "contextCount": 4,
400
+ "contexts": [...]
401
+ }
402
+ ],
403
+ "createdAt": "2026-03-03T10:30:00Z",
404
+ "updatedAt": "2026-03-03T10:30:00Z"
405
+ },
406
+ "timestamp": "2026-03-03T11:00:00Z"
407
+ }
408
+ ```
409
+
410
+ ---
411
+
412
+ ## Error Responses
413
+
414
+ ### 400 Bad Request - Validation Error
415
+ ```json
416
+ {
417
+ "status": "error",
418
+ "message": "Validation failed",
419
+ "code": "VALIDATION_ERROR",
420
+ "details": [
421
+ {
422
+ "field": "cohortName",
423
+ "message": "\"cohortName\" length must be at least 3 characters long",
424
+ "type": "string.min"
425
+ }
426
+ ],
427
+ "timestamp": "2026-03-03T10:30:00Z"
428
+ }
429
+ ```
430
+
431
+ ### 404 Not Found
432
+ ```json
433
+ {
434
+ "status": "error",
435
+ "message": "Cohort not found",
436
+ "code": "COHORT_NOT_FOUND",
437
+ "timestamp": "2026-03-03T10:30:00Z"
438
+ }
439
+ ```
440
+
441
+ ### 409 Conflict - Cohort Already Exists
442
+ ```json
443
+ {
444
+ "status": "error",
445
+ "message": "Cohort with this ID already exists",
446
+ "code": "COHORT_EXISTS",
447
+ "timestamp": "2026-03-03T10:30:00Z"
448
+ }
449
+ ```
450
+
451
+ ### 500 Internal Server Error
452
+ ```json
453
+ {
454
+ "status": "error",
455
+ "message": "Internal server error",
456
+ "code": "INTERNAL_ERROR",
457
+ "timestamp": "2026-03-03T10:30:00Z"
458
+ }
459
+ ```
460
+
461
+ ---
462
+
463
+ ## Data Structure
464
+
465
+ ### Cohort Document
466
+ ```json
467
+ {
468
+ "documentId": "UUID",
469
+ "clientId": "string",
470
+ "cohortId": "string",
471
+ "cohortName": "string",
472
+ "cohortDescription": "string",
473
+ "metrics": [
474
+ {
475
+ "metricId": "string",
476
+ "metricName": "string",
477
+ "metricDescription": "string",
478
+ "hasContext": boolean,
479
+ "isNumneric": boolean,
480
+ "contexts": [...]
481
+ }
482
+ ],
483
+ "isActive": true,
484
+ "version": "1.0",
485
+ "createdAt": "ISO-8601 timestamp",
486
+ "updatedAt": "ISO-8601 timestamp"
487
+ }
488
+ ```
489
+
490
+ ---
491
+
492
+ ## Implementation Notes
493
+
494
+ ### OpenSearch Integration
495
+ - Uses `insert(index, documentId, document)` function from `tango-app-api-middleware`
496
+ - Auto-generates UUID for each document
497
+ - Stores metadata (createdAt, updatedAt, isActive, version)
498
+ - Search operations use Elasticsearch Query DSL
499
+
500
+ ### Validation
501
+ - All requests validated using Joi schemas
502
+ - Custom validation schemas in `src/validations/cohort.validation.js`
503
+ - Validation middleware in `src/middlewares/validation.middleware.js`
504
+
505
+ ### Service Layer
506
+ - Cohort operations in `src/services/cohort.service.js`
507
+ - Handles all OpenSearch CRUD operations
508
+ - Error handling with specific error codes
509
+
510
+ ### Controller Layer
511
+ - API handlers in `src/controllers/cohort.controller.js`
512
+ - Request validation and response formatting
513
+ - Comprehensive logging via `tango-app-api-middleware`