@vitrina/api 11.42.0 → 11.44.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.
Files changed (3) hide show
  1. package/dist/index.d.cts +2529 -424
  2. package/dist/index.d.ts +2529 -424
  3. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -16350,7 +16350,7 @@ interface paths {
16350
16350
  };
16351
16351
  /**
16352
16352
  * A vehicle's change history (Historial)
16353
- * @description Reverse-chronological audit trail for this vehicle — created, field edits (with a before→after diff), publish/unpublish/cierre, and Override local protect/release — with teammate actors resolved to display names. The UI merges it with /activity (leads) into one "Leads y cambios" timeline.
16353
+ * @description Reverse-chronological audit trail for this vehicle — created, field edits (with a before→after diff), publish/unpublish/cierre, and Override local protect/release — with teammate actors resolved to display names. It also carries the deal's milestones, read from each document's own audit rows: nota de compra emitted/voided (`purchase_note_issued`, `purchase_note_voided`), nota de venta emitted/approved/voided (`sale_note_issued`, `sale_note_approved`, `sale_note_voided`), contrato de compraventa first printed (`compraventa_printed`), mandato de consignación first printed (`mandato_issued`), a signed copy filed (`signed_copy_filed`, with `metadata.signed_document_type`) and the liquidación paid to the consignor (`liquidacion_paid`). `metadata.folio` names the document when it has one. Each document type appears only for a caller holding its read scope (`purchase_notes:read`, `sale_notes:read`, `consignments:read`; signed copies also need `vehicle_registry:read`). A download of the Resumen del negocio is `deal_settlement_downloaded`. The UI merges it with /activity (leads) into one "Leads y cambios" timeline.
16354
16354
  */
16355
16355
  get: {
16356
16356
  parameters: {
@@ -16375,6 +16375,22 @@ interface paths {
16375
16375
  * @example {
16376
16376
  * "data": [
16377
16377
  * {
16378
+ * "id": "99999999-0000-4000-8000-000000000005",
16379
+ * "action": "sale_notes.approve",
16380
+ * "kind": "sale_note_approved",
16381
+ * "actor": {
16382
+ * "kind": "user",
16383
+ * "id": "11111111-0000-4000-8000-000000000001",
16384
+ * "name": "Ana Torres"
16385
+ * },
16386
+ * "changes": [],
16387
+ * "metadata": {
16388
+ * "folio": "V-13",
16389
+ * "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001"
16390
+ * },
16391
+ * "at": "2026-09-18T15:02:11.000Z"
16392
+ * },
16393
+ * {
16378
16394
  * "id": "99999999-0000-4000-8000-000000000003",
16379
16395
  * "action": "vehicles.create",
16380
16396
  * "kind": "created",
@@ -19975,6 +19991,15 @@ interface paths {
19975
19991
  * "trade_in_description": null,
19976
19992
  * "offer_amount": null,
19977
19993
  * "offer_note": null,
19994
+ * "financing_term_months": [
19995
+ * 24,
19996
+ * 36
19997
+ * ],
19998
+ * "installment_amount": null,
19999
+ * "max_down_payment_amount": null,
20000
+ * "net_income_amount": 1900000,
20001
+ * "employer": "CGE",
20002
+ * "employment_tenure": "15 años",
19978
20003
  * "deal_terms_meta": {
19979
20004
  * "payment_method": {
19980
20005
  * "source": "ai",
@@ -20054,6 +20079,15 @@ interface paths {
20054
20079
  * "trade_in_description": null,
20055
20080
  * "offer_amount": null,
20056
20081
  * "offer_note": null,
20082
+ * "financing_term_months": [
20083
+ * 24,
20084
+ * 36
20085
+ * ],
20086
+ * "installment_amount": null,
20087
+ * "max_down_payment_amount": null,
20088
+ * "net_income_amount": 1900000,
20089
+ * "employer": "CGE",
20090
+ * "employment_tenure": "15 años",
20057
20091
  * "deal_terms_meta": {
20058
20092
  * "payment_method": {
20059
20093
  * "source": "ai",
@@ -20273,6 +20307,15 @@ interface paths {
20273
20307
  * "trade_in_description": null,
20274
20308
  * "offer_amount": null,
20275
20309
  * "offer_note": null,
20310
+ * "financing_term_months": [
20311
+ * 24,
20312
+ * 36
20313
+ * ],
20314
+ * "installment_amount": null,
20315
+ * "max_down_payment_amount": null,
20316
+ * "net_income_amount": 1900000,
20317
+ * "employer": "CGE",
20318
+ * "employment_tenure": "15 años",
20276
20319
  * "deal_terms_meta": {
20277
20320
  * "payment_method": {
20278
20321
  * "source": "ai",
@@ -20478,6 +20521,15 @@ interface paths {
20478
20521
  * "trade_in_description": null,
20479
20522
  * "offer_amount": null,
20480
20523
  * "offer_note": null,
20524
+ * "financing_term_months": [
20525
+ * 24,
20526
+ * 36
20527
+ * ],
20528
+ * "installment_amount": null,
20529
+ * "max_down_payment_amount": null,
20530
+ * "net_income_amount": 1900000,
20531
+ * "employer": "CGE",
20532
+ * "employment_tenure": "15 años",
20481
20533
  * "deal_terms_meta": {
20482
20534
  * "payment_method": {
20483
20535
  * "source": "ai",
@@ -21193,6 +21245,15 @@ interface paths {
21193
21245
  * "trade_in_description": null,
21194
21246
  * "offer_amount": null,
21195
21247
  * "offer_note": null,
21248
+ * "financing_term_months": [
21249
+ * 24,
21250
+ * 36
21251
+ * ],
21252
+ * "installment_amount": null,
21253
+ * "max_down_payment_amount": null,
21254
+ * "net_income_amount": 1900000,
21255
+ * "employer": "CGE",
21256
+ * "employment_tenure": "15 años",
21196
21257
  * "deal_terms_meta": {
21197
21258
  * "payment_method": {
21198
21259
  * "source": "ai",
@@ -21282,6 +21343,15 @@ interface paths {
21282
21343
  * "trade_in_description": null,
21283
21344
  * "offer_amount": null,
21284
21345
  * "offer_note": null,
21346
+ * "financing_term_months": [
21347
+ * 24,
21348
+ * 36
21349
+ * ],
21350
+ * "installment_amount": null,
21351
+ * "max_down_payment_amount": null,
21352
+ * "net_income_amount": 1900000,
21353
+ * "employer": "CGE",
21354
+ * "employment_tenure": "15 años",
21285
21355
  * "deal_terms_meta": {
21286
21356
  * "payment_method": {
21287
21357
  * "source": "ai",
@@ -21584,6 +21654,15 @@ interface paths {
21584
21654
  * "trade_in_description": null,
21585
21655
  * "offer_amount": null,
21586
21656
  * "offer_note": null,
21657
+ * "financing_term_months": [
21658
+ * 24,
21659
+ * 36
21660
+ * ],
21661
+ * "installment_amount": null,
21662
+ * "max_down_payment_amount": null,
21663
+ * "net_income_amount": 1900000,
21664
+ * "employer": "CGE",
21665
+ * "employment_tenure": "15 años",
21587
21666
  * "deal_terms_meta": {
21588
21667
  * "payment_method": {
21589
21668
  * "source": "ai",
@@ -21781,6 +21860,15 @@ interface paths {
21781
21860
  * "trade_in_description": null,
21782
21861
  * "offer_amount": null,
21783
21862
  * "offer_note": null,
21863
+ * "financing_term_months": [
21864
+ * 24,
21865
+ * 36
21866
+ * ],
21867
+ * "installment_amount": null,
21868
+ * "max_down_payment_amount": null,
21869
+ * "net_income_amount": 1900000,
21870
+ * "employer": "CGE",
21871
+ * "employment_tenure": "15 años",
21784
21872
  * "deal_terms_meta": {
21785
21873
  * "payment_method": {
21786
21874
  * "source": "ai",
@@ -22148,7 +22236,7 @@ interface paths {
22148
22236
  get?: never;
22149
22237
  /**
22150
22238
  * Set a lead's deal terms (human)
22151
- * @description Deal terms are seven nullable, vertical-neutral facts: `payment_method` (`cash` | `financing` | `credit_card` | `debit_card` | `mixed`), `down_payment_amount`, `budget_max_amount`, `offer_amount` (in the lead's `value_currency`), `has_trade_in` (null = unknown, false = none), `trade_in_description`, `offer_note`. Each carries provenance in `deal_terms_meta` (`ai` | `human`); an AI writer never overwrites a human-owned field — a disagreeing AI reading is kept in `deal_terms_suggestions` instead. Every field in the body becomes human-owned (`source: human`, the caller as actor) and its pending suggestion is removed; `null` clears a value but keeps it human-owned, so the next AI read proposes instead of re-filling it. Accepting a suggestion is this call with the suggested value. Changes land on the lead's timeline as `deal_terms_changed`. Returns the Oportunidad `lead` object. `{id}` accepts the lead uuid or its ID visible (`L-89`) — the label is a lookup shortcut on the path only, never a value to store.
22239
+ * @description Deal terms are thirteen nullable, vertical-neutral facts: `payment_method` (`cash` | `financing` | `credit_card` | `debit_card` | `mixed`), `down_payment_amount`, `budget_max_amount`, `offer_amount` (in the lead's `value_currency`), `has_trade_in` (null = unknown, false = none), `trade_in_description`, `offer_note`, and the financing ones: `financing_term_months` (plazo(s) = number of cuotas, e.g. `[12, 18, 24]`), `installment_amount` (valor cuota), `max_down_payment_amount` (pie máximo), `net_income_amount` (renta líquida), `employer`, `employment_tenure`. Each carries provenance in `deal_terms_meta` (`ai` | `human`); an AI writer never overwrites a human-owned field — a disagreeing AI reading is kept in `deal_terms_suggestions` instead. Every field in the body becomes human-owned (`source: human`, the caller as actor) and its pending suggestion is removed; `null` clears a value but keeps it human-owned, so the next AI read proposes instead of re-filling it. Accepting a suggestion is this call with the suggested value. `applicant_full_name` / `applicant_rut` are the applicant's identity and are written to the lead's PRIMARY contact (`legal_name`, `tax_id` kind `rut`) — no provenance; 400 when the lead has no contact or the RUT check digit is wrong, 409 when another contact already holds that RUT. Changes land on the lead's timeline as `deal_terms_changed`. Returns the Oportunidad `lead` object. `{id}` accepts the lead uuid or its ID visible (`L-89`) — the label is a lookup shortcut on the path only, never a value to store.
22152
22240
  */
22153
22241
  put: {
22154
22242
  parameters: {
@@ -22163,8 +22251,14 @@ interface paths {
22163
22251
  content: {
22164
22252
  /**
22165
22253
  * @example {
22166
- * "payment_method": "cash",
22167
- * "offer_amount": 10800000
22254
+ * "payment_method": "financing",
22255
+ * "financing_term_months": [
22256
+ * 12,
22257
+ * 18,
22258
+ * 24
22259
+ * ],
22260
+ * "net_income_amount": 1900000,
22261
+ * "applicant_rut": "12.345.678-5"
22168
22262
  * }
22169
22263
  */
22170
22264
  "application/json": {
@@ -22176,6 +22270,22 @@ interface paths {
22176
22270
  trade_in_description?: string | null;
22177
22271
  offer_amount?: number | null;
22178
22272
  offer_note?: string | null;
22273
+ /** @description Plazo(s) in months the customer asked to quote — the number of cuotas. Stored deduped and ascending, e.g. [12, 18, 24]. */
22274
+ financing_term_months?: number[] | null;
22275
+ /** @description Valor de la cuota as quoted by the dealership / financiera. */
22276
+ installment_amount?: number | null;
22277
+ /** @description The most pie the customer could put if needed. */
22278
+ max_down_payment_amount?: number | null;
22279
+ /** @description Renta líquida mensual. */
22280
+ net_income_amount?: number | null;
22281
+ /** @description Where the customer works («CGE»). */
22282
+ employer?: string | null;
22283
+ /** @description Antigüedad laboral («15 años»). */
22284
+ employment_tenure?: string | null;
22285
+ /** @description The applicant's full legal name → the lead's primary contact `legal_name`. null clears. */
22286
+ applicant_full_name?: string | null;
22287
+ /** @description The applicant's RUT in any spelling → the primary contact's `tax_id` (kind `rut`), stored canonical. 400 on a wrong check digit, 409 when another contact of the workspace already holds it. null clears. */
22288
+ applicant_rut?: string | null;
22179
22289
  };
22180
22290
  };
22181
22291
  };
@@ -22213,7 +22323,17 @@ interface paths {
22213
22323
  * "has_trade_in": true,
22214
22324
  * "trade_in_description": "Chery Tiggo 2 Pro 2023, 32.000 km",
22215
22325
  * "offer_amount": 10500000,
22216
- * "offer_note": "Financiado · pendiente de aprobación"
22326
+ * "offer_note": "Financiado · pendiente de aprobación",
22327
+ * "financing_term_months": [
22328
+ * 12,
22329
+ * 18,
22330
+ * 24
22331
+ * ],
22332
+ * "installment_amount": null,
22333
+ * "max_down_payment_amount": 5000000,
22334
+ * "net_income_amount": 1900000,
22335
+ * "employer": "CGE",
22336
+ * "employment_tenure": "15 años"
22217
22337
  * },
22218
22338
  * "deal_terms_meta": {
22219
22339
  * "payment_method": {
@@ -22329,7 +22449,7 @@ interface paths {
22329
22449
  header?: never;
22330
22450
  path: {
22331
22451
  id: string;
22332
- field: "payment_method" | "down_payment_amount" | "budget_max_amount" | "has_trade_in" | "trade_in_description" | "offer_amount" | "offer_note";
22452
+ field: "payment_method" | "down_payment_amount" | "budget_max_amount" | "has_trade_in" | "trade_in_description" | "offer_amount" | "offer_note" | "financing_term_months" | "installment_amount" | "max_down_payment_amount" | "net_income_amount" | "employer" | "employment_tenure";
22333
22453
  };
22334
22454
  cookie?: never;
22335
22455
  };
@@ -22368,7 +22488,17 @@ interface paths {
22368
22488
  * "has_trade_in": true,
22369
22489
  * "trade_in_description": "Chery Tiggo 2 Pro 2023, 32.000 km",
22370
22490
  * "offer_amount": 10500000,
22371
- * "offer_note": "Financiado · pendiente de aprobación"
22491
+ * "offer_note": "Financiado · pendiente de aprobación",
22492
+ * "financing_term_months": [
22493
+ * 12,
22494
+ * 18,
22495
+ * 24
22496
+ * ],
22497
+ * "installment_amount": null,
22498
+ * "max_down_payment_amount": 5000000,
22499
+ * "net_income_amount": 1900000,
22500
+ * "employer": "CGE",
22501
+ * "employment_tenure": "15 años"
22372
22502
  * },
22373
22503
  * "deal_terms_meta": {
22374
22504
  * "payment_method": {
@@ -22522,7 +22652,17 @@ interface paths {
22522
22652
  * "has_trade_in": true,
22523
22653
  * "trade_in_description": "Chery Tiggo 2 Pro 2023, 32.000 km",
22524
22654
  * "offer_amount": 10500000,
22525
- * "offer_note": "Financiado · pendiente de aprobación"
22655
+ * "offer_note": "Financiado · pendiente de aprobación",
22656
+ * "financing_term_months": [
22657
+ * 12,
22658
+ * 18,
22659
+ * 24
22660
+ * ],
22661
+ * "installment_amount": null,
22662
+ * "max_down_payment_amount": 5000000,
22663
+ * "net_income_amount": 1900000,
22664
+ * "employer": "CGE",
22665
+ * "employment_tenure": "15 años"
22526
22666
  * },
22527
22667
  * "deal_terms_meta": {
22528
22668
  * "payment_method": {
@@ -22703,6 +22843,15 @@ interface paths {
22703
22843
  * "trade_in_description": null,
22704
22844
  * "offer_amount": null,
22705
22845
  * "offer_note": null,
22846
+ * "financing_term_months": [
22847
+ * 24,
22848
+ * 36
22849
+ * ],
22850
+ * "installment_amount": null,
22851
+ * "max_down_payment_amount": null,
22852
+ * "net_income_amount": 1900000,
22853
+ * "employer": "CGE",
22854
+ * "employment_tenure": "15 años",
22706
22855
  * "deal_terms_meta": {
22707
22856
  * "payment_method": {
22708
22857
  * "source": "ai",
@@ -22900,6 +23049,15 @@ interface paths {
22900
23049
  * "trade_in_description": null,
22901
23050
  * "offer_amount": null,
22902
23051
  * "offer_note": null,
23052
+ * "financing_term_months": [
23053
+ * 24,
23054
+ * 36
23055
+ * ],
23056
+ * "installment_amount": null,
23057
+ * "max_down_payment_amount": null,
23058
+ * "net_income_amount": 1900000,
23059
+ * "employer": "CGE",
23060
+ * "employment_tenure": "15 años",
22903
23061
  * "deal_terms_meta": {
22904
23062
  * "payment_method": {
22905
23063
  * "source": "ai",
@@ -23098,6 +23256,15 @@ interface paths {
23098
23256
  * "trade_in_description": null,
23099
23257
  * "offer_amount": null,
23100
23258
  * "offer_note": null,
23259
+ * "financing_term_months": [
23260
+ * 24,
23261
+ * 36
23262
+ * ],
23263
+ * "installment_amount": null,
23264
+ * "max_down_payment_amount": null,
23265
+ * "net_income_amount": 1900000,
23266
+ * "employer": "CGE",
23267
+ * "employment_tenure": "15 años",
23101
23268
  * "deal_terms_meta": {
23102
23269
  * "payment_method": {
23103
23270
  * "source": "ai",
@@ -23298,6 +23465,15 @@ interface paths {
23298
23465
  * "trade_in_description": null,
23299
23466
  * "offer_amount": null,
23300
23467
  * "offer_note": null,
23468
+ * "financing_term_months": [
23469
+ * 24,
23470
+ * 36
23471
+ * ],
23472
+ * "installment_amount": null,
23473
+ * "max_down_payment_amount": null,
23474
+ * "net_income_amount": 1900000,
23475
+ * "employer": "CGE",
23476
+ * "employment_tenure": "15 años",
23301
23477
  * "deal_terms_meta": {
23302
23478
  * "payment_method": {
23303
23479
  * "source": "ai",
@@ -23496,6 +23672,15 @@ interface paths {
23496
23672
  * "trade_in_description": null,
23497
23673
  * "offer_amount": null,
23498
23674
  * "offer_note": null,
23675
+ * "financing_term_months": [
23676
+ * 24,
23677
+ * 36
23678
+ * ],
23679
+ * "installment_amount": null,
23680
+ * "max_down_payment_amount": null,
23681
+ * "net_income_amount": 1900000,
23682
+ * "employer": "CGE",
23683
+ * "employment_tenure": "15 años",
23499
23684
  * "deal_terms_meta": {
23500
23685
  * "payment_method": {
23501
23686
  * "source": "ai",
@@ -23694,6 +23879,15 @@ interface paths {
23694
23879
  * "trade_in_description": null,
23695
23880
  * "offer_amount": null,
23696
23881
  * "offer_note": null,
23882
+ * "financing_term_months": [
23883
+ * 24,
23884
+ * 36
23885
+ * ],
23886
+ * "installment_amount": null,
23887
+ * "max_down_payment_amount": null,
23888
+ * "net_income_amount": 1900000,
23889
+ * "employer": "CGE",
23890
+ * "employment_tenure": "15 años",
23697
23891
  * "deal_terms_meta": {
23698
23892
  * "payment_method": {
23699
23893
  * "source": "ai",
@@ -23877,6 +24071,15 @@ interface paths {
23877
24071
  * "trade_in_description": null,
23878
24072
  * "offer_amount": null,
23879
24073
  * "offer_note": null,
24074
+ * "financing_term_months": [
24075
+ * 24,
24076
+ * 36
24077
+ * ],
24078
+ * "installment_amount": null,
24079
+ * "max_down_payment_amount": null,
24080
+ * "net_income_amount": 1900000,
24081
+ * "employer": "CGE",
24082
+ * "employment_tenure": "15 años",
23880
24083
  * "deal_terms_meta": {
23881
24084
  * "payment_method": {
23882
24085
  * "source": "ai",
@@ -33834,7 +34037,7 @@ interface paths {
33834
34037
  };
33835
34038
  /**
33836
34039
  * Print the nota de compra
33837
- * @description The nota de compra as a printable PDF (`application/pdf`, served `inline`) on the dealership’s paper: folio, seller, vehicle, lines and totals. Rendered on demand and not stored. Any status prints; a voided note says «Anulada». Accepts the UUID or the folio (`P-47`). Requires `purchase_notes:read`.
34040
+ * @description The nota de compra as a printable PDF (`application/pdf`, served `inline`) on the dealership’s paper, drawn from the workspace’s default nota de compra template (the standard text when there is none): folio, the seller and the dealership with RUT and domicilio, the vehicle, the price with its retentions and the amount paid to the seller, detail lines and signatures. A fact the seller’s contact lacks prints «【PENDIENTE: …】» rather than refusing the print. Rendered on demand and not stored. Any status prints; a voided note says «Anulada». Accepts the UUID or the folio (`P-47`). Requires `purchase_notes:read`.
33838
34041
  */
33839
34042
  get: {
33840
34043
  parameters: {
@@ -34420,7 +34623,7 @@ interface paths {
34420
34623
  };
34421
34624
  /**
34422
34625
  * Placeholder values of the latest issued document of a template's type
34423
- * @description What the template preview renders against: the `{{NAME}}` values of the most recent documento emitido of the template's document type, built by the SAME code that prints that document, so the preview cannot drift from the print. Covers `sale_note`, `compraventa`, `deal_settlement` (Resumen del negocio), `consignment` (mandato) and `consignment_settlement` (liquidación); nota de compra, reserva, cotización and ficha técnica print fixed layouts and have no values source. `source` names the document (`display_id`: the folio such as `V-12`, or the patente for a consignment, and when it was issued); it is `null` — with an empty `values` — when none exists or the type has no values source; the caller then falls back to the vocabulary examples. A fact the document lacks is absent from `values`, never blank. The values carry buyer/owner identity and money, so this requires `document_templates:read` AND the read scope of that document (`sale_notes:read` for nota de venta and compraventa, `consignments:read` for the two consignment families, `dealership_economics:read` for the Resumen del negocio). Writes and issues nothing.
34626
+ * @description What the template preview renders against: the `{{NAME}}` values of the most recent documento emitido of the template's document type, built by the SAME code that prints that document, so the preview cannot drift from the print. Covers `sale_note`, `compraventa`, `deal_settlement` (Resumen del negocio), `consignment` (mandato), `consignment_settlement` (liquidación) and `purchase_note` (nota de compra); reserva, cotización and ficha técnica print fixed layouts and have no values source. The designed blocks (`BLOQUE_PARTES`, `BLOQUE_VEHICULO`, `BLOQUE_PRECIO`, `BLOQUE_FIRMAS`) are values too: each is the block's text form filled with the same document's values (a fact the document lacks reads «【PENDIENTE: …】»). `source` names the document (`display_id`: the folio such as `V-12`, or the patente for a consignment, and when it was issued); it is `null` — with an empty `values` — when none exists or the type has no values source; the caller then falls back to the vocabulary examples. A fact the document lacks is absent from `values`, never blank. The values carry buyer/owner identity and money, so this requires `document_templates:read` AND the read scope of that document (`sale_notes:read` for nota de venta and compraventa, `consignments:read` for the two consignment families, `dealership_economics:read` for the Resumen del negocio, `purchase_notes:read` for the nota de compra). Writes and issues nothing.
34424
34627
  */
34425
34628
  get: {
34426
34629
  parameters: {
@@ -39637,6 +39840,205 @@ interface paths {
39637
39840
  patch?: never;
39638
39841
  trace?: never;
39639
39842
  };
39843
+ "/margin/preview": {
39844
+ parameters: {
39845
+ query?: never;
39846
+ header?: never;
39847
+ path?: never;
39848
+ cookie?: never;
39849
+ };
39850
+ get?: never;
39851
+ put?: never;
39852
+ /**
39853
+ * Preview the margin of a nota de venta being written
39854
+ * @description The margin a nota de venta WOULD leave if the unit sold today at `net_clp` — what the nota de venta form shows while the price is typed. The same preview the Resumen del negocio serves for a car with no live nota de venta (`GET /vehicles/{id}/deal-settlement`, `state: preview`), at the typed price instead of the published one: no add-ons, no seller commissions, and the one margin definition. The body is the deal-margin DTO of `GET /margin/deals/{id}` without `sale_note_id`, `display_id` and `salesperson_id` — no document exists yet.
39855
+ *
39856
+ * **A consigned unit is previewed on its contract’s economics**: the split is projected from the active contract’s comisión exactly as the liquidación will compute it (`settlement` carries the projection), so the dealership’s revenue is the comisión, never the whole price. A contract with no comisión on file has no split to project: its revenue is `null` with a `liquidacion` gap.
39857
+ *
39858
+ * `net_clp` is NET of IVA (cifras del negocio, ADR 0114 §2.2). The price a buyer agrees to on an afecto sale includes IVA, like the published price: send `round(price / 1,19)`. Writes nothing. Requires `dealership_economics:read`; 404 for a unit outside the workspace.
39859
+ */
39860
+ post: {
39861
+ parameters: {
39862
+ query?: never;
39863
+ header?: {
39864
+ /** @description Replay-safe retries: resending the SAME key with the SAME body returns the original response (`X-Idempotent-Replay: 1`) instead of creating a second copy — safe to send whenever a response might not have arrived. The same key with a DIFFERENT body answers `409 IDEMPOTENCY_KEY_CONFLICT`; use a fresh key per operation. */
39865
+ "Idempotency-Key"?: string;
39866
+ };
39867
+ path?: never;
39868
+ cookie?: never;
39869
+ };
39870
+ requestBody?: {
39871
+ content: {
39872
+ /**
39873
+ * @example {
39874
+ * "vehicle_id": "e5e5e5e5-0000-4000-8000-000000000002",
39875
+ * "net_clp": 10000000
39876
+ * }
39877
+ */
39878
+ "application/json": {
39879
+ /**
39880
+ * Format: uuid
39881
+ * @description The unit being sold.
39882
+ * @example 4b1c2d3e-5f60-4a7b-8c9d-0e1f2a3b4c5d
39883
+ */
39884
+ vehicle_id: string;
39885
+ /**
39886
+ * @description The sale price the nota de venta would record, NET of IVA, in whole CLP pesos. On an afecto sale that is the price the buyer pays divided by 1,19 (rounded); on an exento sale it is the price.
39887
+ * @example 10084034
39888
+ */
39889
+ net_clp: number;
39890
+ /**
39891
+ * @description The leg the sale would be issued under. Omitted = the leg the unit’s tenencia suggests (`consignante` for a consigned unit, `automotora` otherwise).
39892
+ * @enum {string}
39893
+ */
39894
+ seller_of_record?: "consignante" | "retoma" | "automotora";
39895
+ };
39896
+ };
39897
+ };
39898
+ responses: {
39899
+ /** @description The previewed deal margin */
39900
+ 200: {
39901
+ headers: {
39902
+ [name: string]: unknown;
39903
+ };
39904
+ content: {
39905
+ /**
39906
+ * @example {
39907
+ * "data": {
39908
+ * "vehicle_id": "e5e5e5e5-0000-4000-8000-000000000002",
39909
+ * "issued_at": "2026-09-29T15:00:00.000Z",
39910
+ * "period": "2026-09",
39911
+ * "regime": "consignacion",
39912
+ * "ingresos_clp": 800000,
39913
+ * "revenue_terms": {
39914
+ * "precio_venta_clp": 10000000,
39915
+ * "add_on_charges_clp": 0,
39916
+ * "pass_through_clp": 0,
39917
+ * "pass_through_paid_out_clp": 0,
39918
+ * "dealer_take_clp": 800000
39919
+ * },
39920
+ * "costo_venta_clp": 0,
39921
+ * "margen_bruto_clp": 800000,
39922
+ * "deductions": {
39923
+ * "comisiones_vendedores_clp": 0,
39924
+ * "gastos_adicionales_clp": 120000,
39925
+ * "gastos_unidad_clp": 120000,
39926
+ * "ingresos_unidad_clp": 0,
39927
+ * "desembolsos_add_on_clp": 0,
39928
+ * "gastos_fijos_clp": null
39929
+ * },
39930
+ * "margen_neto_clp": 680000,
39931
+ * "settlement": {
39932
+ * "settlement_mode": "stated_commission",
39933
+ * "amount_venta_clp": 10000000,
39934
+ * "monto_owner_clp": 9200000,
39935
+ * "deducciones_clp": 0
39936
+ * },
39937
+ * "cost_rollup": {
39938
+ * "acquisition_net_clp": 0,
39939
+ * "expense_total_clp": 120000,
39940
+ * "income_total_clp": 0,
39941
+ * "total_cost_clp": 120000,
39942
+ * "dealership_cost_clp": 120000,
39943
+ * "by_party": {
39944
+ * "automotora": {
39945
+ * "acquisition_clp": 0,
39946
+ * "expense_clp": 120000,
39947
+ * "income_clp": 0,
39948
+ * "total_clp": 120000
39949
+ * },
39950
+ * "dueno": {
39951
+ * "acquisition_clp": 0,
39952
+ * "expense_clp": 0,
39953
+ * "income_clp": 0,
39954
+ * "total_clp": 0
39955
+ * },
39956
+ * "cliente": {
39957
+ * "acquisition_clp": 0,
39958
+ * "expense_clp": 0,
39959
+ * "income_clp": 0,
39960
+ * "total_clp": 0
39961
+ * }
39962
+ * },
39963
+ * "entry_count": 2,
39964
+ * "complete": true,
39965
+ * "gaps": []
39966
+ * },
39967
+ * "complete": true,
39968
+ * "gaps": []
39969
+ * }
39970
+ * }
39971
+ */
39972
+ "application/json": {
39973
+ data?: unknown;
39974
+ meta?: {
39975
+ [key: string]: unknown;
39976
+ };
39977
+ };
39978
+ };
39979
+ };
39980
+ /** @description Validation error */
39981
+ 400: {
39982
+ headers: {
39983
+ [name: string]: unknown;
39984
+ };
39985
+ content: {
39986
+ "application/json": components["schemas"]["Error"];
39987
+ };
39988
+ };
39989
+ /** @description Unauthorized */
39990
+ 401: {
39991
+ headers: {
39992
+ [name: string]: unknown;
39993
+ };
39994
+ content: {
39995
+ "application/json": components["schemas"]["Error"];
39996
+ };
39997
+ };
39998
+ /** @description Forbidden */
39999
+ 403: {
40000
+ headers: {
40001
+ [name: string]: unknown;
40002
+ };
40003
+ content: {
40004
+ "application/json": components["schemas"]["Error"];
40005
+ };
40006
+ };
40007
+ /** @description Not found */
40008
+ 404: {
40009
+ headers: {
40010
+ [name: string]: unknown;
40011
+ };
40012
+ content: {
40013
+ "application/json": components["schemas"]["Error"];
40014
+ };
40015
+ };
40016
+ /** @description Conflict (incl. Idempotency-Key reuse with different body) */
40017
+ 409: {
40018
+ headers: {
40019
+ [name: string]: unknown;
40020
+ };
40021
+ content: {
40022
+ "application/json": components["schemas"]["Error"];
40023
+ };
40024
+ };
40025
+ /** @description Rate limited */
40026
+ 429: {
40027
+ headers: {
40028
+ [name: string]: unknown;
40029
+ };
40030
+ content: {
40031
+ "application/json": components["schemas"]["Error"];
40032
+ };
40033
+ };
40034
+ };
40035
+ };
40036
+ delete?: never;
40037
+ options?: never;
40038
+ head?: never;
40039
+ patch?: never;
40040
+ trace?: never;
40041
+ };
39640
40042
  "/margin/export": {
39641
40043
  parameters: {
39642
40044
  query?: never;
@@ -71823,6 +72225,263 @@ interface paths {
71823
72225
  patch?: never;
71824
72226
  trace?: never;
71825
72227
  };
72228
+ "/clinic/insights/resultados": {
72229
+ parameters: {
72230
+ query?: never;
72231
+ header?: never;
72232
+ path?: never;
72233
+ cookie?: never;
72234
+ };
72235
+ /**
72236
+ * «Tu agenda con Vitrina»: what the AI did for the diary
72237
+ * @description One canonical read of what Vitrina's agent did for the clinic's agenda, aggregates only (never a patient, cita or conversation id). A cita is «agendada por Vitrina» when the agent booked it in a conversation (`source = 'agent'` and no public booking page); the window is on the day the cita HAPPENS (`starts_at`), blocks and holds out. Blocks: `bookings` (count and share of the agenda, with the previous period of the same length); `money` (the value of those citas — pipeline — and the CASH their patients paid in the period from the day Vitrina booked them, read from the revenue mirror when it is on, else from the native ledger; `null` with `withheld: true` for a caller without `clinic_money:read`); `out_of_hours` (bookings made while the workspace was closed per its business hours, plus a weekday × hour heatmap; `null` when no hours are configured); `autonomy` (bookings with no team message in the conversation, from the patient's first message of the 7 days before); `time_to_book` (median and p95, first patient message → booking); `hours_returned` (AI bookings × 10 minutes, a stated rule); `recovery` (no-shows over known attendance, and no-shows / cancellations the same patient booked again within 30 days, with how many of those Vitrina booked); `confirmation` (attendance of confirmed vs unconfirmed citas, the `confirmaciones` report's own figures); `ads` (cost per cita agendada / asistida / paciente que pagó = the Ads overview's spend ÷ its counts for the same dates; `not_active` without Vitrina Ads); `reminders` (reminders that did not go out, by cause). Every block carries a printable `rule`; every rate is `null` — never 0 — without a denominator, and measured figures carry `measured` / `unknown` counts. Requires `clinic:read`. Accepts `from` / `to` (bare `YYYY-MM-DD`, `to` inclusive; default the 90 days ending today in the clinic's zone) and `location_id`.
72238
+ *
72239
+ * **Connected apps:** every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, `"M.F. · #1001"` — unless the clinic allowed patient names, with RUT, phone and email masked in free text and `meta.patient_privacy` saying so. Clinical alerts (`flags`) are withheld in both modes, and a non-JSON body (an export, a file) is refused with `403 CONNECTED_APP_SENSITIVE_DATA`.
72240
+ */
72241
+ get: {
72242
+ parameters: {
72243
+ query?: {
72244
+ /** @description First day of the window (by the day the cita happens), inclusive. Defaults to 90 days before `to`. */
72245
+ from?: string;
72246
+ /** @description Last day of the window, INCLUSIVE. Defaults to today in the clinic's zone. */
72247
+ to?: string;
72248
+ /** @description One sucursal. Omit for all of them. */
72249
+ location_id?: string;
72250
+ };
72251
+ header?: never;
72252
+ path?: never;
72253
+ cookie?: never;
72254
+ };
72255
+ requestBody?: never;
72256
+ responses: {
72257
+ /** @description Tu agenda con Vitrina */
72258
+ 200: {
72259
+ headers: {
72260
+ [name: string]: unknown;
72261
+ };
72262
+ content: {
72263
+ /**
72264
+ * @example {
72265
+ * "data": {
72266
+ * "from": "2026-07-01",
72267
+ * "to": "2026-09-28",
72268
+ * "timezone": "America/Santiago",
72269
+ * "location_id": null,
72270
+ * "family": "clinic",
72271
+ * "previous_period": {
72272
+ * "from": "2026-04-02",
72273
+ * "to": "2026-06-30"
72274
+ * },
72275
+ * "bookings": {
72276
+ * "ai": 286,
72277
+ * "agenda_total": 2011,
72278
+ * "share_pct": 14.2,
72279
+ * "previous": {
72280
+ * "ai": 240,
72281
+ * "agenda_total": 1950,
72282
+ * "share_pct": 12.3
72283
+ * },
72284
+ * "rule": "Citas del período (por la fecha de la cita) que agendó el asistente de Vitrina en una conversación, ÷ todas las citas del período."
72285
+ * },
72286
+ * "money": {
72287
+ * "applies": true,
72288
+ * "withheld": false,
72289
+ * "booked_clp": 11400000,
72290
+ * "booked_priced": 271,
72291
+ * "booked_unpriced": 15,
72292
+ * "agenda_clp": 96000000,
72293
+ * "clp_share_pct": 11.9,
72294
+ * "paid_clp": 7250000,
72295
+ * "paid_patients": 164,
72296
+ * "unlinked": 4,
72297
+ * "regime": "mirror",
72298
+ * "previous": {
72299
+ * "booked_clp": 9800000,
72300
+ * "paid_clp": 6100000
72301
+ * },
72302
+ * "rule_booked": "Valor de las citas que agendó Vitrina: el precio de sus prestaciones, o el del catálogo. Es lo agendado, no lo cobrado.",
72303
+ * "rule_paid": "Pagos recibidos en el período por los pacientes que Vitrina agendó, desde el día en que los agendó."
72304
+ * },
72305
+ * "out_of_hours": {
72306
+ * "configured": true,
72307
+ * "count": 111,
72308
+ * "pct": 38.8,
72309
+ * "previous_pct": 36.1,
72310
+ * "heatmap": [
72311
+ * {
72312
+ * "weekday": 1,
72313
+ * "hour": 21,
72314
+ * "count": 9
72315
+ * },
72316
+ * {
72317
+ * "weekday": 6,
72318
+ * "hour": 11,
72319
+ * "count": 14
72320
+ * }
72321
+ * ],
72322
+ * "rule": "Citas que Vitrina agendó mientras tu negocio estaba cerrado, según tu horario de atención (incluye feriados)."
72323
+ * },
72324
+ * "autonomy": {
72325
+ * "no_human": 158,
72326
+ * "pct": 56.6,
72327
+ * "measured": 279,
72328
+ * "unknown": 7,
72329
+ * "previous_pct": 52,
72330
+ * "rule": "Citas de Vitrina en las que nadie de tu equipo escribió en la conversación antes de agendar."
72331
+ * },
72332
+ * "time_to_book": {
72333
+ * "median_seconds": 734,
72334
+ * "p95_seconds": 80100,
72335
+ * "p95_phrase": "5 de cada 100 personas tardan más de 22 h 15 min en quedar agendadas.",
72336
+ * "measured": 279,
72337
+ * "unknown": 7,
72338
+ * "previous_median_seconds": 910,
72339
+ * "rule": "Tiempo desde el primer mensaje del paciente hasta que su cita quedó agendada (la mediana)."
72340
+ * },
72341
+ * "hours_returned": {
72342
+ * "minutes_per_booking": 10,
72343
+ * "hours": 47.7,
72344
+ * "rule": "Cada cita que agenda Vitrina ahorra 10 minutos de responder y agendar a mano."
72345
+ * },
72346
+ * "recovery": {
72347
+ * "window_days": 30,
72348
+ * "known_attendance": 1063,
72349
+ * "unknown_attendance": 21,
72350
+ * "no_show_pct": 10.2,
72351
+ * "no_show": {
72352
+ * "count": 108,
72353
+ * "recovered": 37,
72354
+ * "recovered_via_vitrina": 17,
72355
+ * "recovered_pct": 34.6,
72356
+ * "via_vitrina_pct": 15.9,
72357
+ * "pending": 12,
72358
+ * "unlinked": 1
72359
+ * },
72360
+ * "cancelled": {
72361
+ * "count": 240,
72362
+ * "recovered": 26,
72363
+ * "recovered_via_vitrina": 11,
72364
+ * "recovered_pct": 10.8,
72365
+ * "via_vitrina_pct": 4.6,
72366
+ * "pending": 18,
72367
+ * "unlinked": 0
72368
+ * },
72369
+ * "rule_no_show": "Citas pasadas marcadas como «no asistió» ÷ citas con asistencia conocida (asistió + no asistió).",
72370
+ * "rule_recovered": "Una cita perdida se recupera cuando el mismo paciente agenda otra dentro de 30 días."
72371
+ * },
72372
+ * "confirmation": {
72373
+ * "applies": true,
72374
+ * "confirmed_attendance_pct": 93.1,
72375
+ * "unconfirmed_attendance_pct": 78.4,
72376
+ * "confirmed_closed": 610,
72377
+ * "unconfirmed_closed": 212,
72378
+ * "rule": "Asistencia de las citas cuyo paciente confirmó el recordatorio, frente a las que nunca respondieron."
72379
+ * },
72380
+ * "ads": {
72381
+ * "state": "active",
72382
+ * "spend_clp": 1648000,
72383
+ * "booked": 58,
72384
+ * "attended": 41,
72385
+ * "paid": 22,
72386
+ * "cost_per_booked": 28414,
72387
+ * "cost_per_attended": 40195,
72388
+ * "cost_per_paid": 74909,
72389
+ * "rule": "Inversión en anuncios del período ÷ citas agendadas, asistidas y pacientes que pagaron por primera vez, según Vitrina Ads para las mismas fechas."
72390
+ * },
72391
+ * "reminders": {
72392
+ * "applies": true,
72393
+ * "sent": 721,
72394
+ * "failed": 120,
72395
+ * "failed_pct": 14.3,
72396
+ * "by_cause": [
72397
+ * {
72398
+ * "cause": "no_whatsapp",
72399
+ * "count": 61
72400
+ * },
72401
+ * {
72402
+ * "cause": "no_phone",
72403
+ * "count": 38
72404
+ * },
72405
+ * {
72406
+ * "cause": "meta_payment_block",
72407
+ * "count": 21
72408
+ * }
72409
+ * ],
72410
+ * "rule": "Recordatorios de citas del período que no salieron, agrupados por la causa que registró el envío."
72411
+ * },
72412
+ * "truncated": false
72413
+ * }
72414
+ * }
72415
+ */
72416
+ "application/json": {
72417
+ data: components["schemas"]["AgendaResults"];
72418
+ };
72419
+ };
72420
+ };
72421
+ /** @description Validation error */
72422
+ 400: {
72423
+ headers: {
72424
+ [name: string]: unknown;
72425
+ };
72426
+ content: {
72427
+ "application/json": components["schemas"]["Error"];
72428
+ };
72429
+ };
72430
+ /** @description Unauthorized */
72431
+ 401: {
72432
+ headers: {
72433
+ [name: string]: unknown;
72434
+ };
72435
+ content: {
72436
+ "application/json": components["schemas"]["Error"];
72437
+ };
72438
+ };
72439
+ /** @description Forbidden */
72440
+ 403: {
72441
+ headers: {
72442
+ [name: string]: unknown;
72443
+ };
72444
+ content: {
72445
+ "application/json": components["schemas"]["Error"];
72446
+ };
72447
+ };
72448
+ /** @description Not found */
72449
+ 404: {
72450
+ headers: {
72451
+ [name: string]: unknown;
72452
+ };
72453
+ content: {
72454
+ "application/json": components["schemas"]["Error"];
72455
+ };
72456
+ };
72457
+ /** @description Conflict (incl. Idempotency-Key reuse with different body) */
72458
+ 409: {
72459
+ headers: {
72460
+ [name: string]: unknown;
72461
+ };
72462
+ content: {
72463
+ "application/json": components["schemas"]["Error"];
72464
+ };
72465
+ };
72466
+ /** @description Rate limited */
72467
+ 429: {
72468
+ headers: {
72469
+ [name: string]: unknown;
72470
+ };
72471
+ content: {
72472
+ "application/json": components["schemas"]["Error"];
72473
+ };
72474
+ };
72475
+ };
72476
+ };
72477
+ put?: never;
72478
+ post?: never;
72479
+ delete?: never;
72480
+ options?: never;
72481
+ head?: never;
72482
+ patch?: never;
72483
+ trace?: never;
72484
+ };
71826
72485
  "/clinic/insights/comercial": {
71827
72486
  parameters: {
71828
72487
  query?: never;
@@ -78644,6 +79303,7 @@ interface paths {
78644
79303
  active?: boolean | null;
78645
79304
  filtered?: boolean | null;
78646
79305
  aiReplied?: boolean | null;
79306
+ fromAd?: boolean | null;
78647
79307
  sort?: "created_at" | "updated_at" | "last_message_date";
78648
79308
  order?: "asc" | "desc";
78649
79309
  include?: "counts";
@@ -92819,7 +93479,7 @@ interface paths {
92819
93479
  patch?: never;
92820
93480
  trace?: never;
92821
93481
  };
92822
- "/insights/overview/live": {
93482
+ "/insights/resultados": {
92823
93483
  parameters: {
92824
93484
  query?: never;
92825
93485
  header?: never;
@@ -92827,19 +93487,26 @@ interface paths {
92827
93487
  cookie?: never;
92828
93488
  };
92829
93489
  /**
92830
- * Current live activity
92831
- * @description A now-snapshot: open conversations, who is waiting, what is in flight. The one report that takes NO range — it describes the present, so `from`/`to` would mean nothing and are not accepted.
93490
+ * What the AI did for the agenda (any vertical)
93491
+ * @description The same facts as `GET /clinic/insights/resultados`, for any vertical, with the vertical's vocabulary (`family`: a dealer reads visits and test drives, `clientes`). Blocks with no data for the vertical come back `applies: false` (money, confirmation, reminders for a dealer) rather than as zeros. Aggregates only. Requires `analytics:read`; CLP figures additionally require `clinic_money:read`. Accepts `from` / `to` (bare `YYYY-MM-DD`, `to` inclusive; default the 90 days ending today) and `location_id`.
92832
93492
  */
92833
93493
  get: {
92834
93494
  parameters: {
92835
- query?: never;
93495
+ query?: {
93496
+ /** @description First day of the window (by the day the cita happens), inclusive. Defaults to 90 days before `to`. */
93497
+ from?: string;
93498
+ /** @description Last day of the window, INCLUSIVE. Defaults to today in the clinic's zone. */
93499
+ to?: string;
93500
+ /** @description One sucursal. Omit for all of them. */
93501
+ location_id?: string;
93502
+ };
92836
93503
  header?: never;
92837
93504
  path?: never;
92838
93505
  cookie?: never;
92839
93506
  };
92840
93507
  requestBody?: never;
92841
93508
  responses: {
92842
- /** @description Live activity snapshot */
93509
+ /** @description Tu día con Vitrina */
92843
93510
  200: {
92844
93511
  headers: {
92845
93512
  [name: string]: unknown;
@@ -92848,28 +93515,158 @@ interface paths {
92848
93515
  /**
92849
93516
  * @example {
92850
93517
  * "data": {
92851
- * "open": 14,
92852
- * "unattended": 0,
92853
- * "unassigned": 1,
92854
- * "pending": 0,
92855
- * "agents_online": 1,
92856
- * "agents_busy": 0,
92857
- * "agents_offline": 4
92858
- * },
92859
- * "meta": {
92860
- * "window": {
92861
- * "kind": "instant",
92862
- * "at": "2026-09-22T16:38:43.071Z",
92863
- * "label": "ahora"
92864
- * }
93518
+ * "from": "2026-07-01",
93519
+ * "to": "2026-09-28",
93520
+ * "timezone": "America/Santiago",
93521
+ * "location_id": null,
93522
+ * "family": "clinic",
93523
+ * "previous_period": {
93524
+ * "from": "2026-04-02",
93525
+ * "to": "2026-06-30"
93526
+ * },
93527
+ * "bookings": {
93528
+ * "ai": 286,
93529
+ * "agenda_total": 2011,
93530
+ * "share_pct": 14.2,
93531
+ * "previous": {
93532
+ * "ai": 240,
93533
+ * "agenda_total": 1950,
93534
+ * "share_pct": 12.3
93535
+ * },
93536
+ * "rule": "Citas del período (por la fecha de la cita) que agendó el asistente de Vitrina en una conversación, ÷ todas las citas del período."
93537
+ * },
93538
+ * "money": {
93539
+ * "applies": true,
93540
+ * "withheld": false,
93541
+ * "booked_clp": 11400000,
93542
+ * "booked_priced": 271,
93543
+ * "booked_unpriced": 15,
93544
+ * "agenda_clp": 96000000,
93545
+ * "clp_share_pct": 11.9,
93546
+ * "paid_clp": 7250000,
93547
+ * "paid_patients": 164,
93548
+ * "unlinked": 4,
93549
+ * "regime": "mirror",
93550
+ * "previous": {
93551
+ * "booked_clp": 9800000,
93552
+ * "paid_clp": 6100000
93553
+ * },
93554
+ * "rule_booked": "Valor de las citas que agendó Vitrina: el precio de sus prestaciones, o el del catálogo. Es lo agendado, no lo cobrado.",
93555
+ * "rule_paid": "Pagos recibidos en el período por los pacientes que Vitrina agendó, desde el día en que los agendó."
93556
+ * },
93557
+ * "out_of_hours": {
93558
+ * "configured": true,
93559
+ * "count": 111,
93560
+ * "pct": 38.8,
93561
+ * "previous_pct": 36.1,
93562
+ * "heatmap": [
93563
+ * {
93564
+ * "weekday": 1,
93565
+ * "hour": 21,
93566
+ * "count": 9
93567
+ * },
93568
+ * {
93569
+ * "weekday": 6,
93570
+ * "hour": 11,
93571
+ * "count": 14
93572
+ * }
93573
+ * ],
93574
+ * "rule": "Citas que Vitrina agendó mientras tu negocio estaba cerrado, según tu horario de atención (incluye feriados)."
93575
+ * },
93576
+ * "autonomy": {
93577
+ * "no_human": 158,
93578
+ * "pct": 56.6,
93579
+ * "measured": 279,
93580
+ * "unknown": 7,
93581
+ * "previous_pct": 52,
93582
+ * "rule": "Citas de Vitrina en las que nadie de tu equipo escribió en la conversación antes de agendar."
93583
+ * },
93584
+ * "time_to_book": {
93585
+ * "median_seconds": 734,
93586
+ * "p95_seconds": 80100,
93587
+ * "p95_phrase": "5 de cada 100 personas tardan más de 22 h 15 min en quedar agendadas.",
93588
+ * "measured": 279,
93589
+ * "unknown": 7,
93590
+ * "previous_median_seconds": 910,
93591
+ * "rule": "Tiempo desde el primer mensaje del paciente hasta que su cita quedó agendada (la mediana)."
93592
+ * },
93593
+ * "hours_returned": {
93594
+ * "minutes_per_booking": 10,
93595
+ * "hours": 47.7,
93596
+ * "rule": "Cada cita que agenda Vitrina ahorra 10 minutos de responder y agendar a mano."
93597
+ * },
93598
+ * "recovery": {
93599
+ * "window_days": 30,
93600
+ * "known_attendance": 1063,
93601
+ * "unknown_attendance": 21,
93602
+ * "no_show_pct": 10.2,
93603
+ * "no_show": {
93604
+ * "count": 108,
93605
+ * "recovered": 37,
93606
+ * "recovered_via_vitrina": 17,
93607
+ * "recovered_pct": 34.6,
93608
+ * "via_vitrina_pct": 15.9,
93609
+ * "pending": 12,
93610
+ * "unlinked": 1
93611
+ * },
93612
+ * "cancelled": {
93613
+ * "count": 240,
93614
+ * "recovered": 26,
93615
+ * "recovered_via_vitrina": 11,
93616
+ * "recovered_pct": 10.8,
93617
+ * "via_vitrina_pct": 4.6,
93618
+ * "pending": 18,
93619
+ * "unlinked": 0
93620
+ * },
93621
+ * "rule_no_show": "Citas pasadas marcadas como «no asistió» ÷ citas con asistencia conocida (asistió + no asistió).",
93622
+ * "rule_recovered": "Una cita perdida se recupera cuando el mismo paciente agenda otra dentro de 30 días."
93623
+ * },
93624
+ * "confirmation": {
93625
+ * "applies": true,
93626
+ * "confirmed_attendance_pct": 93.1,
93627
+ * "unconfirmed_attendance_pct": 78.4,
93628
+ * "confirmed_closed": 610,
93629
+ * "unconfirmed_closed": 212,
93630
+ * "rule": "Asistencia de las citas cuyo paciente confirmó el recordatorio, frente a las que nunca respondieron."
93631
+ * },
93632
+ * "ads": {
93633
+ * "state": "active",
93634
+ * "spend_clp": 1648000,
93635
+ * "booked": 58,
93636
+ * "attended": 41,
93637
+ * "paid": 22,
93638
+ * "cost_per_booked": 28414,
93639
+ * "cost_per_attended": 40195,
93640
+ * "cost_per_paid": 74909,
93641
+ * "rule": "Inversión en anuncios del período ÷ citas agendadas, asistidas y pacientes que pagaron por primera vez, según Vitrina Ads para las mismas fechas."
93642
+ * },
93643
+ * "reminders": {
93644
+ * "applies": true,
93645
+ * "sent": 721,
93646
+ * "failed": 120,
93647
+ * "failed_pct": 14.3,
93648
+ * "by_cause": [
93649
+ * {
93650
+ * "cause": "no_whatsapp",
93651
+ * "count": 61
93652
+ * },
93653
+ * {
93654
+ * "cause": "no_phone",
93655
+ * "count": 38
93656
+ * },
93657
+ * {
93658
+ * "cause": "meta_payment_block",
93659
+ * "count": 21
93660
+ * }
93661
+ * ],
93662
+ * "rule": "Recordatorios de citas del período que no salieron, agrupados por la causa que registró el envío."
93663
+ * },
93664
+ * "truncated": false
92865
93665
  * }
92866
93666
  * }
92867
93667
  */
92868
93668
  "application/json": {
92869
- data?: unknown;
92870
- meta?: {
92871
- [key: string]: unknown;
92872
- };
93669
+ data: components["schemas"]["AgendaResults"];
92873
93670
  };
92874
93671
  };
92875
93672
  };
@@ -92937,7 +93734,7 @@ interface paths {
92937
93734
  patch?: never;
92938
93735
  trace?: never;
92939
93736
  };
92940
- "/insights/overview/heatmap": {
93737
+ "/insights/overview/live": {
92941
93738
  parameters: {
92942
93739
  query?: never;
92943
93740
  header?: never;
@@ -92945,32 +93742,19 @@ interface paths {
92945
93742
  cookie?: never;
92946
93743
  };
92947
93744
  /**
92948
- * Activity heatmap by day and hour
92949
- * @description The only report that accepts `tz`. Pass the viewer’s IANA zone (`America/Santiago`) and the day/hour buckets follow their wall clock; omit it and the grid is UTC, which shifts a Chilean workspace’s busy hours by three or four columns depending on DST. The name is validated by Postgres, so an unknown zone is a 500 rather than a 400.
93745
+ * Current live activity
93746
+ * @description A now-snapshot: open conversations, who is waiting, what is in flight. The one report that takes NO range — it describes the present, so `from`/`to` would mean nothing and are not accepted.
92950
93747
  */
92951
93748
  get: {
92952
93749
  parameters: {
92953
- query?: {
92954
- /** @description Which period. Omit it (with `from`/`to`) for an explicit range — the shape every ranged Insights report has always accepted, and which still works unchanged. The calendar windows are the DEALERSHIP’s (America/Santiago), so a month closes when a person would say it closed. */
92955
- window?: "24h" | "7d" | "30d" | "90d" | "calendar_month" | "calendar_year" | "custom";
92956
- /** @description `window=calendar_month` only. ISO month, `YYYY-MM`. Defaults to the month in progress. */
92957
- month?: string;
92958
- /** @description `window=calendar_year` only. `YYYY`. Defaults to the year in progress. */
92959
- year?: string;
92960
- /** @description Explicit range only. Checked for non-emptiness and handed to Postgres, so a malformed value surfaces as a 500 from the query rather than a 400 from the edge — send an ISO-8601 instant. */
92961
- from?: string;
92962
- /** @description Explicit range only. ISO instant, see `from`. */
92963
- to?: string;
92964
- /** @description IANA timezone for the date/hour buckets. Defaults to UTC. */
92965
- tz?: string;
92966
- };
93750
+ query?: never;
92967
93751
  header?: never;
92968
93752
  path?: never;
92969
93753
  cookie?: never;
92970
93754
  };
92971
93755
  requestBody?: never;
92972
93756
  responses: {
92973
- /** @description Day/hour activity buckets */
93757
+ /** @description Live activity snapshot */
92974
93758
  200: {
92975
93759
  headers: {
92976
93760
  [name: string]: unknown;
@@ -92979,27 +93763,19 @@ interface paths {
92979
93763
  /**
92980
93764
  * @example {
92981
93765
  * "data": {
92982
- * "buckets": [
92983
- * {
92984
- * "day": 1,
92985
- * "hour": 10,
92986
- * "conversations": 3
92987
- * },
92988
- * {
92989
- * "day": 1,
92990
- * "hour": 11,
92991
- * "conversations": 5
92992
- * }
92993
- * ]
93766
+ * "open": 14,
93767
+ * "unattended": 0,
93768
+ * "unassigned": 1,
93769
+ * "pending": 0,
93770
+ * "agents_online": 1,
93771
+ * "agents_busy": 0,
93772
+ * "agents_offline": 4
92994
93773
  * },
92995
93774
  * "meta": {
92996
93775
  * "window": {
92997
- * "kind": "rolling",
92998
- * "preset": "7d",
92999
- * "hours": 168,
93000
- * "from": "2026-09-15T16:38:51.000Z",
93001
- * "to": "2026-09-22T16:38:51.000Z",
93002
- * "label": "últimos 7d"
93776
+ * "kind": "instant",
93777
+ * "at": "2026-09-22T16:38:43.071Z",
93778
+ * "label": "ahora"
93003
93779
  * }
93004
93780
  * }
93005
93781
  * }
@@ -93076,7 +93852,7 @@ interface paths {
93076
93852
  patch?: never;
93077
93853
  trace?: never;
93078
93854
  };
93079
- "/insights/calls": {
93855
+ "/insights/overview/heatmap": {
93080
93856
  parameters: {
93081
93857
  query?: never;
93082
93858
  header?: never;
@@ -93084,8 +93860,8 @@ interface paths {
93084
93860
  cookie?: never;
93085
93861
  };
93086
93862
  /**
93087
- * Voice call statistics
93088
- * @description Voice-channel call stats for the window. Served by the voice insights service rather than the general reporting one, so its shape does not match the other reports.
93863
+ * Activity heatmap by day and hour
93864
+ * @description The only report that accepts `tz`. Pass the viewer’s IANA zone (`America/Santiago`) and the day/hour buckets follow their wall clock; omit it and the grid is UTC, which shifts a Chilean workspace’s busy hours by three or four columns depending on DST. The name is validated by Postgres, so an unknown zone is a 500 rather than a 400.
93089
93865
  */
93090
93866
  get: {
93091
93867
  parameters: {
@@ -93100,6 +93876,8 @@ interface paths {
93100
93876
  from?: string;
93101
93877
  /** @description Explicit range only. ISO instant, see `from`. */
93102
93878
  to?: string;
93879
+ /** @description IANA timezone for the date/hour buckets. Defaults to UTC. */
93880
+ tz?: string;
93103
93881
  };
93104
93882
  header?: never;
93105
93883
  path?: never;
@@ -93107,7 +93885,7 @@ interface paths {
93107
93885
  };
93108
93886
  requestBody?: never;
93109
93887
  responses: {
93110
- /** @description Call statistics */
93888
+ /** @description Day/hour activity buckets */
93111
93889
  200: {
93112
93890
  headers: {
93113
93891
  [name: string]: unknown;
@@ -93116,30 +93894,18 @@ interface paths {
93116
93894
  /**
93117
93895
  * @example {
93118
93896
  * "data": {
93119
- * "range": {
93120
- * "from": "2026-09-15T16:38:51.540Z",
93121
- * "to": "2026-09-22T16:38:51.540Z"
93122
- * },
93123
- * "calls": {
93124
- * "total": 6,
93125
- * "answered": 5,
93126
- * "avg_duration_s": 142,
93127
- * "by_outcome": {
93128
- * "completed": 5,
93129
- * "no_answer": 1
93130
- * },
93131
- * "by_direction": {
93132
- * "inbound": 4,
93133
- * "outbound": 2
93897
+ * "buckets": [
93898
+ * {
93899
+ * "day": 1,
93900
+ * "hour": 10,
93901
+ * "conversations": 3
93134
93902
  * },
93135
- * "by_amd": {}
93136
- * },
93137
- * "latency": {
93138
- * "voice_to_voice": 820,
93139
- * "voice_llm_turn": 410,
93140
- * "voice_llm_first_token": 190,
93141
- * "tool_execution": 260
93142
- * }
93903
+ * {
93904
+ * "day": 1,
93905
+ * "hour": 11,
93906
+ * "conversations": 5
93907
+ * }
93908
+ * ]
93143
93909
  * },
93144
93910
  * "meta": {
93145
93911
  * "window": {
@@ -93225,7 +93991,7 @@ interface paths {
93225
93991
  patch?: never;
93226
93992
  trace?: never;
93227
93993
  };
93228
- "/insights/conversations": {
93994
+ "/insights/calls": {
93229
93995
  parameters: {
93230
93996
  query?: never;
93231
93997
  header?: never;
@@ -93233,8 +93999,8 @@ interface paths {
93233
93999
  cookie?: never;
93234
94000
  };
93235
94001
  /**
93236
- * Conversation volume and resolution
93237
- * @description Volume, resolution and handling time over the window — the top-level view the other reports break down.
94002
+ * Voice call statistics
94003
+ * @description Voice-channel call stats for the window. Served by the voice insights service rather than the general reporting one, so its shape does not match the other reports.
93238
94004
  */
93239
94005
  get: {
93240
94006
  parameters: {
@@ -93256,7 +94022,7 @@ interface paths {
93256
94022
  };
93257
94023
  requestBody?: never;
93258
94024
  responses: {
93259
- /** @description Conversation volume and resolution */
94025
+ /** @description Call statistics */
93260
94026
  200: {
93261
94027
  headers: {
93262
94028
  [name: string]: unknown;
@@ -93265,84 +94031,30 @@ interface paths {
93265
94031
  /**
93266
94032
  * @example {
93267
94033
  * "data": {
93268
- * "conversations": {
93269
- * "total": 18,
93270
- * "delta_pct": 17,
93271
- * "series": [
93272
- * {
93273
- * "bucket": "2026-09-21",
93274
- * "value": 0
93275
- * },
93276
- * {
93277
- * "bucket": "2026-09-22",
93278
- * "value": 18
93279
- * }
93280
- * ]
93281
- * },
93282
- * "messages_in": {
93283
- * "total": 11,
93284
- * "delta_pct": null,
93285
- * "series": [
93286
- * {
93287
- * "bucket": "2026-09-22",
93288
- * "value": 10
93289
- * }
93290
- * ]
93291
- * },
93292
- * "messages_out": {
93293
- * "total": 25,
93294
- * "delta_pct": null,
93295
- * "series": [
93296
- * {
93297
- * "bucket": "2026-09-22",
93298
- * "value": 25
93299
- * }
93300
- * ]
93301
- * },
93302
- * "first_response_seconds": {
93303
- * "avg": 728.65,
93304
- * "delta_pct": null,
93305
- * "series": [
93306
- * {
93307
- * "bucket": "2026-09-22",
93308
- * "value": 728.65
93309
- * }
93310
- * ]
93311
- * },
93312
- * "first_response_p50_seconds": 388.36,
93313
- * "first_response_p90_seconds": 1411.41,
93314
- * "resolution_seconds": {
93315
- * "avg": 9891.67,
93316
- * "delta_pct": -91.3,
93317
- * "series": [
93318
- * {
93319
- * "bucket": "2026-09-22",
93320
- * "value": 9891.67
93321
- * }
93322
- * ]
93323
- * },
93324
- * "resolutions": {
93325
- * "total": 5,
93326
- * "delta_pct": -16.7,
93327
- * "series": [
93328
- * {
93329
- * "bucket": "2026-09-22",
93330
- * "value": 4
93331
- * }
93332
- * ]
94034
+ * "range": {
94035
+ * "from": "2026-09-15T16:38:51.540Z",
94036
+ * "to": "2026-09-22T16:38:51.540Z"
93333
94037
  * },
93334
- * "customer_wait_seconds": {
93335
- * "avg": 728.65,
93336
- * "delta_pct": null,
93337
- * "series": [
93338
- * {
93339
- * "bucket": "2026-09-22",
93340
- * "value": 728.65
93341
- * }
93342
- * ]
94038
+ * "calls": {
94039
+ * "total": 6,
94040
+ * "answered": 5,
94041
+ * "avg_duration_s": 142,
94042
+ * "by_outcome": {
94043
+ * "completed": 5,
94044
+ * "no_answer": 1
94045
+ * },
94046
+ * "by_direction": {
94047
+ * "inbound": 4,
94048
+ * "outbound": 2
94049
+ * },
94050
+ * "by_amd": {}
93343
94051
  * },
93344
- * "facturables": 4,
93345
- * "solo_humano": 14
94052
+ * "latency": {
94053
+ * "voice_to_voice": 820,
94054
+ * "voice_llm_turn": 410,
94055
+ * "voice_llm_first_token": 190,
94056
+ * "tool_execution": 260
94057
+ * }
93346
94058
  * },
93347
94059
  * "meta": {
93348
94060
  * "window": {
@@ -93428,7 +94140,7 @@ interface paths {
93428
94140
  patch?: never;
93429
94141
  trace?: never;
93430
94142
  };
93431
- "/insights/agents": {
94143
+ "/insights/conversations": {
93432
94144
  parameters: {
93433
94145
  query?: never;
93434
94146
  header?: never;
@@ -93436,8 +94148,8 @@ interface paths {
93436
94148
  cookie?: never;
93437
94149
  };
93438
94150
  /**
93439
- * Human agent performance
93440
- * @description Per-human-agent throughput and response times. `/insights/ai-agents` is the machine-side counterpart; the two are not comparable row for row, because a human is assigned a conversation and an AI agent runs turns within one.
94151
+ * Conversation volume and resolution
94152
+ * @description Volume, resolution and handling time over the window — the top-level view the other reports break down.
93441
94153
  */
93442
94154
  get: {
93443
94155
  parameters: {
@@ -93459,7 +94171,7 @@ interface paths {
93459
94171
  };
93460
94172
  requestBody?: never;
93461
94173
  responses: {
93462
- /** @description Human agent performance */
94174
+ /** @description Conversation volume and resolution */
93463
94175
  200: {
93464
94176
  headers: {
93465
94177
  [name: string]: unknown;
@@ -93467,20 +94179,86 @@ interface paths {
93467
94179
  content: {
93468
94180
  /**
93469
94181
  * @example {
93470
- * "data": [
93471
- * {
93472
- * "user_id": "11111111-0000-4000-8000-000000000001",
93473
- * "name": "Carolina Muñoz",
93474
- * "email": "carolina@example.cl",
93475
- * "conversations": 8,
93476
- * "replies": 5,
93477
- * "avg_first_response_seconds": 733.76,
93478
- * "avg_response_seconds": 28197.49,
93479
- * "avg_resolution_seconds": 9891.67,
93480
- * "avg_customer_wait_seconds": 733.76,
93481
- * "resolutions": 4
93482
- * }
93483
- * ],
94182
+ * "data": {
94183
+ * "conversations": {
94184
+ * "total": 18,
94185
+ * "delta_pct": 17,
94186
+ * "series": [
94187
+ * {
94188
+ * "bucket": "2026-09-21",
94189
+ * "value": 0
94190
+ * },
94191
+ * {
94192
+ * "bucket": "2026-09-22",
94193
+ * "value": 18
94194
+ * }
94195
+ * ]
94196
+ * },
94197
+ * "messages_in": {
94198
+ * "total": 11,
94199
+ * "delta_pct": null,
94200
+ * "series": [
94201
+ * {
94202
+ * "bucket": "2026-09-22",
94203
+ * "value": 10
94204
+ * }
94205
+ * ]
94206
+ * },
94207
+ * "messages_out": {
94208
+ * "total": 25,
94209
+ * "delta_pct": null,
94210
+ * "series": [
94211
+ * {
94212
+ * "bucket": "2026-09-22",
94213
+ * "value": 25
94214
+ * }
94215
+ * ]
94216
+ * },
94217
+ * "first_response_seconds": {
94218
+ * "avg": 728.65,
94219
+ * "delta_pct": null,
94220
+ * "series": [
94221
+ * {
94222
+ * "bucket": "2026-09-22",
94223
+ * "value": 728.65
94224
+ * }
94225
+ * ]
94226
+ * },
94227
+ * "first_response_p50_seconds": 388.36,
94228
+ * "first_response_p90_seconds": 1411.41,
94229
+ * "resolution_seconds": {
94230
+ * "avg": 9891.67,
94231
+ * "delta_pct": -91.3,
94232
+ * "series": [
94233
+ * {
94234
+ * "bucket": "2026-09-22",
94235
+ * "value": 9891.67
94236
+ * }
94237
+ * ]
94238
+ * },
94239
+ * "resolutions": {
94240
+ * "total": 5,
94241
+ * "delta_pct": -16.7,
94242
+ * "series": [
94243
+ * {
94244
+ * "bucket": "2026-09-22",
94245
+ * "value": 4
94246
+ * }
94247
+ * ]
94248
+ * },
94249
+ * "customer_wait_seconds": {
94250
+ * "avg": 728.65,
94251
+ * "delta_pct": null,
94252
+ * "series": [
94253
+ * {
94254
+ * "bucket": "2026-09-22",
94255
+ * "value": 728.65
94256
+ * }
94257
+ * ]
94258
+ * },
94259
+ * "facturables": 4,
94260
+ * "solo_humano": 14
94261
+ * },
93484
94262
  * "meta": {
93485
94263
  * "window": {
93486
94264
  * "kind": "rolling",
@@ -93565,7 +94343,7 @@ interface paths {
93565
94343
  patch?: never;
93566
94344
  trace?: never;
93567
94345
  };
93568
- "/insights/ai-agents": {
94346
+ "/insights/agents": {
93569
94347
  parameters: {
93570
94348
  query?: never;
93571
94349
  header?: never;
@@ -93573,8 +94351,8 @@ interface paths {
93573
94351
  cookie?: never;
93574
94352
  };
93575
94353
  /**
93576
- * Per-AI-agent performance breakdown
93577
- * @description One row per `ai_agent`. `/insights/bots` answers the same question in aggregate — use that for a single headline number and this to find which agent moved it.
94354
+ * Human agent performance
94355
+ * @description Per-human-agent throughput and response times. `/insights/ai-agents` is the machine-side counterpart; the two are not comparable row for row, because a human is assigned a conversation and an AI agent runs turns within one.
93578
94356
  */
93579
94357
  get: {
93580
94358
  parameters: {
@@ -93596,7 +94374,7 @@ interface paths {
93596
94374
  };
93597
94375
  requestBody?: never;
93598
94376
  responses: {
93599
- /** @description Per-AI-agent performance breakdown */
94377
+ /** @description Human agent performance */
93600
94378
  200: {
93601
94379
  headers: {
93602
94380
  [name: string]: unknown;
@@ -93606,22 +94384,16 @@ interface paths {
93606
94384
  * @example {
93607
94385
  * "data": [
93608
94386
  * {
93609
- * "ai_agent_id": "a3a3a3a3-0000-4000-8000-000000000001",
93610
- * "name": "Asistente de ventas",
93611
- * "status": "active",
93612
- * "is_default": true,
93613
- * "conversations": 12,
93614
- * "responses": 30,
93615
- * "avg_response_seconds": 4.2,
93616
- * "automated_conversations": 8,
93617
- * "handoffs": 2,
93618
- * "resolutions": 4,
93619
- * "tool_calls": 21,
93620
- * "cost_usd": 0.0508,
93621
- * "tokens": 322522,
93622
- * "avg_gen_latency_ms": 7938,
93623
- * "handoffs_requested": 2,
93624
- * "handoffs_answered": 2
94387
+ * "user_id": "11111111-0000-4000-8000-000000000001",
94388
+ * "name": "Carolina Muñoz",
94389
+ * "email": "carolina@example.cl",
94390
+ * "conversations": 8,
94391
+ * "replies": 5,
94392
+ * "avg_first_response_seconds": 733.76,
94393
+ * "avg_response_seconds": 28197.49,
94394
+ * "avg_resolution_seconds": 9891.67,
94395
+ * "avg_customer_wait_seconds": 733.76,
94396
+ * "resolutions": 4
93625
94397
  * }
93626
94398
  * ],
93627
94399
  * "meta": {
@@ -93708,7 +94480,7 @@ interface paths {
93708
94480
  patch?: never;
93709
94481
  trace?: never;
93710
94482
  };
93711
- "/insights/bots": {
94483
+ "/insights/ai-agents": {
93712
94484
  parameters: {
93713
94485
  query?: never;
93714
94486
  header?: never;
@@ -93716,8 +94488,8 @@ interface paths {
93716
94488
  cookie?: never;
93717
94489
  };
93718
94490
  /**
93719
- * Aggregate AI handling
93720
- * @description AI handling across the workspace as one figure, not split by agent. The aggregate counterpart to `/insights/ai-agents`.
94491
+ * Per-AI-agent performance breakdown
94492
+ * @description One row per `ai_agent`. `/insights/bots` answers the same question in aggregate — use that for a single headline number and this to find which agent moved it.
93721
94493
  */
93722
94494
  get: {
93723
94495
  parameters: {
@@ -93739,7 +94511,7 @@ interface paths {
93739
94511
  };
93740
94512
  requestBody?: never;
93741
94513
  responses: {
93742
- /** @description Aggregate AI handling */
94514
+ /** @description Per-AI-agent performance breakdown */
93743
94515
  200: {
93744
94516
  headers: {
93745
94517
  [name: string]: unknown;
@@ -93747,43 +94519,26 @@ interface paths {
93747
94519
  content: {
93748
94520
  /**
93749
94521
  * @example {
93750
- * "data": {
93751
- * "conversations": 12,
93752
- * "automated_conversations": 8,
93753
- * "total_conversations": 18,
93754
- * "engaged_conversations": 11,
93755
- * "deflection_rate": 0.44,
93756
- * "total_responses": 30,
93757
- * "avg_response_seconds": 4.2,
93758
- * "resolutions": 4,
93759
- * "handoff_rate": 0.17,
93760
- * "resolved_by_bot": 3,
93761
- * "resolved_by_human": 1,
93762
- * "resolved_by_auto": 0,
93763
- * "cost_usd": 0.0508,
93764
- * "cost_per_conversation": 0.0042,
93765
- * "tokens": 322522,
93766
- * "avg_gen_latency_ms": 7938,
93767
- * "tool_calls": 21,
93768
- * "resolutions_series": [
93769
- * {
93770
- * "bucket": "2026-09-22",
93771
- * "value": 3
93772
- * }
93773
- * ],
93774
- * "handoff_series": [
93775
- * {
93776
- * "bucket": "2026-09-22",
93777
- * "value": 1
93778
- * }
93779
- * ],
93780
- * "cost_series": [
93781
- * {
93782
- * "bucket": "2026-09-22",
93783
- * "value": 0.0064
93784
- * }
93785
- * ]
93786
- * },
94522
+ * "data": [
94523
+ * {
94524
+ * "ai_agent_id": "a3a3a3a3-0000-4000-8000-000000000001",
94525
+ * "name": "Asistente de ventas",
94526
+ * "status": "active",
94527
+ * "is_default": true,
94528
+ * "conversations": 12,
94529
+ * "responses": 30,
94530
+ * "avg_response_seconds": 4.2,
94531
+ * "automated_conversations": 8,
94532
+ * "handoffs": 2,
94533
+ * "resolutions": 4,
94534
+ * "tool_calls": 21,
94535
+ * "cost_usd": 0.0508,
94536
+ * "tokens": 322522,
94537
+ * "avg_gen_latency_ms": 7938,
94538
+ * "handoffs_requested": 2,
94539
+ * "handoffs_answered": 2
94540
+ * }
94541
+ * ],
93787
94542
  * "meta": {
93788
94543
  * "window": {
93789
94544
  * "kind": "rolling",
@@ -93868,7 +94623,7 @@ interface paths {
93868
94623
  patch?: never;
93869
94624
  trace?: never;
93870
94625
  };
93871
- "/insights/tags": {
94626
+ "/insights/bots": {
93872
94627
  parameters: {
93873
94628
  query?: never;
93874
94629
  header?: never;
@@ -93876,8 +94631,8 @@ interface paths {
93876
94631
  cookie?: never;
93877
94632
  };
93878
94633
  /**
93879
- * Volume by tag
93880
- * @description Conversation counts grouped by the tags applied to them.
94634
+ * Aggregate AI handling
94635
+ * @description AI handling across the workspace as one figure, not split by agent. The aggregate counterpart to `/insights/ai-agents`.
93881
94636
  */
93882
94637
  get: {
93883
94638
  parameters: {
@@ -93899,7 +94654,7 @@ interface paths {
93899
94654
  };
93900
94655
  requestBody?: never;
93901
94656
  responses: {
93902
- /** @description Volume by tag */
94657
+ /** @description Aggregate AI handling */
93903
94658
  200: {
93904
94659
  headers: {
93905
94660
  [name: string]: unknown;
@@ -93907,26 +94662,43 @@ interface paths {
93907
94662
  content: {
93908
94663
  /**
93909
94664
  * @example {
93910
- * "data": [
93911
- * {
93912
- * "key": "__none__",
93913
- * "label": "Sin etiqueta",
93914
- * "conversations": 17,
93915
- * "avg_first_response_seconds": 728.65,
93916
- * "avg_resolution_seconds": 9891.67,
93917
- * "avg_customer_wait_seconds": 728.65,
93918
- * "resolutions": 4
93919
- * },
93920
- * {
93921
- * "key": "e1e1e1e1-9000-4000-8000-000000000001",
93922
- * "label": "garantia",
93923
- * "conversations": 1,
93924
- * "avg_first_response_seconds": 0,
93925
- * "avg_resolution_seconds": 0,
93926
- * "avg_customer_wait_seconds": 0,
93927
- * "resolutions": 0
93928
- * }
93929
- * ],
94665
+ * "data": {
94666
+ * "conversations": 12,
94667
+ * "automated_conversations": 8,
94668
+ * "total_conversations": 18,
94669
+ * "engaged_conversations": 11,
94670
+ * "deflection_rate": 0.44,
94671
+ * "total_responses": 30,
94672
+ * "avg_response_seconds": 4.2,
94673
+ * "resolutions": 4,
94674
+ * "handoff_rate": 0.17,
94675
+ * "resolved_by_bot": 3,
94676
+ * "resolved_by_human": 1,
94677
+ * "resolved_by_auto": 0,
94678
+ * "cost_usd": 0.0508,
94679
+ * "cost_per_conversation": 0.0042,
94680
+ * "tokens": 322522,
94681
+ * "avg_gen_latency_ms": 7938,
94682
+ * "tool_calls": 21,
94683
+ * "resolutions_series": [
94684
+ * {
94685
+ * "bucket": "2026-09-22",
94686
+ * "value": 3
94687
+ * }
94688
+ * ],
94689
+ * "handoff_series": [
94690
+ * {
94691
+ * "bucket": "2026-09-22",
94692
+ * "value": 1
94693
+ * }
94694
+ * ],
94695
+ * "cost_series": [
94696
+ * {
94697
+ * "bucket": "2026-09-22",
94698
+ * "value": 0.0064
94699
+ * }
94700
+ * ]
94701
+ * },
93930
94702
  * "meta": {
93931
94703
  * "window": {
93932
94704
  * "kind": "rolling",
@@ -94011,7 +94783,7 @@ interface paths {
94011
94783
  patch?: never;
94012
94784
  trace?: never;
94013
94785
  };
94014
- "/insights/channels": {
94786
+ "/insights/tags": {
94015
94787
  parameters: {
94016
94788
  query?: never;
94017
94789
  header?: never;
@@ -94019,8 +94791,8 @@ interface paths {
94019
94791
  cookie?: never;
94020
94792
  };
94021
94793
  /**
94022
- * Volume by channel
94023
- * @description Grouped by messaging channel (WhatsApp, Instagram, email, voice, …), so a channel with no traffic in the window is simply absent rather than present with a zero.
94794
+ * Volume by tag
94795
+ * @description Conversation counts grouped by the tags applied to them.
94024
94796
  */
94025
94797
  get: {
94026
94798
  parameters: {
@@ -94042,7 +94814,7 @@ interface paths {
94042
94814
  };
94043
94815
  requestBody?: never;
94044
94816
  responses: {
94045
- /** @description Volume by channel */
94817
+ /** @description Volume by tag */
94046
94818
  200: {
94047
94819
  headers: {
94048
94820
  [name: string]: unknown;
@@ -94052,18 +94824,18 @@ interface paths {
94052
94824
  * @example {
94053
94825
  * "data": [
94054
94826
  * {
94055
- * "key": "00000000-0000-4000-8000-000000005001",
94056
- * "label": "WhatsApp · Acme",
94057
- * "conversations": 5,
94058
- * "avg_first_response_seconds": 450.43,
94059
- * "avg_resolution_seconds": 101.4,
94060
- * "avg_customer_wait_seconds": 450.43,
94061
- * "resolutions": 1
94827
+ * "key": "__none__",
94828
+ * "label": "Sin etiqueta",
94829
+ * "conversations": 17,
94830
+ * "avg_first_response_seconds": 728.65,
94831
+ * "avg_resolution_seconds": 9891.67,
94832
+ * "avg_customer_wait_seconds": 728.65,
94833
+ * "resolutions": 4
94062
94834
  * },
94063
94835
  * {
94064
- * "key": "__none__",
94065
- * "label": "Directo / sin canal",
94066
- * "conversations": 4,
94836
+ * "key": "e1e1e1e1-9000-4000-8000-000000000001",
94837
+ * "label": "garantia",
94838
+ * "conversations": 1,
94067
94839
  * "avg_first_response_seconds": 0,
94068
94840
  * "avg_resolution_seconds": 0,
94069
94841
  * "avg_customer_wait_seconds": 0,
@@ -94154,7 +94926,7 @@ interface paths {
94154
94926
  patch?: never;
94155
94927
  trace?: never;
94156
94928
  };
94157
- "/insights/teams": {
94929
+ "/insights/channels": {
94158
94930
  parameters: {
94159
94931
  query?: never;
94160
94932
  header?: never;
@@ -94162,8 +94934,8 @@ interface paths {
94162
94934
  cookie?: never;
94163
94935
  };
94164
94936
  /**
94165
- * Volume by team
94166
- * @description Conversation counts grouped by the team they were routed to.
94937
+ * Volume by channel
94938
+ * @description Grouped by messaging channel (WhatsApp, Instagram, email, voice, …), so a channel with no traffic in the window is simply absent rather than present with a zero.
94167
94939
  */
94168
94940
  get: {
94169
94941
  parameters: {
@@ -94185,7 +94957,7 @@ interface paths {
94185
94957
  };
94186
94958
  requestBody?: never;
94187
94959
  responses: {
94188
- /** @description Volume by team */
94960
+ /** @description Volume by channel */
94189
94961
  200: {
94190
94962
  headers: {
94191
94963
  [name: string]: unknown;
@@ -94195,18 +94967,18 @@ interface paths {
94195
94967
  * @example {
94196
94968
  * "data": [
94197
94969
  * {
94198
- * "key": "__none__",
94199
- * "label": "Sin equipo",
94200
- * "conversations": 18,
94201
- * "avg_first_response_seconds": 728.65,
94202
- * "avg_resolution_seconds": 9891.67,
94203
- * "avg_customer_wait_seconds": 728.65,
94204
- * "resolutions": 4
94970
+ * "key": "00000000-0000-4000-8000-000000005001",
94971
+ * "label": "WhatsApp · Acme",
94972
+ * "conversations": 5,
94973
+ * "avg_first_response_seconds": 450.43,
94974
+ * "avg_resolution_seconds": 101.4,
94975
+ * "avg_customer_wait_seconds": 450.43,
94976
+ * "resolutions": 1
94205
94977
  * },
94206
94978
  * {
94207
- * "key": "cccccccc-0000-4000-8000-000000000001",
94208
- * "label": "Marketing",
94209
- * "conversations": 0,
94979
+ * "key": "__none__",
94980
+ * "label": "Directo / sin canal",
94981
+ * "conversations": 4,
94210
94982
  * "avg_first_response_seconds": 0,
94211
94983
  * "avg_resolution_seconds": 0,
94212
94984
  * "avg_customer_wait_seconds": 0,
@@ -94297,7 +95069,7 @@ interface paths {
94297
95069
  patch?: never;
94298
95070
  trace?: never;
94299
95071
  };
94300
- "/insights/sources": {
95072
+ "/insights/teams": {
94301
95073
  parameters: {
94302
95074
  query?: never;
94303
95075
  header?: never;
@@ -94305,8 +95077,8 @@ interface paths {
94305
95077
  cookie?: never;
94306
95078
  };
94307
95079
  /**
94308
- * Volume by origin
94309
- * @description The same row shape as `/insights/channels`, grouped by where the conversation CAME FROM (`mercadolibre`, `yapo`, `chileautos`, `ai_agent`, `website`, …) rather than which messaging account it rode in on. The two are not interchangeable: marketplace leads all arrive on the same WhatsApp number, so `/insights/channels` collapses every paid origin into one row. Unlike channels there is no catalogue to zero-fill from, so an origin with no traffic is absent rather than present with a zero; `__none__` is the no-origin bucket.
95080
+ * Volume by team
95081
+ * @description Conversation counts grouped by the team they were routed to.
94310
95082
  */
94311
95083
  get: {
94312
95084
  parameters: {
@@ -94328,7 +95100,7 @@ interface paths {
94328
95100
  };
94329
95101
  requestBody?: never;
94330
95102
  responses: {
94331
- /** @description Volume by origin */
95103
+ /** @description Volume by team */
94332
95104
  200: {
94333
95105
  headers: {
94334
95106
  [name: string]: unknown;
@@ -94339,17 +95111,17 @@ interface paths {
94339
95111
  * "data": [
94340
95112
  * {
94341
95113
  * "key": "__none__",
94342
- * "label": "Directo / sin origen",
94343
- * "conversations": 14,
95114
+ * "label": "Sin equipo",
95115
+ * "conversations": 18,
94344
95116
  * "avg_first_response_seconds": 728.65,
94345
95117
  * "avg_resolution_seconds": 9891.67,
94346
95118
  * "avg_customer_wait_seconds": 728.65,
94347
95119
  * "resolutions": 4
94348
95120
  * },
94349
95121
  * {
94350
- * "key": "website",
94351
- * "label": "Sitio web",
94352
- * "conversations": 4,
95122
+ * "key": "cccccccc-0000-4000-8000-000000000001",
95123
+ * "label": "Marketing",
95124
+ * "conversations": 0,
94353
95125
  * "avg_first_response_seconds": 0,
94354
95126
  * "avg_resolution_seconds": 0,
94355
95127
  * "avg_customer_wait_seconds": 0,
@@ -94440,7 +95212,7 @@ interface paths {
94440
95212
  patch?: never;
94441
95213
  trace?: never;
94442
95214
  };
94443
- "/insights/leads": {
95215
+ "/insights/sources": {
94444
95216
  parameters: {
94445
95217
  query?: never;
94446
95218
  header?: never;
@@ -94448,8 +95220,8 @@ interface paths {
94448
95220
  cookie?: never;
94449
95221
  };
94450
95222
  /**
94451
- * Lead capture
94452
- * @description Leads created over the window and where they came from.
95223
+ * Volume by origin
95224
+ * @description The same row shape as `/insights/channels`, grouped by where the conversation CAME FROM (`mercadolibre`, `yapo`, `chileautos`, `ai_agent`, `website`, …) rather than which messaging account it rode in on. The two are not interchangeable: marketplace leads all arrive on the same WhatsApp number, so `/insights/channels` collapses every paid origin into one row. Unlike channels there is no catalogue to zero-fill from, so an origin with no traffic is absent rather than present with a zero; `__none__` is the no-origin bucket.
94453
95225
  */
94454
95226
  get: {
94455
95227
  parameters: {
@@ -94471,7 +95243,7 @@ interface paths {
94471
95243
  };
94472
95244
  requestBody?: never;
94473
95245
  responses: {
94474
- /** @description Lead capture */
95246
+ /** @description Volume by origin */
94475
95247
  200: {
94476
95248
  headers: {
94477
95249
  [name: string]: unknown;
@@ -94479,60 +95251,26 @@ interface paths {
94479
95251
  content: {
94480
95252
  /**
94481
95253
  * @example {
94482
- * "data": {
94483
- * "open": 16,
94484
- * "won": 2,
94485
- * "lost": 1,
94486
- * "unqualified": 0,
94487
- * "total_value_open": 19407775,
94488
- * "total_value_won": 4500000,
94489
- * "total_value_open_by_currency": {
94490
- * "CLP": 19399000
94491
- * },
94492
- * "total_value_won_by_currency": {
94493
- * "CLP": 4500000
95254
+ * "data": [
95255
+ * {
95256
+ * "key": "__none__",
95257
+ * "label": "Directo / sin origen",
95258
+ * "conversations": 14,
95259
+ * "avg_first_response_seconds": 728.65,
95260
+ * "avg_resolution_seconds": 9891.67,
95261
+ * "avg_customer_wait_seconds": 728.65,
95262
+ * "resolutions": 4
94494
95263
  * },
94495
- * "is_mixed_currency": false,
94496
- * "is_mixed_currency_open": false,
94497
- * "win_rate": 0.67,
94498
- * "avg_cycle_seconds": 432000,
94499
- * "created_series": [
94500
- * {
94501
- * "bucket": "2026-09-22",
94502
- * "value": 6
94503
- * }
94504
- * ],
94505
- * "won_series": [
94506
- * {
94507
- * "bucket": "2026-09-22",
94508
- * "value": 1
94509
- * }
94510
- * ],
94511
- * "revenue_series": [
94512
- * {
94513
- * "bucket": "2026-09-22",
94514
- * "value": 4500000,
94515
- * "value_by_currency": {
94516
- * "CLP": 4500000
94517
- * },
94518
- * "is_mixed_currency": false
94519
- * }
94520
- * ],
94521
- * "funnel": [
94522
- * {
94523
- * "stage_id": "55555555-0000-4000-8000-000000000001",
94524
- * "stage_name": "Nuevo",
94525
- * "position": 0,
94526
- * "open_count": 9,
94527
- * "total_value": 19401030,
94528
- * "total_value_by_currency": {
94529
- * "CLP": 19399000
94530
- * },
94531
- * "is_mixed_currency": false,
94532
- * "median_time_in_stage_hours": 6.5
94533
- * }
94534
- * ]
94535
- * },
95264
+ * {
95265
+ * "key": "website",
95266
+ * "label": "Sitio web",
95267
+ * "conversations": 4,
95268
+ * "avg_first_response_seconds": 0,
95269
+ * "avg_resolution_seconds": 0,
95270
+ * "avg_customer_wait_seconds": 0,
95271
+ * "resolutions": 0
95272
+ * }
95273
+ * ],
94536
95274
  * "meta": {
94537
95275
  * "window": {
94538
95276
  * "kind": "rolling",
@@ -94617,7 +95355,7 @@ interface paths {
94617
95355
  patch?: never;
94618
95356
  trace?: never;
94619
95357
  };
94620
- "/insights/csat": {
95358
+ "/insights/leads": {
94621
95359
  parameters: {
94622
95360
  query?: never;
94623
95361
  header?: never;
@@ -94625,8 +95363,8 @@ interface paths {
94625
95363
  cookie?: never;
94626
95364
  };
94627
95365
  /**
94628
- * Estimated satisfaction
94629
- * @description CSAT is AI-ESTIMATED from the conversation, not collected from a survey — no customer was asked to rate anything. Read it as a model judgement about tone and outcome, which is why it exists for every conversation rather than the small fraction that would answer a survey.
95366
+ * Lead capture
95367
+ * @description Leads created over the window and where they came from.
94630
95368
  */
94631
95369
  get: {
94632
95370
  parameters: {
@@ -94648,7 +95386,7 @@ interface paths {
94648
95386
  };
94649
95387
  requestBody?: never;
94650
95388
  responses: {
94651
- /** @description Estimated satisfaction */
95389
+ /** @description Lead capture */
94652
95390
  200: {
94653
95391
  headers: {
94654
95392
  [name: string]: unknown;
@@ -94657,27 +95395,58 @@ interface paths {
94657
95395
  /**
94658
95396
  * @example {
94659
95397
  * "data": {
94660
- * "total_responses": 9,
94661
- * "satisfaction_score": 0.82,
94662
- * "response_rate": 0.5,
94663
- * "positive": 7,
94664
- * "neutral": 1,
94665
- * "negative": 1,
94666
- * "recommend_rate": 0.78,
94667
- * "avg_confidence": 0.9,
94668
- * "review_requests_sent": 18,
94669
- * "resolved_tickets": 5,
94670
- * "distribution": {
94671
- * "positive": 7,
94672
- * "neutral": 1,
94673
- * "negative": 1
95398
+ * "open": 16,
95399
+ * "won": 2,
95400
+ * "lost": 1,
95401
+ * "unqualified": 0,
95402
+ * "total_value_open": 19407775,
95403
+ * "total_value_won": 4500000,
95404
+ * "total_value_open_by_currency": {
95405
+ * "CLP": 19399000
94674
95406
  * },
94675
- * "resolution_quality": {
94676
- * "good": 8,
94677
- * "poor": 1
95407
+ * "total_value_won_by_currency": {
95408
+ * "CLP": 4500000
94678
95409
  * },
94679
- * "agent_performance": {},
94680
- * "recent": []
95410
+ * "is_mixed_currency": false,
95411
+ * "is_mixed_currency_open": false,
95412
+ * "win_rate": 0.67,
95413
+ * "avg_cycle_seconds": 432000,
95414
+ * "created_series": [
95415
+ * {
95416
+ * "bucket": "2026-09-22",
95417
+ * "value": 6
95418
+ * }
95419
+ * ],
95420
+ * "won_series": [
95421
+ * {
95422
+ * "bucket": "2026-09-22",
95423
+ * "value": 1
95424
+ * }
95425
+ * ],
95426
+ * "revenue_series": [
95427
+ * {
95428
+ * "bucket": "2026-09-22",
95429
+ * "value": 4500000,
95430
+ * "value_by_currency": {
95431
+ * "CLP": 4500000
95432
+ * },
95433
+ * "is_mixed_currency": false
95434
+ * }
95435
+ * ],
95436
+ * "funnel": [
95437
+ * {
95438
+ * "stage_id": "55555555-0000-4000-8000-000000000001",
95439
+ * "stage_name": "Nuevo",
95440
+ * "position": 0,
95441
+ * "open_count": 9,
95442
+ * "total_value": 19401030,
95443
+ * "total_value_by_currency": {
95444
+ * "CLP": 19399000
95445
+ * },
95446
+ * "is_mixed_currency": false,
95447
+ * "median_time_in_stage_hours": 6.5
95448
+ * }
95449
+ * ]
94681
95450
  * },
94682
95451
  * "meta": {
94683
95452
  * "window": {
@@ -94763,7 +95532,7 @@ interface paths {
94763
95532
  patch?: never;
94764
95533
  trace?: never;
94765
95534
  };
94766
- "/insights/sla": {
95535
+ "/insights/csat": {
94767
95536
  parameters: {
94768
95537
  query?: never;
94769
95538
  header?: never;
@@ -94771,8 +95540,8 @@ interface paths {
94771
95540
  cookie?: never;
94772
95541
  };
94773
95542
  /**
94774
- * SLA compliance
94775
- * @description Breach and compliance counts against the workspace SLA policies. A window with no policy configured reports nothing to comply with, not full compliance.
95543
+ * Estimated satisfaction
95544
+ * @description CSAT is AI-ESTIMATED from the conversation, not collected from a survey — no customer was asked to rate anything. Read it as a model judgement about tone and outcome, which is why it exists for every conversation rather than the small fraction that would answer a survey.
94776
95545
  */
94777
95546
  get: {
94778
95547
  parameters: {
@@ -94794,7 +95563,7 @@ interface paths {
94794
95563
  };
94795
95564
  requestBody?: never;
94796
95565
  responses: {
94797
- /** @description SLA compliance */
95566
+ /** @description Estimated satisfaction */
94798
95567
  200: {
94799
95568
  headers: {
94800
95569
  [name: string]: unknown;
@@ -94803,32 +95572,178 @@ interface paths {
94803
95572
  /**
94804
95573
  * @example {
94805
95574
  * "data": {
94806
- * "has_policies": true,
94807
- * "policy_count": 2,
94808
- * "target_first_response_minutes": 15,
94809
- * "target_resolution_minutes": 480,
94810
- * "tracked": 18,
94811
- * "breached": 2,
94812
- * "hits": 16,
94813
- * "hit_rate": 0.89,
94814
- * "first_response": {
94815
- * "evaluated": 18,
94816
- * "breached": 1,
94817
- * "hit_rate": 0.94
95575
+ * "total_responses": 9,
95576
+ * "satisfaction_score": 0.82,
95577
+ * "response_rate": 0.5,
95578
+ * "positive": 7,
95579
+ * "neutral": 1,
95580
+ * "negative": 1,
95581
+ * "recommend_rate": 0.78,
95582
+ * "avg_confidence": 0.9,
95583
+ * "review_requests_sent": 18,
95584
+ * "resolved_tickets": 5,
95585
+ * "distribution": {
95586
+ * "positive": 7,
95587
+ * "neutral": 1,
95588
+ * "negative": 1
94818
95589
  * },
94819
- * "resolution": {
94820
- * "evaluated": 5,
94821
- * "breached": 1,
94822
- * "hit_rate": 0.8
95590
+ * "resolution_quality": {
95591
+ * "good": 8,
95592
+ * "poor": 1
94823
95593
  * },
94824
- * "by_policy": [
94825
- * {
94826
- * "policy_id": "cccccccc-1000-4000-8000-000000000001",
94827
- * "name": "SLA estándar",
94828
- * "hit_rate": 0.89
94829
- * }
94830
- * ],
94831
- * "breaches": []
95594
+ * "agent_performance": {},
95595
+ * "recent": []
95596
+ * },
95597
+ * "meta": {
95598
+ * "window": {
95599
+ * "kind": "rolling",
95600
+ * "preset": "7d",
95601
+ * "hours": 168,
95602
+ * "from": "2026-09-15T16:38:51.000Z",
95603
+ * "to": "2026-09-22T16:38:51.000Z",
95604
+ * "label": "últimos 7d"
95605
+ * }
95606
+ * }
95607
+ * }
95608
+ */
95609
+ "application/json": {
95610
+ data?: unknown;
95611
+ meta?: {
95612
+ [key: string]: unknown;
95613
+ };
95614
+ };
95615
+ };
95616
+ };
95617
+ /** @description Validation error */
95618
+ 400: {
95619
+ headers: {
95620
+ [name: string]: unknown;
95621
+ };
95622
+ content: {
95623
+ "application/json": components["schemas"]["Error"];
95624
+ };
95625
+ };
95626
+ /** @description Unauthorized */
95627
+ 401: {
95628
+ headers: {
95629
+ [name: string]: unknown;
95630
+ };
95631
+ content: {
95632
+ "application/json": components["schemas"]["Error"];
95633
+ };
95634
+ };
95635
+ /** @description Forbidden */
95636
+ 403: {
95637
+ headers: {
95638
+ [name: string]: unknown;
95639
+ };
95640
+ content: {
95641
+ "application/json": components["schemas"]["Error"];
95642
+ };
95643
+ };
95644
+ /** @description Not found */
95645
+ 404: {
95646
+ headers: {
95647
+ [name: string]: unknown;
95648
+ };
95649
+ content: {
95650
+ "application/json": components["schemas"]["Error"];
95651
+ };
95652
+ };
95653
+ /** @description Conflict (incl. Idempotency-Key reuse with different body) */
95654
+ 409: {
95655
+ headers: {
95656
+ [name: string]: unknown;
95657
+ };
95658
+ content: {
95659
+ "application/json": components["schemas"]["Error"];
95660
+ };
95661
+ };
95662
+ /** @description Rate limited */
95663
+ 429: {
95664
+ headers: {
95665
+ [name: string]: unknown;
95666
+ };
95667
+ content: {
95668
+ "application/json": components["schemas"]["Error"];
95669
+ };
95670
+ };
95671
+ };
95672
+ };
95673
+ put?: never;
95674
+ post?: never;
95675
+ delete?: never;
95676
+ options?: never;
95677
+ head?: never;
95678
+ patch?: never;
95679
+ trace?: never;
95680
+ };
95681
+ "/insights/sla": {
95682
+ parameters: {
95683
+ query?: never;
95684
+ header?: never;
95685
+ path?: never;
95686
+ cookie?: never;
95687
+ };
95688
+ /**
95689
+ * SLA compliance
95690
+ * @description Breach and compliance counts against the workspace SLA policies. A window with no policy configured reports nothing to comply with, not full compliance.
95691
+ */
95692
+ get: {
95693
+ parameters: {
95694
+ query?: {
95695
+ /** @description Which period. Omit it (with `from`/`to`) for an explicit range — the shape every ranged Insights report has always accepted, and which still works unchanged. The calendar windows are the DEALERSHIP’s (America/Santiago), so a month closes when a person would say it closed. */
95696
+ window?: "24h" | "7d" | "30d" | "90d" | "calendar_month" | "calendar_year" | "custom";
95697
+ /** @description `window=calendar_month` only. ISO month, `YYYY-MM`. Defaults to the month in progress. */
95698
+ month?: string;
95699
+ /** @description `window=calendar_year` only. `YYYY`. Defaults to the year in progress. */
95700
+ year?: string;
95701
+ /** @description Explicit range only. Checked for non-emptiness and handed to Postgres, so a malformed value surfaces as a 500 from the query rather than a 400 from the edge — send an ISO-8601 instant. */
95702
+ from?: string;
95703
+ /** @description Explicit range only. ISO instant, see `from`. */
95704
+ to?: string;
95705
+ };
95706
+ header?: never;
95707
+ path?: never;
95708
+ cookie?: never;
95709
+ };
95710
+ requestBody?: never;
95711
+ responses: {
95712
+ /** @description SLA compliance */
95713
+ 200: {
95714
+ headers: {
95715
+ [name: string]: unknown;
95716
+ };
95717
+ content: {
95718
+ /**
95719
+ * @example {
95720
+ * "data": {
95721
+ * "has_policies": true,
95722
+ * "policy_count": 2,
95723
+ * "target_first_response_minutes": 15,
95724
+ * "target_resolution_minutes": 480,
95725
+ * "tracked": 18,
95726
+ * "breached": 2,
95727
+ * "hits": 16,
95728
+ * "hit_rate": 0.89,
95729
+ * "first_response": {
95730
+ * "evaluated": 18,
95731
+ * "breached": 1,
95732
+ * "hit_rate": 0.94
95733
+ * },
95734
+ * "resolution": {
95735
+ * "evaluated": 5,
95736
+ * "breached": 1,
95737
+ * "hit_rate": 0.8
95738
+ * },
95739
+ * "by_policy": [
95740
+ * {
95741
+ * "policy_id": "cccccccc-1000-4000-8000-000000000001",
95742
+ * "name": "SLA estándar",
95743
+ * "hit_rate": 0.89
95744
+ * }
95745
+ * ],
95746
+ * "breaches": []
94832
95747
  * },
94833
95748
  * "meta": {
94834
95749
  * "window": {
@@ -97321,6 +98236,593 @@ interface paths {
97321
98236
  patch?: never;
97322
98237
  trace?: never;
97323
98238
  };
98239
+ "/ads/report": {
98240
+ parameters: {
98241
+ query?: never;
98242
+ header?: never;
98243
+ path?: never;
98244
+ cookie?: never;
98245
+ };
98246
+ /**
98247
+ * Reporte: campaigns, ad sets or ads with their funnel, costs and cash return
98248
+ * @description One table at `level` (campaign, ad set or ad) for the window. Per row: the spend and the cash credited by the attribution engine, Vitrina’s own conversational funnel (conversations each ad opened → answered → citas → attended → closes) with the cost of each step, «Retorno» = cash ÷ spend (`null` when no payment was recorded in the period), and Meta’s own figures apart. `tail` holds the period’s conversations with no ad behind them, so from-ads + tail = the workspace total; `reconciliation` states Σ spend against `/ads/overview`. A failed read is `null`, never 0.
98249
+ */
98250
+ get: {
98251
+ parameters: {
98252
+ query: {
98253
+ /** @description Window start (inclusive), YYYY-MM-DD. */
98254
+ from: string;
98255
+ /** @description Window end (inclusive), YYYY-MM-DD. */
98256
+ to: string;
98257
+ /** @description The attribution model. Defaults to `last_touch`. */
98258
+ model?: string;
98259
+ /** @description `1` serves the deterministic sample dataset («Ver con datos de ejemplo»): same shapes, invented but internally consistent figures, no entitlement required (the scope still is). A sandbox workspace is always served the sample, with or without this parameter. */
98260
+ sample?: "1" | "true";
98261
+ /** @description Campaña, conjunto (ad set) or anuncio. Default `campaign`. */
98262
+ level?: "campaign" | "ad_set" | "ad";
98263
+ };
98264
+ header?: never;
98265
+ path?: never;
98266
+ cookie?: never;
98267
+ };
98268
+ requestBody?: never;
98269
+ responses: {
98270
+ /** @description The report at the requested level */
98271
+ 200: {
98272
+ headers: {
98273
+ [name: string]: unknown;
98274
+ };
98275
+ content: {
98276
+ /**
98277
+ * @example {
98278
+ * "data": {
98279
+ * "level": "campaign",
98280
+ * "window": {
98281
+ * "from": "2026-08-30",
98282
+ * "to": "2026-09-28"
98283
+ * },
98284
+ * "rows": [
98285
+ * {
98286
+ * "external_id": "120211000000000001",
98287
+ * "level": "campaign",
98288
+ * "name": "Implantes · Septiembre",
98289
+ * "parent": null,
98290
+ * "thumbnail_url": null,
98291
+ * "spark": [
98292
+ * 13200,
98293
+ * 14100,
98294
+ * 13900
98295
+ * ],
98296
+ * "spend": 412300,
98297
+ * "funnel": {
98298
+ * "conversations": 120,
98299
+ * "replied": 110,
98300
+ * "appointments": 20,
98301
+ * "attended": 12,
98302
+ * "closes": 2
98303
+ * },
98304
+ * "cost_per": {
98305
+ * "conversation": 3436,
98306
+ * "appointment": 20615,
98307
+ * "attended": 34358,
98308
+ * "close": 206150
98309
+ * },
98310
+ * "cash": 0,
98311
+ * "return": null,
98312
+ * "meta": {
98313
+ * "conversations_started": 131,
98314
+ * "cost_per_conversation": 3147
98315
+ * }
98316
+ * }
98317
+ * ],
98318
+ * "tail": [
98319
+ * {
98320
+ * "key": "direct",
98321
+ * "conversations": 210
98322
+ * },
98323
+ * {
98324
+ * "key": "website",
98325
+ * "conversations": 40
98326
+ * }
98327
+ * ],
98328
+ * "totals": {
98329
+ * "spend": 412300,
98330
+ * "funnel": {
98331
+ * "conversations": 120,
98332
+ * "replied": 110,
98333
+ * "appointments": 20,
98334
+ * "attended": 12,
98335
+ * "closes": 2
98336
+ * },
98337
+ * "cost_per": {
98338
+ * "conversation": 3436,
98339
+ * "appointment": 20615,
98340
+ * "attended": 34358,
98341
+ * "close": 206150
98342
+ * },
98343
+ * "cash": 0,
98344
+ * "return": null,
98345
+ * "meta": {
98346
+ * "conversations_started": 131,
98347
+ * "cost_per_conversation": 3147
98348
+ * }
98349
+ * },
98350
+ * "pipeline": {
98351
+ * "closed_count": 3,
98352
+ * "closed_value": 93082
98353
+ * },
98354
+ * "cash_recorded": false,
98355
+ * "reconciliation": {
98356
+ * "overview_spend": 412300,
98357
+ * "spend_matches": true,
98358
+ * "conversations_total": 370,
98359
+ * "conversations_from_ads": 120,
98360
+ * "conversations_without_ad": 250
98361
+ * }
98362
+ * }
98363
+ * }
98364
+ */
98365
+ "application/json": {
98366
+ data: components["schemas"]["AdsReport"];
98367
+ };
98368
+ };
98369
+ };
98370
+ /** @description Validation error */
98371
+ 400: {
98372
+ headers: {
98373
+ [name: string]: unknown;
98374
+ };
98375
+ content: {
98376
+ "application/json": components["schemas"]["Error"];
98377
+ };
98378
+ };
98379
+ /** @description Unauthorized */
98380
+ 401: {
98381
+ headers: {
98382
+ [name: string]: unknown;
98383
+ };
98384
+ content: {
98385
+ "application/json": components["schemas"]["Error"];
98386
+ };
98387
+ };
98388
+ /** @description Vitrina Ads is not active for this workspace. `error.code` is `ENTITLEMENT_NOT_ACTIVE`, `error.details.feature` is `vitrina_ads`. */
98389
+ 402: {
98390
+ headers: {
98391
+ [name: string]: unknown;
98392
+ };
98393
+ content: {
98394
+ /**
98395
+ * @example {
98396
+ * "error": {
98397
+ * "code": "ENTITLEMENT_NOT_ACTIVE",
98398
+ * "message": "El complemento Vitrina Ads no está activo en este espacio de trabajo.",
98399
+ * "details": {
98400
+ * "required": [
98401
+ * "vitrina_ads"
98402
+ * ],
98403
+ * "active": [],
98404
+ * "feature": "vitrina_ads",
98405
+ * "entitlement_state": "off"
98406
+ * }
98407
+ * }
98408
+ * }
98409
+ */
98410
+ "application/json": components["schemas"]["Error"];
98411
+ };
98412
+ };
98413
+ /** @description Forbidden */
98414
+ 403: {
98415
+ headers: {
98416
+ [name: string]: unknown;
98417
+ };
98418
+ content: {
98419
+ "application/json": components["schemas"]["Error"];
98420
+ };
98421
+ };
98422
+ /** @description Not found */
98423
+ 404: {
98424
+ headers: {
98425
+ [name: string]: unknown;
98426
+ };
98427
+ content: {
98428
+ "application/json": components["schemas"]["Error"];
98429
+ };
98430
+ };
98431
+ /** @description Vitrina Ads is active but the delegated key has not finished rotating (`ADS_KEY_NEEDS_REMINT`) — retry once `GET /ads/state` reports `needs_remint: false`. Also the generic conflict of a write. */
98432
+ 409: {
98433
+ headers: {
98434
+ [name: string]: unknown;
98435
+ };
98436
+ content: {
98437
+ /**
98438
+ * @example {
98439
+ * "error": {
98440
+ * "code": "ADS_KEY_NEEDS_REMINT",
98441
+ * "message": "Vitrina Ads is active but the delegated key has not finished rotating (key_kind: core)",
98442
+ * "details": {
98443
+ * "key_kind": "core"
98444
+ * }
98445
+ * }
98446
+ * }
98447
+ */
98448
+ "application/json": components["schemas"]["Error"];
98449
+ };
98450
+ };
98451
+ /** @description Rate limited */
98452
+ 429: {
98453
+ headers: {
98454
+ [name: string]: unknown;
98455
+ };
98456
+ content: {
98457
+ "application/json": components["schemas"]["Error"];
98458
+ };
98459
+ };
98460
+ };
98461
+ };
98462
+ put?: never;
98463
+ post?: never;
98464
+ delete?: never;
98465
+ options?: never;
98466
+ head?: never;
98467
+ patch?: never;
98468
+ trace?: never;
98469
+ };
98470
+ "/ads/report/export": {
98471
+ parameters: {
98472
+ query?: never;
98473
+ header?: never;
98474
+ path?: never;
98475
+ cookie?: never;
98476
+ };
98477
+ /**
98478
+ * Export the Reporte (aggregates only)
98479
+ * @description The same table as `GET /ads/report`, as a file. CSV: `;`, Spanish headers, `dd-mm-aaaa` dates, a preamble with the period, the model and «Retorno = caja». XLSX: the table plus a «Notas» sheet. No row names a person. Audited as `ads.report.export`.
98480
+ */
98481
+ get: {
98482
+ parameters: {
98483
+ query: {
98484
+ /** @description Window start (inclusive), YYYY-MM-DD. */
98485
+ from: string;
98486
+ /** @description Window end (inclusive), YYYY-MM-DD. */
98487
+ to: string;
98488
+ /** @description The attribution model. Defaults to `last_touch`. */
98489
+ model?: string;
98490
+ /** @description `1` serves the deterministic sample dataset («Ver con datos de ejemplo»): same shapes, invented but internally consistent figures, no entitlement required (the scope still is). A sandbox workspace is always served the sample, with or without this parameter. */
98491
+ sample?: "1" | "true";
98492
+ /** @description Campaña, conjunto (ad set) or anuncio. Default `campaign`. */
98493
+ level?: "campaign" | "ad_set" | "ad";
98494
+ /** @description `csv`: `;`-separated, Spanish headers, `dd-mm-aaaa` dates, a preamble with the period, the model and «Retorno = caja». `xlsx`: the same table plus a «Notas» sheet. Aggregates only — no person rows. */
98495
+ format?: "csv" | "xlsx";
98496
+ };
98497
+ header?: never;
98498
+ path?: never;
98499
+ cookie?: never;
98500
+ };
98501
+ requestBody?: never;
98502
+ responses: {
98503
+ /** @description The file */
98504
+ 200: {
98505
+ headers: {
98506
+ [name: string]: unknown;
98507
+ };
98508
+ content: {
98509
+ "text/csv": string;
98510
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": string;
98511
+ };
98512
+ };
98513
+ /** @description Validation error */
98514
+ 400: {
98515
+ headers: {
98516
+ [name: string]: unknown;
98517
+ };
98518
+ content: {
98519
+ "application/json": components["schemas"]["Error"];
98520
+ };
98521
+ };
98522
+ /** @description Unauthorized */
98523
+ 401: {
98524
+ headers: {
98525
+ [name: string]: unknown;
98526
+ };
98527
+ content: {
98528
+ "application/json": components["schemas"]["Error"];
98529
+ };
98530
+ };
98531
+ /** @description Vitrina Ads is not active for this workspace. `error.code` is `ENTITLEMENT_NOT_ACTIVE`, `error.details.feature` is `vitrina_ads`. */
98532
+ 402: {
98533
+ headers: {
98534
+ [name: string]: unknown;
98535
+ };
98536
+ content: {
98537
+ /**
98538
+ * @example {
98539
+ * "error": {
98540
+ * "code": "ENTITLEMENT_NOT_ACTIVE",
98541
+ * "message": "El complemento Vitrina Ads no está activo en este espacio de trabajo.",
98542
+ * "details": {
98543
+ * "required": [
98544
+ * "vitrina_ads"
98545
+ * ],
98546
+ * "active": [],
98547
+ * "feature": "vitrina_ads",
98548
+ * "entitlement_state": "off"
98549
+ * }
98550
+ * }
98551
+ * }
98552
+ */
98553
+ "application/json": components["schemas"]["Error"];
98554
+ };
98555
+ };
98556
+ /** @description Forbidden */
98557
+ 403: {
98558
+ headers: {
98559
+ [name: string]: unknown;
98560
+ };
98561
+ content: {
98562
+ "application/json": components["schemas"]["Error"];
98563
+ };
98564
+ };
98565
+ /** @description Not found */
98566
+ 404: {
98567
+ headers: {
98568
+ [name: string]: unknown;
98569
+ };
98570
+ content: {
98571
+ "application/json": components["schemas"]["Error"];
98572
+ };
98573
+ };
98574
+ /** @description Vitrina Ads is active but the delegated key has not finished rotating (`ADS_KEY_NEEDS_REMINT`) — retry once `GET /ads/state` reports `needs_remint: false`. Also the generic conflict of a write. */
98575
+ 409: {
98576
+ headers: {
98577
+ [name: string]: unknown;
98578
+ };
98579
+ content: {
98580
+ /**
98581
+ * @example {
98582
+ * "error": {
98583
+ * "code": "ADS_KEY_NEEDS_REMINT",
98584
+ * "message": "Vitrina Ads is active but the delegated key has not finished rotating (key_kind: core)",
98585
+ * "details": {
98586
+ * "key_kind": "core"
98587
+ * }
98588
+ * }
98589
+ * }
98590
+ */
98591
+ "application/json": components["schemas"]["Error"];
98592
+ };
98593
+ };
98594
+ /** @description Rate limited */
98595
+ 429: {
98596
+ headers: {
98597
+ [name: string]: unknown;
98598
+ };
98599
+ content: {
98600
+ "application/json": components["schemas"]["Error"];
98601
+ };
98602
+ };
98603
+ };
98604
+ };
98605
+ put?: never;
98606
+ post?: never;
98607
+ delete?: never;
98608
+ options?: never;
98609
+ head?: never;
98610
+ patch?: never;
98611
+ trace?: never;
98612
+ };
98613
+ "/ads/ads/{id}": {
98614
+ parameters: {
98615
+ query?: never;
98616
+ header?: never;
98617
+ path?: never;
98618
+ cookie?: never;
98619
+ };
98620
+ /**
98621
+ * The ad sheet: creative, funnel and the people it brought (masked)
98622
+ * @description One ad: the creative and delivery metrics, the SAME funnel/costs/cash as its Reporte row for the window, and the conversations it opened (a label, the furthest stage, its value). Never a phone or an e-mail; for healthcare the label is always initials. There is no export of people.
98623
+ */
98624
+ get: {
98625
+ parameters: {
98626
+ query: {
98627
+ /** @description Window start (inclusive), YYYY-MM-DD. */
98628
+ from: string;
98629
+ /** @description Window end (inclusive), YYYY-MM-DD. */
98630
+ to: string;
98631
+ /** @description The attribution model. Defaults to `last_touch`. */
98632
+ model?: string;
98633
+ /** @description `1` serves the deterministic sample dataset («Ver con datos de ejemplo»): same shapes, invented but internally consistent figures, no entitlement required (the scope still is). A sandbox workspace is always served the sample, with or without this parameter. */
98634
+ sample?: "1" | "true";
98635
+ };
98636
+ header?: never;
98637
+ path: {
98638
+ id: string;
98639
+ };
98640
+ cookie?: never;
98641
+ };
98642
+ requestBody?: never;
98643
+ responses: {
98644
+ /** @description The ad sheet */
98645
+ 200: {
98646
+ headers: {
98647
+ [name: string]: unknown;
98648
+ };
98649
+ content: {
98650
+ /**
98651
+ * @example {
98652
+ * "data": {
98653
+ * "ad": {
98654
+ * "external_id": "120212000000000009",
98655
+ * "name": "Video testimonio 15s",
98656
+ * "ad_set": {
98657
+ * "external_id": "120213000000000004",
98658
+ * "name": "INTERESES"
98659
+ * },
98660
+ * "campaign": {
98661
+ * "external_id": "120211000000000001"
98662
+ * },
98663
+ * "thumbnail_url": null,
98664
+ * "title": "Implantes en un día",
98665
+ * "body": "Agenda tu evaluación.",
98666
+ * "has_video": true,
98667
+ * "spend": 168000,
98668
+ * "impressions": 24100,
98669
+ * "clicks": 337,
98670
+ * "ctr": 1.4,
98671
+ * "cpm": 6971,
98672
+ * "cpc": 498,
98673
+ * "cash_count": 0,
98674
+ * "cash_value": 0,
98675
+ * "meta_conversations_started": 22
98676
+ * },
98677
+ * "window": {
98678
+ * "from": "2026-08-30",
98679
+ * "to": "2026-09-28"
98680
+ * },
98681
+ * "row": {
98682
+ * "spend": 412300,
98683
+ * "funnel": {
98684
+ * "conversations": 120,
98685
+ * "replied": 110,
98686
+ * "appointments": 20,
98687
+ * "attended": 12,
98688
+ * "closes": 2
98689
+ * },
98690
+ * "cost_per": {
98691
+ * "conversation": 3436,
98692
+ * "appointment": 20615,
98693
+ * "attended": 34358,
98694
+ * "close": 206150
98695
+ * },
98696
+ * "cash": 0,
98697
+ * "return": null,
98698
+ * "meta": {
98699
+ * "conversations_started": 131,
98700
+ * "cost_per_conversation": 3147
98701
+ * }
98702
+ * },
98703
+ * "cash_recorded": false,
98704
+ * "people": [
98705
+ * {
98706
+ * "conversation_id": "00000000-0000-4000-8000-00000000c0a1",
98707
+ * "contact_id": "00000000-0000-4000-8000-00000000c0a2",
98708
+ * "label": "M. R.",
98709
+ * "masked": true,
98710
+ * "stage": "closed_won",
98711
+ * "stage_at": "2026-09-25T15:00:00.000Z",
98712
+ * "opened_at": "2026-09-20T13:10:00.000Z",
98713
+ * "value": 1250000
98714
+ * }
98715
+ * ],
98716
+ * "people_more": false,
98717
+ * "people_hidden": false
98718
+ * }
98719
+ * }
98720
+ */
98721
+ "application/json": {
98722
+ data: components["schemas"]["AdsAdSheet"];
98723
+ };
98724
+ };
98725
+ };
98726
+ /** @description Validation error */
98727
+ 400: {
98728
+ headers: {
98729
+ [name: string]: unknown;
98730
+ };
98731
+ content: {
98732
+ "application/json": components["schemas"]["Error"];
98733
+ };
98734
+ };
98735
+ /** @description Unauthorized */
98736
+ 401: {
98737
+ headers: {
98738
+ [name: string]: unknown;
98739
+ };
98740
+ content: {
98741
+ "application/json": components["schemas"]["Error"];
98742
+ };
98743
+ };
98744
+ /** @description Vitrina Ads is not active for this workspace. `error.code` is `ENTITLEMENT_NOT_ACTIVE`, `error.details.feature` is `vitrina_ads`. */
98745
+ 402: {
98746
+ headers: {
98747
+ [name: string]: unknown;
98748
+ };
98749
+ content: {
98750
+ /**
98751
+ * @example {
98752
+ * "error": {
98753
+ * "code": "ENTITLEMENT_NOT_ACTIVE",
98754
+ * "message": "El complemento Vitrina Ads no está activo en este espacio de trabajo.",
98755
+ * "details": {
98756
+ * "required": [
98757
+ * "vitrina_ads"
98758
+ * ],
98759
+ * "active": [],
98760
+ * "feature": "vitrina_ads",
98761
+ * "entitlement_state": "off"
98762
+ * }
98763
+ * }
98764
+ * }
98765
+ */
98766
+ "application/json": components["schemas"]["Error"];
98767
+ };
98768
+ };
98769
+ /** @description Forbidden */
98770
+ 403: {
98771
+ headers: {
98772
+ [name: string]: unknown;
98773
+ };
98774
+ content: {
98775
+ "application/json": components["schemas"]["Error"];
98776
+ };
98777
+ };
98778
+ /** @description Not found */
98779
+ 404: {
98780
+ headers: {
98781
+ [name: string]: unknown;
98782
+ };
98783
+ content: {
98784
+ "application/json": components["schemas"]["Error"];
98785
+ };
98786
+ };
98787
+ /** @description Vitrina Ads is active but the delegated key has not finished rotating (`ADS_KEY_NEEDS_REMINT`) — retry once `GET /ads/state` reports `needs_remint: false`. Also the generic conflict of a write. */
98788
+ 409: {
98789
+ headers: {
98790
+ [name: string]: unknown;
98791
+ };
98792
+ content: {
98793
+ /**
98794
+ * @example {
98795
+ * "error": {
98796
+ * "code": "ADS_KEY_NEEDS_REMINT",
98797
+ * "message": "Vitrina Ads is active but the delegated key has not finished rotating (key_kind: core)",
98798
+ * "details": {
98799
+ * "key_kind": "core"
98800
+ * }
98801
+ * }
98802
+ * }
98803
+ */
98804
+ "application/json": components["schemas"]["Error"];
98805
+ };
98806
+ };
98807
+ /** @description Rate limited */
98808
+ 429: {
98809
+ headers: {
98810
+ [name: string]: unknown;
98811
+ };
98812
+ content: {
98813
+ "application/json": components["schemas"]["Error"];
98814
+ };
98815
+ };
98816
+ };
98817
+ };
98818
+ put?: never;
98819
+ post?: never;
98820
+ delete?: never;
98821
+ options?: never;
98822
+ head?: never;
98823
+ patch?: never;
98824
+ trace?: never;
98825
+ };
97324
98826
  "/ads/overview": {
97325
98827
  parameters: {
97326
98828
  query?: never;
@@ -97906,6 +99408,17 @@ interface paths {
97906
99408
  * "attributed_outcomes": 1,
97907
99409
  * "partial": false
97908
99410
  * }
99411
+ * ],
99412
+ * "gaps": [
99413
+ * {
99414
+ * "from": "2026-09-12",
99415
+ * "to": "2026-09-15",
99416
+ * "cause": "meta_disconnected",
99417
+ * "metrics": [
99418
+ * "spend"
99419
+ * ],
99420
+ * "incident_id": "b1b1b1b1-0000-4000-8000-000000000002"
99421
+ * }
97909
99422
  * ]
97910
99423
  * }
97911
99424
  * }
@@ -98015,6 +99528,186 @@ interface paths {
98015
99528
  patch?: never;
98016
99529
  trace?: never;
98017
99530
  };
99531
+ "/ads/measurement": {
99532
+ parameters: {
99533
+ query?: never;
99534
+ header?: never;
99535
+ path?: never;
99536
+ cookie?: never;
99537
+ };
99538
+ /**
99539
+ * Measurement incidents: what stopped measuring, since when
99540
+ * @description The measurement watchdog’s ledger (W1.1, «Vigilancia de la medición»). `open` are the legs broken right now — the Meta ad account read (disconnected or stale), the site tag’s heartbeat, the Conversions API sends, a WhatsApp channel, clinic facts not reaching the attribution — each with the day the data stopped and its ONE fix (`action.path`). `recent` are the ones resolved in the last 14 days, with who fixed them.
99541
+ *
99542
+ * The owner and admins are told by WhatsApp and email at +0 h, +3 d and +7 d while an incident stays open. `/ads/overview` and `/ads/campaigns` carry the same incidents as `gaps` over their window.
99543
+ */
99544
+ get: {
99545
+ parameters: {
99546
+ query?: {
99547
+ /** @description `1` serves the deterministic sample dataset («Ver con datos de ejemplo»): same shapes, invented but internally consistent figures, no entitlement required (the scope still is). A sandbox workspace is always served the sample, with or without this parameter. */
99548
+ sample?: "1" | "true";
99549
+ };
99550
+ header?: never;
99551
+ path?: never;
99552
+ cookie?: never;
99553
+ };
99554
+ requestBody?: never;
99555
+ responses: {
99556
+ /** @description Open and recently resolved incidents */
99557
+ 200: {
99558
+ headers: {
99559
+ [name: string]: unknown;
99560
+ };
99561
+ content: {
99562
+ /**
99563
+ * @example {
99564
+ * "data": {
99565
+ * "open": [
99566
+ * {
99567
+ * "id": "b1b1b1b1-0000-4000-8000-000000000001",
99568
+ * "cause": "tag_silent",
99569
+ * "label": "Etiqueta del sitio sin señal",
99570
+ * "sentence": "La etiqueta de tu sitio web no envía visitas desde el 20 sep",
99571
+ * "action": {
99572
+ * "label": "Revisar la etiqueta",
99573
+ * "path": "/anuncios/activar?paso=tag"
99574
+ * },
99575
+ * "since": "2026-09-20T14:05:00.000Z",
99576
+ * "opened_at": "2026-09-27T15:00:00.000Z",
99577
+ * "resolved_at": null,
99578
+ * "resolution": null,
99579
+ * "resolved_by_name": null,
99580
+ * "metrics": []
99581
+ * }
99582
+ * ],
99583
+ * "recent": [
99584
+ * {
99585
+ * "id": "b1b1b1b1-0000-4000-8000-000000000002",
99586
+ * "cause": "meta_disconnected",
99587
+ * "label": "Meta Ads desconectado",
99588
+ * "sentence": "Tus anuncios de Meta dejaron de medirse el 12 sep",
99589
+ * "action": {
99590
+ * "label": "Reconectar Meta",
99591
+ * "path": "/anuncios/activar?paso=meta"
99592
+ * },
99593
+ * "since": "2026-09-12T11:20:00.000Z",
99594
+ * "opened_at": "2026-09-12T12:00:00.000Z",
99595
+ * "resolved_at": "2026-09-15T13:42:00.000Z",
99596
+ * "resolution": "reconnected",
99597
+ * "resolved_by_name": "Camila",
99598
+ * "metrics": [
99599
+ * "spend"
99600
+ * ]
99601
+ * }
99602
+ * ]
99603
+ * }
99604
+ * }
99605
+ */
99606
+ "application/json": {
99607
+ data: components["schemas"]["AdsMeasurement"];
99608
+ };
99609
+ };
99610
+ };
99611
+ /** @description Validation error */
99612
+ 400: {
99613
+ headers: {
99614
+ [name: string]: unknown;
99615
+ };
99616
+ content: {
99617
+ "application/json": components["schemas"]["Error"];
99618
+ };
99619
+ };
99620
+ /** @description Unauthorized */
99621
+ 401: {
99622
+ headers: {
99623
+ [name: string]: unknown;
99624
+ };
99625
+ content: {
99626
+ "application/json": components["schemas"]["Error"];
99627
+ };
99628
+ };
99629
+ /** @description Vitrina Ads is not active for this workspace. `error.code` is `ENTITLEMENT_NOT_ACTIVE`, `error.details.feature` is `vitrina_ads`. */
99630
+ 402: {
99631
+ headers: {
99632
+ [name: string]: unknown;
99633
+ };
99634
+ content: {
99635
+ /**
99636
+ * @example {
99637
+ * "error": {
99638
+ * "code": "ENTITLEMENT_NOT_ACTIVE",
99639
+ * "message": "El complemento Vitrina Ads no está activo en este espacio de trabajo.",
99640
+ * "details": {
99641
+ * "required": [
99642
+ * "vitrina_ads"
99643
+ * ],
99644
+ * "active": [],
99645
+ * "feature": "vitrina_ads",
99646
+ * "entitlement_state": "off"
99647
+ * }
99648
+ * }
99649
+ * }
99650
+ */
99651
+ "application/json": components["schemas"]["Error"];
99652
+ };
99653
+ };
99654
+ /** @description Forbidden */
99655
+ 403: {
99656
+ headers: {
99657
+ [name: string]: unknown;
99658
+ };
99659
+ content: {
99660
+ "application/json": components["schemas"]["Error"];
99661
+ };
99662
+ };
99663
+ /** @description Not found */
99664
+ 404: {
99665
+ headers: {
99666
+ [name: string]: unknown;
99667
+ };
99668
+ content: {
99669
+ "application/json": components["schemas"]["Error"];
99670
+ };
99671
+ };
99672
+ /** @description Vitrina Ads is active but the delegated key has not finished rotating (`ADS_KEY_NEEDS_REMINT`) — retry once `GET /ads/state` reports `needs_remint: false`. Also the generic conflict of a write. */
99673
+ 409: {
99674
+ headers: {
99675
+ [name: string]: unknown;
99676
+ };
99677
+ content: {
99678
+ /**
99679
+ * @example {
99680
+ * "error": {
99681
+ * "code": "ADS_KEY_NEEDS_REMINT",
99682
+ * "message": "Vitrina Ads is active but the delegated key has not finished rotating (key_kind: core)",
99683
+ * "details": {
99684
+ * "key_kind": "core"
99685
+ * }
99686
+ * }
99687
+ * }
99688
+ */
99689
+ "application/json": components["schemas"]["Error"];
99690
+ };
99691
+ };
99692
+ /** @description Rate limited */
99693
+ 429: {
99694
+ headers: {
99695
+ [name: string]: unknown;
99696
+ };
99697
+ content: {
99698
+ "application/json": components["schemas"]["Error"];
99699
+ };
99700
+ };
99701
+ };
99702
+ };
99703
+ put?: never;
99704
+ post?: never;
99705
+ delete?: never;
99706
+ options?: never;
99707
+ head?: never;
99708
+ patch?: never;
99709
+ trace?: never;
99710
+ };
98018
99711
  "/ads/campaigns": {
98019
99712
  parameters: {
98020
99713
  query?: never;
@@ -98230,6 +99923,17 @@ interface paths {
98230
99923
  * }
98231
99924
  * ]
98232
99925
  * }
99926
+ * ],
99927
+ * "gaps": [
99928
+ * {
99929
+ * "from": "2026-09-12",
99930
+ * "to": "2026-09-15",
99931
+ * "cause": "meta_disconnected",
99932
+ * "metrics": [
99933
+ * "spend"
99934
+ * ],
99935
+ * "incident_id": "b1b1b1b1-0000-4000-8000-000000000002"
99936
+ * }
98233
99937
  * ]
98234
99938
  * }
98235
99939
  * }
@@ -122361,6 +124065,178 @@ interface components {
122361
124065
  from: string;
122362
124066
  to: string;
122363
124067
  };
124068
+ AgendaResults: {
124069
+ from: string;
124070
+ to: string;
124071
+ timezone: string;
124072
+ /** Format: uuid */
124073
+ location_id: string | null;
124074
+ /**
124075
+ * @description Vocabulary: citas/pacientes, visitas/clientes, citas/clientes.
124076
+ * @enum {string}
124077
+ */
124078
+ family: "clinic" | "dealer" | "generic";
124079
+ previous_period: {
124080
+ from: string;
124081
+ to: string;
124082
+ };
124083
+ bookings: {
124084
+ /** @description Citas of the period booked by Vitrina's agent in a conversation (`source='agent'`, not a public booking page). */
124085
+ ai: number;
124086
+ /** @description Every cita of the period (blocks and holds excluded). */
124087
+ agenda_total: number;
124088
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124089
+ share_pct: number | null;
124090
+ previous: {
124091
+ ai: number;
124092
+ agenda_total: number;
124093
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124094
+ share_pct: number | null;
124095
+ };
124096
+ rule: string;
124097
+ };
124098
+ money: {
124099
+ /** @description False for a vertical with no priced citas. */
124100
+ applies: boolean;
124101
+ withheld: boolean;
124102
+ /** @description Value of the AI-booked citas whose value is known (pipeline, not cash). */
124103
+ booked_clp: number | null;
124104
+ booked_priced: number;
124105
+ /** @description AI-booked citas with no price — «sin dato». */
124106
+ booked_unpriced: number;
124107
+ /** @description CLP. `null` when unknown or when the caller lacks `clinic_money:read` (`money.withheld`). */
124108
+ agenda_clp: number | null;
124109
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124110
+ clp_share_pct: number | null;
124111
+ /** @description Cash received in the period by the patients Vitrina booked, from the day it booked them. */
124112
+ paid_clp: number | null;
124113
+ paid_patients: number | null;
124114
+ /** @description AI-booked citas with no patient to match a payment to. */
124115
+ unlinked: number;
124116
+ /** @enum {string|null} */
124117
+ regime: "mirror" | "native" | null;
124118
+ previous: {
124119
+ /** @description CLP. `null` when unknown or when the caller lacks `clinic_money:read` (`money.withheld`). */
124120
+ booked_clp: number | null;
124121
+ /** @description CLP. `null` when unknown or when the caller lacks `clinic_money:read` (`money.withheld`). */
124122
+ paid_clp: number | null;
124123
+ };
124124
+ rule_booked: string;
124125
+ rule_paid: string;
124126
+ };
124127
+ out_of_hours: {
124128
+ /** @description False when the workspace has no business hours; count/pct are then null. */
124129
+ configured: boolean;
124130
+ count: number | null;
124131
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124132
+ pct: number | null;
124133
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124134
+ previous_pct: number | null;
124135
+ /** @description AI bookings by weekday × hour of the booking, in `timezone`. Empty cells omitted. */
124136
+ heatmap: {
124137
+ /** @description 1 = Monday … 7 = Sunday. */
124138
+ weekday: number;
124139
+ hour: number;
124140
+ count: number;
124141
+ }[];
124142
+ rule: string;
124143
+ };
124144
+ autonomy: {
124145
+ no_human: number;
124146
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124147
+ pct: number | null;
124148
+ measured: number;
124149
+ unknown: number;
124150
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124151
+ previous_pct: number | null;
124152
+ rule: string;
124153
+ };
124154
+ time_to_book: {
124155
+ median_seconds: number | null;
124156
+ p95_seconds: number | null;
124157
+ p95_phrase: string | null;
124158
+ measured: number;
124159
+ unknown: number;
124160
+ previous_median_seconds: number | null;
124161
+ rule: string;
124162
+ };
124163
+ hours_returned: {
124164
+ minutes_per_booking: number;
124165
+ hours: number;
124166
+ rule: string;
124167
+ };
124168
+ recovery: {
124169
+ window_days: number;
124170
+ known_attendance: number;
124171
+ unknown_attendance: number;
124172
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124173
+ no_show_pct: number | null;
124174
+ no_show: {
124175
+ count: number;
124176
+ recovered: number;
124177
+ recovered_via_vitrina: number;
124178
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124179
+ recovered_pct: number | null;
124180
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124181
+ via_vitrina_pct: number | null;
124182
+ /** @description Not recovered yet, still inside the 30 days. */
124183
+ pending: number;
124184
+ /** @description Missed with no identifiable patient. */
124185
+ unlinked: number;
124186
+ };
124187
+ cancelled: {
124188
+ count: number;
124189
+ recovered: number;
124190
+ recovered_via_vitrina: number;
124191
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124192
+ recovered_pct: number | null;
124193
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124194
+ via_vitrina_pct: number | null;
124195
+ /** @description Not recovered yet, still inside the 30 days. */
124196
+ pending: number;
124197
+ /** @description Missed with no identifiable patient. */
124198
+ unlinked: number;
124199
+ };
124200
+ rule_no_show: string;
124201
+ rule_recovered: string;
124202
+ };
124203
+ confirmation: {
124204
+ applies: boolean;
124205
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124206
+ confirmed_attendance_pct: number | null;
124207
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124208
+ unconfirmed_attendance_pct: number | null;
124209
+ confirmed_closed: number | null;
124210
+ unconfirmed_closed: number | null;
124211
+ rule: string;
124212
+ };
124213
+ ads: {
124214
+ /** @enum {string} */
124215
+ state: "active" | "not_active" | "unavailable";
124216
+ spend_clp: number | null;
124217
+ booked: number | null;
124218
+ attended: number | null;
124219
+ paid: number | null;
124220
+ cost_per_booked: number | null;
124221
+ cost_per_attended: number | null;
124222
+ cost_per_paid: number | null;
124223
+ rule: string;
124224
+ };
124225
+ reminders: {
124226
+ applies: boolean;
124227
+ sent: number;
124228
+ failed: number;
124229
+ /** @description Percent, one decimal. `null` — never 0 — with no denominator. */
124230
+ failed_pct: number | null;
124231
+ by_cause: {
124232
+ /** @enum {string} */
124233
+ cause: "no_patient_link" | "no_phone" | "no_channel" | "opted_out" | "template_not_approved" | "meta_payment_block" | "no_whatsapp" | "window_closed" | "template_rejected" | "send_error";
124234
+ count: number;
124235
+ }[];
124236
+ rule: string;
124237
+ };
124238
+ truncated: boolean;
124239
+ };
122364
124240
  ClinicComercialReport: {
122365
124241
  from: string;
122366
124242
  to: string;
@@ -123178,6 +125054,180 @@ interface components {
123178
125054
  */
123179
125055
  handoff_id?: string;
123180
125056
  };
125057
+ AdsReportRow: {
125058
+ spend: number | null;
125059
+ /** @description Vitrina’s own funnel: conversations each ad OPENED in the period and the stages recorded against them (a campaign / ad set sums its ads). `null` = unknown (the read failed), never 0. */
125060
+ funnel: {
125061
+ conversations: number | null;
125062
+ replied: number | null;
125063
+ appointments: number | null;
125064
+ attended: number | null;
125065
+ closes: number | null;
125066
+ };
125067
+ cost_per: {
125068
+ conversation: number | null;
125069
+ appointment: number | null;
125070
+ attended: number | null;
125071
+ close: number | null;
125072
+ };
125073
+ /** @description Payments credited to the entity (CLP). Cash only. */
125074
+ cash: number | null;
125075
+ /** @description cash ÷ spend. `null` when no payment was recorded in the period (see `cash_recorded`) — the return is unknown then, never 0×. */
125076
+ return: number | null;
125077
+ /** @description Meta’s OWN figures (its 7-day window, every sender) — never added to Vitrina’s. */
125078
+ meta: {
125079
+ conversations_started: number | null;
125080
+ cost_per_conversation: number | null;
125081
+ };
125082
+ /** @description Platform id; `null` for the unmapped bucket. */
125083
+ external_id: string | null;
125084
+ /** @enum {string} */
125085
+ level: "campaign" | "ad_set" | "ad";
125086
+ name: string;
125087
+ /** @description An ad’s ad set / an ad set’s campaign; `null` for a campaign. */
125088
+ parent: {
125089
+ external_id: string | null;
125090
+ name: string | null;
125091
+ } | null;
125092
+ thumbnail_url: string | null;
125093
+ /** @description Daily spend, oldest first; `null` unread. */
125094
+ spark: number[] | null;
125095
+ /**
125096
+ * @description Ads that opened conversations but have no row at this level yet.
125097
+ * @enum {boolean}
125098
+ */
125099
+ unmapped?: true;
125100
+ };
125101
+ AdsReport: {
125102
+ /** @enum {string} */
125103
+ level: "campaign" | "ad_set" | "ad";
125104
+ window: {
125105
+ from: string;
125106
+ to: string;
125107
+ };
125108
+ rows: components["schemas"]["AdsReportRow"][];
125109
+ /** @description «Sin anuncio»: the period’s conversations with no ad behind them. `null` = unknown. */
125110
+ tail: {
125111
+ /** @enum {string} */
125112
+ key: "website" | "portals" | "direct";
125113
+ conversations: number;
125114
+ }[] | null;
125115
+ totals: {
125116
+ spend: number | null;
125117
+ /** @description Vitrina’s own funnel: conversations each ad OPENED in the period and the stages recorded against them (a campaign / ad set sums its ads). `null` = unknown (the read failed), never 0. */
125118
+ funnel: {
125119
+ conversations: number | null;
125120
+ replied: number | null;
125121
+ appointments: number | null;
125122
+ attended: number | null;
125123
+ closes: number | null;
125124
+ };
125125
+ cost_per: {
125126
+ conversation: number | null;
125127
+ appointment: number | null;
125128
+ attended: number | null;
125129
+ close: number | null;
125130
+ };
125131
+ /** @description Payments credited to the entity (CLP). Cash only. */
125132
+ cash: number | null;
125133
+ /** @description cash ÷ spend. `null` when no payment was recorded in the period (see `cash_recorded`) — the return is unknown then, never 0×. */
125134
+ return: number | null;
125135
+ /** @description Meta’s OWN figures (its 7-day window, every sender) — never added to Vitrina’s. */
125136
+ meta: {
125137
+ conversations_started: number | null;
125138
+ cost_per_conversation: number | null;
125139
+ };
125140
+ };
125141
+ /** @description Closes credited to an ad and their recorded value — PIPELINE, never in `return`. */
125142
+ pipeline: {
125143
+ closed_count: number;
125144
+ closed_value: number;
125145
+ } | null;
125146
+ cash_recorded: boolean;
125147
+ reconciliation: {
125148
+ overview_spend: number | null;
125149
+ spend_matches: boolean | null;
125150
+ conversations_total: number | null;
125151
+ conversations_from_ads: number | null;
125152
+ conversations_without_ad: number | null;
125153
+ };
125154
+ };
125155
+ AdsAdSheet: {
125156
+ /** @description The creative and the delivery metrics; `null` when the engine read failed. */
125157
+ ad: {
125158
+ external_id: string;
125159
+ name: string;
125160
+ ad_set: {
125161
+ external_id: string | null;
125162
+ name: string | null;
125163
+ } | null;
125164
+ campaign: {
125165
+ external_id: string;
125166
+ } | null;
125167
+ thumbnail_url: string | null;
125168
+ title: string | null;
125169
+ body: string | null;
125170
+ has_video: boolean;
125171
+ spend: number | null;
125172
+ impressions: number;
125173
+ clicks: number;
125174
+ ctr: number;
125175
+ cpm: number;
125176
+ cpc: number;
125177
+ cash_count: number;
125178
+ cash_value: number;
125179
+ meta_conversations_started: number | null;
125180
+ } | null;
125181
+ window: {
125182
+ from: string;
125183
+ to: string;
125184
+ };
125185
+ /** @description The same figures as the Reporte row for this ad. */
125186
+ row: {
125187
+ spend: number | null;
125188
+ /** @description Vitrina’s own funnel: conversations each ad OPENED in the period and the stages recorded against them (a campaign / ad set sums its ads). `null` = unknown (the read failed), never 0. */
125189
+ funnel: {
125190
+ conversations: number | null;
125191
+ replied: number | null;
125192
+ appointments: number | null;
125193
+ attended: number | null;
125194
+ closes: number | null;
125195
+ };
125196
+ cost_per: {
125197
+ conversation: number | null;
125198
+ appointment: number | null;
125199
+ attended: number | null;
125200
+ close: number | null;
125201
+ };
125202
+ /** @description Payments credited to the entity (CLP). Cash only. */
125203
+ cash: number | null;
125204
+ /** @description cash ÷ spend. `null` when no payment was recorded in the period (see `cash_recorded`) — the return is unknown then, never 0×. */
125205
+ return: number | null;
125206
+ /** @description Meta’s OWN figures (its 7-day window, every sender) — never added to Vitrina’s. */
125207
+ meta: {
125208
+ conversations_started: number | null;
125209
+ cost_per_conversation: number | null;
125210
+ };
125211
+ };
125212
+ cash_recorded: boolean;
125213
+ /** @description The conversations this ad opened, newest first. Healthcare: always initials. Elsewhere a name only with `contacts:read`. No export. */
125214
+ people: {
125215
+ /** Format: uuid */
125216
+ conversation_id: string;
125217
+ /** Format: uuid */
125218
+ contact_id: string | null;
125219
+ /** @description Initials, or the name where allowed. Never a phone or an e-mail. */
125220
+ label: string;
125221
+ masked: boolean;
125222
+ stage: string | null;
125223
+ stage_at: string | null;
125224
+ opened_at: string;
125225
+ value: number | null;
125226
+ }[];
125227
+ people_more: boolean;
125228
+ /** @description The caller lacks `contacts:read`: `people` is empty on purpose. */
125229
+ people_hidden: boolean;
125230
+ };
123181
125231
  AdsOverviewDay: {
123182
125232
  date: string;
123183
125233
  /** @description `null` exactly when the engine could not scope spend. */
@@ -123189,6 +125239,21 @@ interface components {
123189
125239
  /** @description `true` on the day still running (today, America/Santiago): end the solid line before it. */
123190
125240
  partial: boolean;
123191
125241
  };
125242
+ AdsGap: {
125243
+ /** @description First day with missing data, YYYY-MM-DD. */
125244
+ from: string;
125245
+ /** @description Last day with missing data, YYYY-MM-DD; `null` = still ongoing. */
125246
+ to: string | null;
125247
+ /**
125248
+ * @description What broke: `meta_disconnected` / `meta_stale` (the ad account read), `tag_silent` (the site tag stopped reporting), `capi_failing` (the Conversions API sends), `whatsapp_disconnected`, `engine_facts_missing` (clinic payments/plans not reaching the attribution).
125249
+ * @enum {string}
125250
+ */
125251
+ cause: "meta_disconnected" | "meta_stale" | "tag_silent" | "capi_failing" | "whatsapp_disconnected" | "engine_facts_missing";
125252
+ /** @description The figures UNKNOWN inside the gap: draw them as missing (a break in the line, «sin datos»), never as 0. Empty = nothing Vitrina shows is blanked; the window is annotated only. */
125253
+ metrics: ("spend" | "conversations" | "outcomes")[];
125254
+ /** Format: uuid */
125255
+ incident_id: string;
125256
+ };
123192
125257
  AdsOverview: {
123193
125258
  current: {
123194
125259
  spend: number | null;
@@ -123256,6 +125321,44 @@ interface components {
123256
125321
  days?: components["schemas"]["AdsOverviewDay"][];
123257
125322
  /** @description `grain=day` only: every day of the previous window of equal length. */
123258
125323
  previous_days?: components["schemas"]["AdsOverviewDay"][];
125324
+ /** @description Measurement gaps overlapping the window (W1.1). Days inside a gap whose `metrics` list a figure carry NO measured value for it — the engine may report 0 there; render «sin datos», never the 0. */
125325
+ gaps: components["schemas"]["AdsGap"][];
125326
+ };
125327
+ AdsMeasurementIncident: {
125328
+ /** Format: uuid */
125329
+ id: string;
125330
+ /** @enum {string} */
125331
+ cause: "meta_disconnected" | "meta_stale" | "tag_silent" | "capi_failing" | "whatsapp_disconnected" | "engine_facts_missing";
125332
+ /** @description «Meta Ads desconectado». */
125333
+ label: string;
125334
+ /** @description «Tus anuncios de Meta dejaron de medirse el 12 sep». */
125335
+ sentence: string;
125336
+ /** @description The one primary action. */
125337
+ action: {
125338
+ /** @description «Reconectar Meta». */
125339
+ label: string;
125340
+ /** @description Workspace-relative path of the ONE fix, e.g. `/anuncios/activar?paso=meta`. */
125341
+ path: string;
125342
+ };
125343
+ /** @description When the data stopped (ISO instant). */
125344
+ since: string;
125345
+ /** @description When the watchdog opened it (ISO). */
125346
+ opened_at: string;
125347
+ resolved_at: string | null;
125348
+ /**
125349
+ * @description `reconnected` — a member fixed it; `recovered` — the leg came back on its own; `withdrawn` — it was switched off on purpose.
125350
+ * @enum {string|null}
125351
+ */
125352
+ resolution: "reconnected" | "recovered" | "withdrawn" | null;
125353
+ /** @description The member who fixed it. `null` when it recovered on its own, or when the caller lacks `memberships:read`. */
125354
+ resolved_by_name: string | null;
125355
+ metrics: ("spend" | "conversations" | "outcomes")[];
125356
+ };
125357
+ AdsMeasurement: {
125358
+ /** @description Open incidents, oldest first — the banner. */
125359
+ open: components["schemas"]["AdsMeasurementIncident"][];
125360
+ /** @description Incidents resolved in the last 14 days, newest first. */
125361
+ recent: components["schemas"]["AdsMeasurementIncident"][];
123259
125362
  };
123260
125363
  /** @description Present on a conversational row: a message-only objective (`MESSAGES`), or conversations the platform reports, or conversations Vitrina counts. Also present with `data_complete: false` (figures `null`) when a read failed on a row that may be conversational (its objective unknown or in the messaging family) in a workspace with ad-opened conversations. ABSENT otherwise — never a row of zeros, never partial counts. */
123261
125364
  AdsConversational: {
@@ -123314,6 +125417,8 @@ interface components {
123314
125417
  }[] | null;
123315
125418
  conversational?: components["schemas"]["AdsConversational"];
123316
125419
  }[];
125420
+ /** @description Measurement gaps overlapping the window (W1.1). Days inside a gap whose `metrics` list a figure carry NO measured value for it — the engine may report 0 there; render «sin datos», never the 0. */
125421
+ gaps: components["schemas"]["AdsGap"][];
123317
125422
  };
123318
125423
  AdsAttributedSales: {
123319
125424
  data: {