@snokam/mcp-api 2.15.1 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snokam/mcp-api",
3
- "version": "2.15.1",
3
+ "version": "2.17.0",
4
4
  "description": "MCP server exposing Snokam backend APIs as tools for Claude Code and other MCP clients",
5
5
  "type": "module",
6
6
  "bin": {
@@ -447,6 +447,112 @@
447
447
  ]
448
448
  }
449
449
  },
450
+ "/v1.0/tenders/funnel": {
451
+ "get": {
452
+ "tags": [
453
+ "Tenders"
454
+ ],
455
+ "summary": "Pipeline funnel analytics: stage counts, conversion rates, cycle times",
456
+ "operationId": "GetTenderFunnel",
457
+ "parameters": [
458
+ {
459
+ "name": "windowDays",
460
+ "in": "query",
461
+ "description": "Rolling window in days (default 30, max 365)",
462
+ "schema": {
463
+ "type": "integer",
464
+ "format": "int32"
465
+ }
466
+ }
467
+ ],
468
+ "responses": {
469
+ "200": {
470
+ "description": "Payload of FunnelResponse",
471
+ "content": {
472
+ "application/json": {
473
+ "schema": {
474
+ "$ref": "#/components/schemas/funnelResponse"
475
+ }
476
+ }
477
+ }
478
+ }
479
+ },
480
+ "security": [
481
+ {
482
+ "Implicit": [
483
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
484
+ ]
485
+ }
486
+ ]
487
+ }
488
+ },
489
+ "/v1.0/tenders/stats": {
490
+ "get": {
491
+ "tags": [
492
+ "Tenders"
493
+ ],
494
+ "summary": "Aggregated tender KPIs for the admin dashboard (by status/stage/health + activity window)",
495
+ "operationId": "GetTenderStats",
496
+ "parameters": [
497
+ {
498
+ "name": "windowDays",
499
+ "in": "query",
500
+ "description": "Rolling window for activity-based metrics (defaults to 30, max 365)",
501
+ "schema": {
502
+ "type": "integer",
503
+ "format": "int32"
504
+ }
505
+ }
506
+ ],
507
+ "responses": {
508
+ "200": {
509
+ "description": "Payload of TenderStatsResponse",
510
+ "content": {
511
+ "application/json": {
512
+ "schema": {
513
+ "$ref": "#/components/schemas/tenderStatsResponse"
514
+ }
515
+ }
516
+ }
517
+ }
518
+ },
519
+ "security": [
520
+ {
521
+ "Implicit": [
522
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
523
+ ]
524
+ }
525
+ ]
526
+ }
527
+ },
528
+ "/v1.0/consultants/stats": {
529
+ "get": {
530
+ "tags": [
531
+ "Consultants"
532
+ ],
533
+ "summary": "Aggregated consultant KPIs (total, availability split, avg fit score from latest matches)",
534
+ "operationId": "GetConsultantStats",
535
+ "responses": {
536
+ "200": {
537
+ "description": "Payload of ConsultantStatsResponse",
538
+ "content": {
539
+ "application/json": {
540
+ "schema": {
541
+ "$ref": "#/components/schemas/consultantStatsResponse"
542
+ }
543
+ }
544
+ }
545
+ }
546
+ },
547
+ "security": [
548
+ {
549
+ "Implicit": [
550
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
551
+ ]
552
+ }
553
+ ]
554
+ }
555
+ },
450
556
  "/v1.0/crawl/sources": {
451
557
  "get": {
452
558
  "tags": [
@@ -1436,45 +1542,6 @@
1436
1542
  ]
1437
1543
  }
1438
1544
  },
1439
- "/v1.0/tenders/funnel": {
1440
- "get": {
1441
- "tags": [
1442
- "Tenders"
1443
- ],
1444
- "summary": "Pipeline funnel analytics: stage counts, conversion rates, cycle times",
1445
- "operationId": "GetTenderFunnel",
1446
- "parameters": [
1447
- {
1448
- "name": "windowDays",
1449
- "in": "query",
1450
- "description": "Rolling window in days (default 30, max 365)",
1451
- "schema": {
1452
- "type": "integer",
1453
- "format": "int32"
1454
- }
1455
- }
1456
- ],
1457
- "responses": {
1458
- "200": {
1459
- "description": "Payload of FunnelResponse",
1460
- "content": {
1461
- "application/json": {
1462
- "schema": {
1463
- "$ref": "#/components/schemas/funnelResponse"
1464
- }
1465
- }
1466
- }
1467
- }
1468
- },
1469
- "security": [
1470
- {
1471
- "Implicit": [
1472
- "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1473
- ]
1474
- }
1475
- ]
1476
- }
1477
- },
1478
1545
  "/v1.0/realtime/negotiate": {
1479
1546
  "post": {
1480
1547
  "tags": [
@@ -1515,6 +1582,69 @@
1515
1582
  ]
1516
1583
  }
1517
1584
  },
1585
+ "/v1.0/stream": {
1586
+ "get": {
1587
+ "tags": [
1588
+ "Realtime"
1589
+ ],
1590
+ "summary": "Unified SSE stream: tender/job/crawl/consultant/audit events on one connection",
1591
+ "operationId": "StreamAll",
1592
+ "parameters": [
1593
+ {
1594
+ "name": "channels",
1595
+ "in": "query",
1596
+ "description": "Comma-separated namespaces to include (tender,job,crawl,consultant,audit). Default: all.",
1597
+ "schema": {
1598
+ "type": "string"
1599
+ }
1600
+ }
1601
+ ],
1602
+ "responses": {},
1603
+ "security": [
1604
+ {
1605
+ "Implicit": [
1606
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1607
+ ]
1608
+ }
1609
+ ]
1610
+ }
1611
+ },
1612
+ "/v1.0/tenders/stream-redirect": {
1613
+ "get": {
1614
+ "tags": [
1615
+ "Realtime"
1616
+ ],
1617
+ "summary": "Deprecated: redirects to /v1.0/stream?channels=tender,job",
1618
+ "operationId": "DeprecatedTenderStream",
1619
+ "responses": {},
1620
+ "deprecated": true,
1621
+ "security": [
1622
+ {
1623
+ "Implicit": [
1624
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1625
+ ]
1626
+ }
1627
+ ]
1628
+ }
1629
+ },
1630
+ "/v1.0/crawl/stream-redirect": {
1631
+ "get": {
1632
+ "tags": [
1633
+ "Realtime"
1634
+ ],
1635
+ "summary": "Deprecated: redirects to /v1.0/stream?channels=crawl,job",
1636
+ "operationId": "DeprecatedCrawlStream",
1637
+ "responses": {},
1638
+ "deprecated": true,
1639
+ "security": [
1640
+ {
1641
+ "Implicit": [
1642
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1643
+ ]
1644
+ }
1645
+ ]
1646
+ }
1647
+ },
1518
1648
  "/v1.0/salesforce/opportunities": {
1519
1649
  "get": {
1520
1650
  "tags": [
@@ -1565,39 +1695,23 @@
1565
1695
  ]
1566
1696
  }
1567
1697
  },
1568
- "/v1.0/tenders/{id}/salesforce": {
1698
+ "/v1.0/salesforce/refresh": {
1569
1699
  "post": {
1570
1700
  "tags": [
1571
1701
  "Salesforce"
1572
1702
  ],
1573
- "summary": "Create a Salesforce Opportunity from a Snøkam tender and cache the link.",
1574
- "operationId": "PromoteTenderToSalesforce",
1575
- "parameters": [
1576
- {
1577
- "name": "id",
1578
- "in": "path",
1579
- "required": true,
1580
- "schema": {
1581
- "type": "string"
1582
- }
1583
- }
1584
- ],
1703
+ "summary": "Batch-refresh the cached Salesforce state on every linked Snøkam tender.",
1704
+ "operationId": "RefreshAllSalesforceLinks",
1585
1705
  "responses": {
1586
1706
  "200": {
1587
- "description": "Payload of Tender",
1707
+ "description": "Payload of SalesforceRefreshResult",
1588
1708
  "content": {
1589
1709
  "application/json": {
1590
1710
  "schema": {
1591
- "$ref": "#/components/schemas/tender"
1711
+ "$ref": "#/components/schemas/salesforceRefreshResult"
1592
1712
  }
1593
1713
  }
1594
1714
  }
1595
- },
1596
- "404": {
1597
- "description": "No description"
1598
- },
1599
- "409": {
1600
- "description": "Tender is already linked to a Salesforce Opportunity."
1601
1715
  }
1602
1716
  },
1603
1717
  "security": [
@@ -1609,21 +1723,22 @@
1609
1723
  ]
1610
1724
  }
1611
1725
  },
1612
- "/v1.0/tenders/{id}/salesforce/refresh": {
1726
+ "/v1.0/salesforce/opportunities/{sfId}/import": {
1613
1727
  "post": {
1614
1728
  "tags": [
1615
1729
  "Salesforce"
1616
1730
  ],
1617
- "summary": "Re-sync cached Salesforce Opportunity state (stage / closed / won) onto the tender.",
1618
- "operationId": "RefreshTenderSalesforceLink",
1731
+ "summary": "Create a Snøkam tender stub from an existing Salesforce Opportunity.",
1732
+ "operationId": "ImportSalesforceOpportunity",
1619
1733
  "parameters": [
1620
1734
  {
1621
- "name": "id",
1735
+ "name": "sfId",
1622
1736
  "in": "path",
1623
1737
  "required": true,
1624
1738
  "schema": {
1625
1739
  "type": "string"
1626
- }
1740
+ },
1741
+ "x-ms-summary": "Salesforce Opportunity Id."
1627
1742
  }
1628
1743
  ],
1629
1744
  "responses": {
@@ -1639,6 +1754,9 @@
1639
1754
  },
1640
1755
  "404": {
1641
1756
  "description": "No description"
1757
+ },
1758
+ "409": {
1759
+ "description": "A tender is already linked to this Opportunity."
1642
1760
  }
1643
1761
  },
1644
1762
  "security": [
@@ -1650,34 +1768,39 @@
1650
1768
  ]
1651
1769
  }
1652
1770
  },
1653
- "/v1.0/tenders/stats": {
1654
- "get": {
1771
+ "/v1.0/tenders/{id}/salesforce": {
1772
+ "post": {
1655
1773
  "tags": [
1656
- "Tenders"
1774
+ "Salesforce"
1657
1775
  ],
1658
- "summary": "Aggregated tender KPIs for the admin dashboard (by status/stage/health + activity window)",
1659
- "operationId": "GetTenderStats",
1776
+ "summary": "Create a Salesforce Opportunity from a Snøkam tender and cache the link.",
1777
+ "operationId": "PromoteTenderToSalesforce",
1660
1778
  "parameters": [
1661
1779
  {
1662
- "name": "windowDays",
1663
- "in": "query",
1664
- "description": "Rolling window for activity-based metrics (defaults to 30, max 365)",
1780
+ "name": "id",
1781
+ "in": "path",
1782
+ "required": true,
1665
1783
  "schema": {
1666
- "type": "integer",
1667
- "format": "int32"
1784
+ "type": "string"
1668
1785
  }
1669
1786
  }
1670
1787
  ],
1671
1788
  "responses": {
1672
1789
  "200": {
1673
- "description": "Payload of TenderStatsResponse",
1790
+ "description": "Payload of Tender",
1674
1791
  "content": {
1675
1792
  "application/json": {
1676
1793
  "schema": {
1677
- "$ref": "#/components/schemas/tenderStatsResponse"
1794
+ "$ref": "#/components/schemas/tender"
1678
1795
  }
1679
1796
  }
1680
1797
  }
1798
+ },
1799
+ "404": {
1800
+ "description": "No description"
1801
+ },
1802
+ "409": {
1803
+ "description": "Tender is already linked to a Salesforce Opportunity."
1681
1804
  }
1682
1805
  },
1683
1806
  "security": [
@@ -1689,23 +1812,36 @@
1689
1812
  ]
1690
1813
  }
1691
1814
  },
1692
- "/v1.0/consultants/stats": {
1693
- "get": {
1815
+ "/v1.0/tenders/{id}/salesforce/refresh": {
1816
+ "post": {
1694
1817
  "tags": [
1695
- "Consultants"
1818
+ "Salesforce"
1819
+ ],
1820
+ "summary": "Re-sync cached Salesforce Opportunity state (stage / closed / won) onto the tender.",
1821
+ "operationId": "RefreshTenderSalesforceLink",
1822
+ "parameters": [
1823
+ {
1824
+ "name": "id",
1825
+ "in": "path",
1826
+ "required": true,
1827
+ "schema": {
1828
+ "type": "string"
1829
+ }
1830
+ }
1696
1831
  ],
1697
- "summary": "Aggregated consultant KPIs (total, availability split, avg fit score from latest matches)",
1698
- "operationId": "GetConsultantStats",
1699
1832
  "responses": {
1700
1833
  "200": {
1701
- "description": "Payload of ConsultantStatsResponse",
1834
+ "description": "Payload of Tender",
1702
1835
  "content": {
1703
1836
  "application/json": {
1704
1837
  "schema": {
1705
- "$ref": "#/components/schemas/consultantStatsResponse"
1838
+ "$ref": "#/components/schemas/tender"
1706
1839
  }
1707
1840
  }
1708
1841
  }
1842
+ },
1843
+ "404": {
1844
+ "description": "No description"
1709
1845
  }
1710
1846
  },
1711
1847
  "security": [
@@ -1717,69 +1853,6 @@
1717
1853
  ]
1718
1854
  }
1719
1855
  },
1720
- "/v1.0/stream": {
1721
- "get": {
1722
- "tags": [
1723
- "Realtime"
1724
- ],
1725
- "summary": "Unified SSE stream: tender/job/crawl/consultant/audit events on one connection",
1726
- "operationId": "StreamAll",
1727
- "parameters": [
1728
- {
1729
- "name": "channels",
1730
- "in": "query",
1731
- "description": "Comma-separated namespaces to include (tender,job,crawl,consultant,audit). Default: all.",
1732
- "schema": {
1733
- "type": "string"
1734
- }
1735
- }
1736
- ],
1737
- "responses": {},
1738
- "security": [
1739
- {
1740
- "Implicit": [
1741
- "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1742
- ]
1743
- }
1744
- ]
1745
- }
1746
- },
1747
- "/v1.0/tenders/stream-redirect": {
1748
- "get": {
1749
- "tags": [
1750
- "Realtime"
1751
- ],
1752
- "summary": "Deprecated: redirects to /v1.0/stream?channels=tender,job",
1753
- "operationId": "DeprecatedTenderStream",
1754
- "responses": {},
1755
- "deprecated": true,
1756
- "security": [
1757
- {
1758
- "Implicit": [
1759
- "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1760
- ]
1761
- }
1762
- ]
1763
- }
1764
- },
1765
- "/v1.0/crawl/stream-redirect": {
1766
- "get": {
1767
- "tags": [
1768
- "Realtime"
1769
- ],
1770
- "summary": "Deprecated: redirects to /v1.0/stream?channels=crawl,job",
1771
- "operationId": "DeprecatedCrawlStream",
1772
- "responses": {},
1773
- "deprecated": true,
1774
- "security": [
1775
- {
1776
- "Implicit": [
1777
- "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
1778
- ]
1779
- }
1780
- ]
1781
- }
1782
- },
1783
1856
  "/v1.0/tenders": {
1784
1857
  "get": {
1785
1858
  "tags": [
@@ -1969,6 +2042,146 @@
1969
2042
  ]
1970
2043
  }
1971
2044
  },
2045
+ "/v1.0/tenders/{id}/reingest": {
2046
+ "post": {
2047
+ "tags": [
2048
+ "Tenders"
2049
+ ],
2050
+ "summary": "Re-run the ingestion pipeline on an existing tender, re-parsing documents and refreshing AI match / summary / classification.",
2051
+ "operationId": "ReingestTender",
2052
+ "parameters": [
2053
+ {
2054
+ "name": "id",
2055
+ "in": "path",
2056
+ "required": true,
2057
+ "schema": {
2058
+ "type": "string"
2059
+ }
2060
+ }
2061
+ ],
2062
+ "responses": {
2063
+ "200": {
2064
+ "description": "Payload of AgentJob",
2065
+ "content": {
2066
+ "application/json": {
2067
+ "schema": {
2068
+ "$ref": "#/components/schemas/agentJob"
2069
+ }
2070
+ }
2071
+ }
2072
+ },
2073
+ "404": {
2074
+ "description": "No description"
2075
+ }
2076
+ },
2077
+ "security": [
2078
+ {
2079
+ "Implicit": [
2080
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
2081
+ ]
2082
+ }
2083
+ ]
2084
+ }
2085
+ },
2086
+ "/v1.0/tenders/{id}/jobs/{jobId}/snapshot": {
2087
+ "get": {
2088
+ "tags": [
2089
+ "Tenders"
2090
+ ],
2091
+ "summary": "Return the tender as it looked right after a given agent job ran (time-travel view).",
2092
+ "operationId": "GetTenderJobSnapshot",
2093
+ "parameters": [
2094
+ {
2095
+ "name": "id",
2096
+ "in": "path",
2097
+ "required": true,
2098
+ "schema": {
2099
+ "type": "string"
2100
+ }
2101
+ },
2102
+ {
2103
+ "name": "jobId",
2104
+ "in": "path",
2105
+ "required": true,
2106
+ "schema": {
2107
+ "type": "string"
2108
+ }
2109
+ }
2110
+ ],
2111
+ "responses": {
2112
+ "200": {
2113
+ "description": "Payload of Tender",
2114
+ "content": {
2115
+ "application/json": {
2116
+ "schema": {
2117
+ "$ref": "#/components/schemas/tender"
2118
+ }
2119
+ }
2120
+ }
2121
+ },
2122
+ "404": {
2123
+ "description": "No description"
2124
+ }
2125
+ },
2126
+ "security": [
2127
+ {
2128
+ "Implicit": [
2129
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
2130
+ ]
2131
+ }
2132
+ ]
2133
+ }
2134
+ },
2135
+ "/v1.0/tenders/{id}/jobs": {
2136
+ "get": {
2137
+ "tags": [
2138
+ "Tenders"
2139
+ ],
2140
+ "summary": "Recent agent jobs (ingestion, CV matching, …) for a tender — newest first.",
2141
+ "operationId": "ListTenderJobs",
2142
+ "parameters": [
2143
+ {
2144
+ "name": "id",
2145
+ "in": "path",
2146
+ "required": true,
2147
+ "schema": {
2148
+ "type": "string"
2149
+ }
2150
+ },
2151
+ {
2152
+ "name": "limit",
2153
+ "in": "query",
2154
+ "schema": {
2155
+ "type": "integer",
2156
+ "format": "int32"
2157
+ },
2158
+ "x-ms-summary": "Max rows (default 10, capped at 100)."
2159
+ }
2160
+ ],
2161
+ "responses": {
2162
+ "200": {
2163
+ "description": "Payload of Array of AgentJob",
2164
+ "content": {
2165
+ "application/json": {
2166
+ "schema": {
2167
+ "type": "array",
2168
+ "items": {
2169
+ "$ref": "#/components/schemas/agentJob"
2170
+ }
2171
+ }
2172
+ }
2173
+ }
2174
+ }
2175
+ },
2176
+ "security": [
2177
+ {
2178
+ "Implicit": [
2179
+ "api://7e877854-e62d-4637-a655-1da7141f7ac9/.default"
2180
+ ]
2181
+ }
2182
+ ]
2183
+ }
2184
+ },
1972
2185
  "/v1.0/admin/tenders": {
1973
2186
  "delete": {
1974
2187
  "tags": [
@@ -2184,6 +2397,10 @@
2184
2397
  "$ref": "#/components/schemas/agentJobLogEntry"
2185
2398
  },
2186
2399
  "nullable": true
2400
+ },
2401
+ "afterSnapshot": {
2402
+ "type": "string",
2403
+ "nullable": true
2187
2404
  }
2188
2405
  }
2189
2406
  },
@@ -3106,6 +3323,19 @@
3106
3323
  },
3107
3324
  "nullable": true
3108
3325
  },
3326
+ "salesforceRefreshResult": {
3327
+ "type": "object",
3328
+ "properties": {
3329
+ "checked": {
3330
+ "type": "integer",
3331
+ "format": "int32"
3332
+ },
3333
+ "updated": {
3334
+ "type": "integer",
3335
+ "format": "int32"
3336
+ }
3337
+ }
3338
+ },
3109
3339
  "sourceFile": {
3110
3340
  "type": "object",
3111
3341
  "properties": {
@@ -447,6 +447,112 @@
447
447
  ]
448
448
  }
449
449
  },
450
+ "/v1.0/tenders/funnel": {
451
+ "get": {
452
+ "tags": [
453
+ "Tenders"
454
+ ],
455
+ "summary": "Pipeline funnel analytics: stage counts, conversion rates, cycle times",
456
+ "operationId": "GetTenderFunnel",
457
+ "parameters": [
458
+ {
459
+ "name": "windowDays",
460
+ "in": "query",
461
+ "description": "Rolling window in days (default 30, max 365)",
462
+ "schema": {
463
+ "type": "integer",
464
+ "format": "int32"
465
+ }
466
+ }
467
+ ],
468
+ "responses": {
469
+ "200": {
470
+ "description": "Payload of FunnelResponse",
471
+ "content": {
472
+ "application/json": {
473
+ "schema": {
474
+ "$ref": "#/components/schemas/funnelResponse"
475
+ }
476
+ }
477
+ }
478
+ }
479
+ },
480
+ "security": [
481
+ {
482
+ "Implicit": [
483
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
484
+ ]
485
+ }
486
+ ]
487
+ }
488
+ },
489
+ "/v1.0/tenders/stats": {
490
+ "get": {
491
+ "tags": [
492
+ "Tenders"
493
+ ],
494
+ "summary": "Aggregated tender KPIs for the admin dashboard (by status/stage/health + activity window)",
495
+ "operationId": "GetTenderStats",
496
+ "parameters": [
497
+ {
498
+ "name": "windowDays",
499
+ "in": "query",
500
+ "description": "Rolling window for activity-based metrics (defaults to 30, max 365)",
501
+ "schema": {
502
+ "type": "integer",
503
+ "format": "int32"
504
+ }
505
+ }
506
+ ],
507
+ "responses": {
508
+ "200": {
509
+ "description": "Payload of TenderStatsResponse",
510
+ "content": {
511
+ "application/json": {
512
+ "schema": {
513
+ "$ref": "#/components/schemas/tenderStatsResponse"
514
+ }
515
+ }
516
+ }
517
+ }
518
+ },
519
+ "security": [
520
+ {
521
+ "Implicit": [
522
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
523
+ ]
524
+ }
525
+ ]
526
+ }
527
+ },
528
+ "/v1.0/consultants/stats": {
529
+ "get": {
530
+ "tags": [
531
+ "Consultants"
532
+ ],
533
+ "summary": "Aggregated consultant KPIs (total, availability split, avg fit score from latest matches)",
534
+ "operationId": "GetConsultantStats",
535
+ "responses": {
536
+ "200": {
537
+ "description": "Payload of ConsultantStatsResponse",
538
+ "content": {
539
+ "application/json": {
540
+ "schema": {
541
+ "$ref": "#/components/schemas/consultantStatsResponse"
542
+ }
543
+ }
544
+ }
545
+ }
546
+ },
547
+ "security": [
548
+ {
549
+ "Implicit": [
550
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
551
+ ]
552
+ }
553
+ ]
554
+ }
555
+ },
450
556
  "/v1.0/crawl/sources": {
451
557
  "get": {
452
558
  "tags": [
@@ -1436,45 +1542,6 @@
1436
1542
  ]
1437
1543
  }
1438
1544
  },
1439
- "/v1.0/tenders/funnel": {
1440
- "get": {
1441
- "tags": [
1442
- "Tenders"
1443
- ],
1444
- "summary": "Pipeline funnel analytics: stage counts, conversion rates, cycle times",
1445
- "operationId": "GetTenderFunnel",
1446
- "parameters": [
1447
- {
1448
- "name": "windowDays",
1449
- "in": "query",
1450
- "description": "Rolling window in days (default 30, max 365)",
1451
- "schema": {
1452
- "type": "integer",
1453
- "format": "int32"
1454
- }
1455
- }
1456
- ],
1457
- "responses": {
1458
- "200": {
1459
- "description": "Payload of FunnelResponse",
1460
- "content": {
1461
- "application/json": {
1462
- "schema": {
1463
- "$ref": "#/components/schemas/funnelResponse"
1464
- }
1465
- }
1466
- }
1467
- }
1468
- },
1469
- "security": [
1470
- {
1471
- "Implicit": [
1472
- "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1473
- ]
1474
- }
1475
- ]
1476
- }
1477
- },
1478
1545
  "/v1.0/realtime/negotiate": {
1479
1546
  "post": {
1480
1547
  "tags": [
@@ -1515,6 +1582,69 @@
1515
1582
  ]
1516
1583
  }
1517
1584
  },
1585
+ "/v1.0/stream": {
1586
+ "get": {
1587
+ "tags": [
1588
+ "Realtime"
1589
+ ],
1590
+ "summary": "Unified SSE stream: tender/job/crawl/consultant/audit events on one connection",
1591
+ "operationId": "StreamAll",
1592
+ "parameters": [
1593
+ {
1594
+ "name": "channels",
1595
+ "in": "query",
1596
+ "description": "Comma-separated namespaces to include (tender,job,crawl,consultant,audit). Default: all.",
1597
+ "schema": {
1598
+ "type": "string"
1599
+ }
1600
+ }
1601
+ ],
1602
+ "responses": {},
1603
+ "security": [
1604
+ {
1605
+ "Implicit": [
1606
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1607
+ ]
1608
+ }
1609
+ ]
1610
+ }
1611
+ },
1612
+ "/v1.0/tenders/stream-redirect": {
1613
+ "get": {
1614
+ "tags": [
1615
+ "Realtime"
1616
+ ],
1617
+ "summary": "Deprecated: redirects to /v1.0/stream?channels=tender,job",
1618
+ "operationId": "DeprecatedTenderStream",
1619
+ "responses": {},
1620
+ "deprecated": true,
1621
+ "security": [
1622
+ {
1623
+ "Implicit": [
1624
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1625
+ ]
1626
+ }
1627
+ ]
1628
+ }
1629
+ },
1630
+ "/v1.0/crawl/stream-redirect": {
1631
+ "get": {
1632
+ "tags": [
1633
+ "Realtime"
1634
+ ],
1635
+ "summary": "Deprecated: redirects to /v1.0/stream?channels=crawl,job",
1636
+ "operationId": "DeprecatedCrawlStream",
1637
+ "responses": {},
1638
+ "deprecated": true,
1639
+ "security": [
1640
+ {
1641
+ "Implicit": [
1642
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1643
+ ]
1644
+ }
1645
+ ]
1646
+ }
1647
+ },
1518
1648
  "/v1.0/salesforce/opportunities": {
1519
1649
  "get": {
1520
1650
  "tags": [
@@ -1565,39 +1695,23 @@
1565
1695
  ]
1566
1696
  }
1567
1697
  },
1568
- "/v1.0/tenders/{id}/salesforce": {
1698
+ "/v1.0/salesforce/refresh": {
1569
1699
  "post": {
1570
1700
  "tags": [
1571
1701
  "Salesforce"
1572
1702
  ],
1573
- "summary": "Create a Salesforce Opportunity from a Snøkam tender and cache the link.",
1574
- "operationId": "PromoteTenderToSalesforce",
1575
- "parameters": [
1576
- {
1577
- "name": "id",
1578
- "in": "path",
1579
- "required": true,
1580
- "schema": {
1581
- "type": "string"
1582
- }
1583
- }
1584
- ],
1703
+ "summary": "Batch-refresh the cached Salesforce state on every linked Snøkam tender.",
1704
+ "operationId": "RefreshAllSalesforceLinks",
1585
1705
  "responses": {
1586
1706
  "200": {
1587
- "description": "Payload of Tender",
1707
+ "description": "Payload of SalesforceRefreshResult",
1588
1708
  "content": {
1589
1709
  "application/json": {
1590
1710
  "schema": {
1591
- "$ref": "#/components/schemas/tender"
1711
+ "$ref": "#/components/schemas/salesforceRefreshResult"
1592
1712
  }
1593
1713
  }
1594
1714
  }
1595
- },
1596
- "404": {
1597
- "description": "No description"
1598
- },
1599
- "409": {
1600
- "description": "Tender is already linked to a Salesforce Opportunity."
1601
1715
  }
1602
1716
  },
1603
1717
  "security": [
@@ -1609,21 +1723,22 @@
1609
1723
  ]
1610
1724
  }
1611
1725
  },
1612
- "/v1.0/tenders/{id}/salesforce/refresh": {
1726
+ "/v1.0/salesforce/opportunities/{sfId}/import": {
1613
1727
  "post": {
1614
1728
  "tags": [
1615
1729
  "Salesforce"
1616
1730
  ],
1617
- "summary": "Re-sync cached Salesforce Opportunity state (stage / closed / won) onto the tender.",
1618
- "operationId": "RefreshTenderSalesforceLink",
1731
+ "summary": "Create a Snøkam tender stub from an existing Salesforce Opportunity.",
1732
+ "operationId": "ImportSalesforceOpportunity",
1619
1733
  "parameters": [
1620
1734
  {
1621
- "name": "id",
1735
+ "name": "sfId",
1622
1736
  "in": "path",
1623
1737
  "required": true,
1624
1738
  "schema": {
1625
1739
  "type": "string"
1626
- }
1740
+ },
1741
+ "x-ms-summary": "Salesforce Opportunity Id."
1627
1742
  }
1628
1743
  ],
1629
1744
  "responses": {
@@ -1639,6 +1754,9 @@
1639
1754
  },
1640
1755
  "404": {
1641
1756
  "description": "No description"
1757
+ },
1758
+ "409": {
1759
+ "description": "A tender is already linked to this Opportunity."
1642
1760
  }
1643
1761
  },
1644
1762
  "security": [
@@ -1650,34 +1768,39 @@
1650
1768
  ]
1651
1769
  }
1652
1770
  },
1653
- "/v1.0/tenders/stats": {
1654
- "get": {
1771
+ "/v1.0/tenders/{id}/salesforce": {
1772
+ "post": {
1655
1773
  "tags": [
1656
- "Tenders"
1774
+ "Salesforce"
1657
1775
  ],
1658
- "summary": "Aggregated tender KPIs for the admin dashboard (by status/stage/health + activity window)",
1659
- "operationId": "GetTenderStats",
1776
+ "summary": "Create a Salesforce Opportunity from a Snøkam tender and cache the link.",
1777
+ "operationId": "PromoteTenderToSalesforce",
1660
1778
  "parameters": [
1661
1779
  {
1662
- "name": "windowDays",
1663
- "in": "query",
1664
- "description": "Rolling window for activity-based metrics (defaults to 30, max 365)",
1780
+ "name": "id",
1781
+ "in": "path",
1782
+ "required": true,
1665
1783
  "schema": {
1666
- "type": "integer",
1667
- "format": "int32"
1784
+ "type": "string"
1668
1785
  }
1669
1786
  }
1670
1787
  ],
1671
1788
  "responses": {
1672
1789
  "200": {
1673
- "description": "Payload of TenderStatsResponse",
1790
+ "description": "Payload of Tender",
1674
1791
  "content": {
1675
1792
  "application/json": {
1676
1793
  "schema": {
1677
- "$ref": "#/components/schemas/tenderStatsResponse"
1794
+ "$ref": "#/components/schemas/tender"
1678
1795
  }
1679
1796
  }
1680
1797
  }
1798
+ },
1799
+ "404": {
1800
+ "description": "No description"
1801
+ },
1802
+ "409": {
1803
+ "description": "Tender is already linked to a Salesforce Opportunity."
1681
1804
  }
1682
1805
  },
1683
1806
  "security": [
@@ -1689,23 +1812,36 @@
1689
1812
  ]
1690
1813
  }
1691
1814
  },
1692
- "/v1.0/consultants/stats": {
1693
- "get": {
1815
+ "/v1.0/tenders/{id}/salesforce/refresh": {
1816
+ "post": {
1694
1817
  "tags": [
1695
- "Consultants"
1818
+ "Salesforce"
1819
+ ],
1820
+ "summary": "Re-sync cached Salesforce Opportunity state (stage / closed / won) onto the tender.",
1821
+ "operationId": "RefreshTenderSalesforceLink",
1822
+ "parameters": [
1823
+ {
1824
+ "name": "id",
1825
+ "in": "path",
1826
+ "required": true,
1827
+ "schema": {
1828
+ "type": "string"
1829
+ }
1830
+ }
1696
1831
  ],
1697
- "summary": "Aggregated consultant KPIs (total, availability split, avg fit score from latest matches)",
1698
- "operationId": "GetConsultantStats",
1699
1832
  "responses": {
1700
1833
  "200": {
1701
- "description": "Payload of ConsultantStatsResponse",
1834
+ "description": "Payload of Tender",
1702
1835
  "content": {
1703
1836
  "application/json": {
1704
1837
  "schema": {
1705
- "$ref": "#/components/schemas/consultantStatsResponse"
1838
+ "$ref": "#/components/schemas/tender"
1706
1839
  }
1707
1840
  }
1708
1841
  }
1842
+ },
1843
+ "404": {
1844
+ "description": "No description"
1709
1845
  }
1710
1846
  },
1711
1847
  "security": [
@@ -1717,69 +1853,6 @@
1717
1853
  ]
1718
1854
  }
1719
1855
  },
1720
- "/v1.0/stream": {
1721
- "get": {
1722
- "tags": [
1723
- "Realtime"
1724
- ],
1725
- "summary": "Unified SSE stream: tender/job/crawl/consultant/audit events on one connection",
1726
- "operationId": "StreamAll",
1727
- "parameters": [
1728
- {
1729
- "name": "channels",
1730
- "in": "query",
1731
- "description": "Comma-separated namespaces to include (tender,job,crawl,consultant,audit). Default: all.",
1732
- "schema": {
1733
- "type": "string"
1734
- }
1735
- }
1736
- ],
1737
- "responses": {},
1738
- "security": [
1739
- {
1740
- "Implicit": [
1741
- "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1742
- ]
1743
- }
1744
- ]
1745
- }
1746
- },
1747
- "/v1.0/tenders/stream-redirect": {
1748
- "get": {
1749
- "tags": [
1750
- "Realtime"
1751
- ],
1752
- "summary": "Deprecated: redirects to /v1.0/stream?channels=tender,job",
1753
- "operationId": "DeprecatedTenderStream",
1754
- "responses": {},
1755
- "deprecated": true,
1756
- "security": [
1757
- {
1758
- "Implicit": [
1759
- "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1760
- ]
1761
- }
1762
- ]
1763
- }
1764
- },
1765
- "/v1.0/crawl/stream-redirect": {
1766
- "get": {
1767
- "tags": [
1768
- "Realtime"
1769
- ],
1770
- "summary": "Deprecated: redirects to /v1.0/stream?channels=crawl,job",
1771
- "operationId": "DeprecatedCrawlStream",
1772
- "responses": {},
1773
- "deprecated": true,
1774
- "security": [
1775
- {
1776
- "Implicit": [
1777
- "api://d7f15838-af74-4048-88b3-503089de0064/.default"
1778
- ]
1779
- }
1780
- ]
1781
- }
1782
- },
1783
1856
  "/v1.0/tenders": {
1784
1857
  "get": {
1785
1858
  "tags": [
@@ -1969,6 +2042,146 @@
1969
2042
  ]
1970
2043
  }
1971
2044
  },
2045
+ "/v1.0/tenders/{id}/reingest": {
2046
+ "post": {
2047
+ "tags": [
2048
+ "Tenders"
2049
+ ],
2050
+ "summary": "Re-run the ingestion pipeline on an existing tender, re-parsing documents and refreshing AI match / summary / classification.",
2051
+ "operationId": "ReingestTender",
2052
+ "parameters": [
2053
+ {
2054
+ "name": "id",
2055
+ "in": "path",
2056
+ "required": true,
2057
+ "schema": {
2058
+ "type": "string"
2059
+ }
2060
+ }
2061
+ ],
2062
+ "responses": {
2063
+ "200": {
2064
+ "description": "Payload of AgentJob",
2065
+ "content": {
2066
+ "application/json": {
2067
+ "schema": {
2068
+ "$ref": "#/components/schemas/agentJob"
2069
+ }
2070
+ }
2071
+ }
2072
+ },
2073
+ "404": {
2074
+ "description": "No description"
2075
+ }
2076
+ },
2077
+ "security": [
2078
+ {
2079
+ "Implicit": [
2080
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
2081
+ ]
2082
+ }
2083
+ ]
2084
+ }
2085
+ },
2086
+ "/v1.0/tenders/{id}/jobs/{jobId}/snapshot": {
2087
+ "get": {
2088
+ "tags": [
2089
+ "Tenders"
2090
+ ],
2091
+ "summary": "Return the tender as it looked right after a given agent job ran (time-travel view).",
2092
+ "operationId": "GetTenderJobSnapshot",
2093
+ "parameters": [
2094
+ {
2095
+ "name": "id",
2096
+ "in": "path",
2097
+ "required": true,
2098
+ "schema": {
2099
+ "type": "string"
2100
+ }
2101
+ },
2102
+ {
2103
+ "name": "jobId",
2104
+ "in": "path",
2105
+ "required": true,
2106
+ "schema": {
2107
+ "type": "string"
2108
+ }
2109
+ }
2110
+ ],
2111
+ "responses": {
2112
+ "200": {
2113
+ "description": "Payload of Tender",
2114
+ "content": {
2115
+ "application/json": {
2116
+ "schema": {
2117
+ "$ref": "#/components/schemas/tender"
2118
+ }
2119
+ }
2120
+ }
2121
+ },
2122
+ "404": {
2123
+ "description": "No description"
2124
+ }
2125
+ },
2126
+ "security": [
2127
+ {
2128
+ "Implicit": [
2129
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
2130
+ ]
2131
+ }
2132
+ ]
2133
+ }
2134
+ },
2135
+ "/v1.0/tenders/{id}/jobs": {
2136
+ "get": {
2137
+ "tags": [
2138
+ "Tenders"
2139
+ ],
2140
+ "summary": "Recent agent jobs (ingestion, CV matching, …) for a tender — newest first.",
2141
+ "operationId": "ListTenderJobs",
2142
+ "parameters": [
2143
+ {
2144
+ "name": "id",
2145
+ "in": "path",
2146
+ "required": true,
2147
+ "schema": {
2148
+ "type": "string"
2149
+ }
2150
+ },
2151
+ {
2152
+ "name": "limit",
2153
+ "in": "query",
2154
+ "schema": {
2155
+ "type": "integer",
2156
+ "format": "int32"
2157
+ },
2158
+ "x-ms-summary": "Max rows (default 10, capped at 100)."
2159
+ }
2160
+ ],
2161
+ "responses": {
2162
+ "200": {
2163
+ "description": "Payload of Array of AgentJob",
2164
+ "content": {
2165
+ "application/json": {
2166
+ "schema": {
2167
+ "type": "array",
2168
+ "items": {
2169
+ "$ref": "#/components/schemas/agentJob"
2170
+ }
2171
+ }
2172
+ }
2173
+ }
2174
+ }
2175
+ },
2176
+ "security": [
2177
+ {
2178
+ "Implicit": [
2179
+ "api://d7f15838-af74-4048-88b3-503089de0064/.default"
2180
+ ]
2181
+ }
2182
+ ]
2183
+ }
2184
+ },
1972
2185
  "/v1.0/admin/tenders": {
1973
2186
  "delete": {
1974
2187
  "tags": [
@@ -2184,6 +2397,10 @@
2184
2397
  "$ref": "#/components/schemas/agentJobLogEntry"
2185
2398
  },
2186
2399
  "nullable": true
2400
+ },
2401
+ "afterSnapshot": {
2402
+ "type": "string",
2403
+ "nullable": true
2187
2404
  }
2188
2405
  }
2189
2406
  },
@@ -3106,6 +3323,19 @@
3106
3323
  },
3107
3324
  "nullable": true
3108
3325
  },
3326
+ "salesforceRefreshResult": {
3327
+ "type": "object",
3328
+ "properties": {
3329
+ "checked": {
3330
+ "type": "integer",
3331
+ "format": "int32"
3332
+ },
3333
+ "updated": {
3334
+ "type": "integer",
3335
+ "format": "int32"
3336
+ }
3337
+ }
3338
+ },
3109
3339
  "sourceFile": {
3110
3340
  "type": "object",
3111
3341
  "properties": {