@goable-io/sdk 0.1.1 → 0.2.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.
@@ -460,7 +460,7 @@ export interface paths {
460
460
  };
461
461
  get?: never;
462
462
  put?: never;
463
- /** Counterfactual analysis (L7): binding constraint + sensitivities + best window/spot */
463
+ /** Counterfactual analysis: binding constraint + sensitivities + best window/spot */
464
464
  post: {
465
465
  parameters: {
466
466
  query?: never;
@@ -541,7 +541,7 @@ export interface paths {
541
541
  };
542
542
  get?: never;
543
543
  put?: never;
544
- /** Personalized go/no-go decision (L6, Pro+) */
544
+ /** Personalized go/no-go decision (Pro+) */
545
545
  post: {
546
546
  parameters: {
547
547
  query?: never;
@@ -947,6 +947,1050 @@ export interface paths {
947
947
  patch?: never;
948
948
  trace?: never;
949
949
  };
950
+ "/v1/underwriting/bind": {
951
+ parameters: {
952
+ query?: never;
953
+ header?: never;
954
+ path?: never;
955
+ cookie?: never;
956
+ };
957
+ get?: never;
958
+ put?: never;
959
+ /**
960
+ * Bind a parametric policy (Scale)
961
+ * @description Convert a recent /v1/underwriting/quote into a bound policy. Submit the quoteId (≤24h old); returns a policyId + immutable cohortHash anchoring the bound weather sample set.
962
+ */
963
+ post: {
964
+ parameters: {
965
+ query?: never;
966
+ header?: never;
967
+ path?: never;
968
+ cookie?: never;
969
+ };
970
+ requestBody: {
971
+ content: {
972
+ "application/json": {
973
+ quoteId: string;
974
+ premiumConfirmation?: {
975
+ [key: string]: unknown;
976
+ };
977
+ } & {
978
+ [key: string]: unknown;
979
+ };
980
+ };
981
+ };
982
+ responses: {
983
+ /** @description Bound policy id + cohort hash + settlement schedule */
984
+ 200: {
985
+ headers: {
986
+ [name: string]: unknown;
987
+ };
988
+ content: {
989
+ "application/json": {
990
+ [key: string]: unknown;
991
+ };
992
+ };
993
+ };
994
+ /** @description Requires Scale plan */
995
+ 402: {
996
+ headers: {
997
+ [name: string]: unknown;
998
+ };
999
+ content: {
1000
+ "application/json": components["schemas"]["Error"];
1001
+ };
1002
+ };
1003
+ /** @description Quote expired or not found */
1004
+ 404: {
1005
+ headers: {
1006
+ [name: string]: unknown;
1007
+ };
1008
+ content: {
1009
+ "application/json": components["schemas"]["Error"];
1010
+ };
1011
+ };
1012
+ /** @description Validation error */
1013
+ 422: {
1014
+ headers: {
1015
+ [name: string]: unknown;
1016
+ };
1017
+ content: {
1018
+ "application/json": components["schemas"]["Error"];
1019
+ };
1020
+ };
1021
+ };
1022
+ };
1023
+ delete?: never;
1024
+ options?: never;
1025
+ head?: never;
1026
+ patch?: never;
1027
+ trace?: never;
1028
+ };
1029
+ "/v1/underwriting/evaluate": {
1030
+ parameters: {
1031
+ query?: never;
1032
+ header?: never;
1033
+ path?: never;
1034
+ cookie?: never;
1035
+ };
1036
+ get?: never;
1037
+ put?: never;
1038
+ /**
1039
+ * Read-only payout projection for a bound policy (Scale)
1040
+ * @description Returns the current accrued shortfall + projected payout for a bound policy. Does NOT settle — settlement runs automatically on a cron at policy expiry.
1041
+ */
1042
+ post: {
1043
+ parameters: {
1044
+ query?: never;
1045
+ header?: never;
1046
+ path?: never;
1047
+ cookie?: never;
1048
+ };
1049
+ requestBody: {
1050
+ content: {
1051
+ "application/json": {
1052
+ policyId: string;
1053
+ };
1054
+ };
1055
+ };
1056
+ responses: {
1057
+ /** @description Accrued shortfall + projected payout per currency */
1058
+ 200: {
1059
+ headers: {
1060
+ [name: string]: unknown;
1061
+ };
1062
+ content: {
1063
+ "application/json": {
1064
+ [key: string]: unknown;
1065
+ };
1066
+ };
1067
+ };
1068
+ /** @description Requires Scale plan */
1069
+ 402: {
1070
+ headers: {
1071
+ [name: string]: unknown;
1072
+ };
1073
+ content: {
1074
+ "application/json": components["schemas"]["Error"];
1075
+ };
1076
+ };
1077
+ /** @description Policy not found */
1078
+ 404: {
1079
+ headers: {
1080
+ [name: string]: unknown;
1081
+ };
1082
+ content: {
1083
+ "application/json": components["schemas"]["Error"];
1084
+ };
1085
+ };
1086
+ /** @description Validation error */
1087
+ 422: {
1088
+ headers: {
1089
+ [name: string]: unknown;
1090
+ };
1091
+ content: {
1092
+ "application/json": components["schemas"]["Error"];
1093
+ };
1094
+ };
1095
+ };
1096
+ };
1097
+ delete?: never;
1098
+ options?: never;
1099
+ head?: never;
1100
+ patch?: never;
1101
+ trace?: never;
1102
+ };
1103
+ "/v1/score/{sessionId}/outcome": {
1104
+ parameters: {
1105
+ query?: never;
1106
+ header?: never;
1107
+ path?: never;
1108
+ cookie?: never;
1109
+ };
1110
+ get?: never;
1111
+ put?: never;
1112
+ /**
1113
+ * Report observed outcome for a scored session
1114
+ * @description Close the calibration loop. Submit the actual outcome (ran/cancelled/no_show/rescheduled/note) of a /v1/score session. The calibration pipeline + forecast verification + drift monitor consume these. Requires the `outcomes:write` scope (live keys carry it by default; test keys don't).
1115
+ */
1116
+ post: {
1117
+ parameters: {
1118
+ query?: never;
1119
+ header?: never;
1120
+ path: {
1121
+ /** @description Session UUID returned in the /v1/score response metadata. */
1122
+ sessionId: string;
1123
+ };
1124
+ cookie?: never;
1125
+ };
1126
+ requestBody: {
1127
+ content: {
1128
+ "application/json": {
1129
+ /** @enum {string} */
1130
+ outcome_type: "ran" | "cancelled" | "rescheduled" | "no_show" | "note";
1131
+ detail?: {
1132
+ [key: string]: unknown;
1133
+ };
1134
+ };
1135
+ };
1136
+ };
1137
+ responses: {
1138
+ /** @description Accepted (queued for the next calibration batch) */
1139
+ 202: {
1140
+ headers: {
1141
+ [name: string]: unknown;
1142
+ };
1143
+ content: {
1144
+ "application/json": {
1145
+ [key: string]: unknown;
1146
+ };
1147
+ };
1148
+ };
1149
+ /** @description Missing scope: outcomes:write */
1150
+ 403: {
1151
+ headers: {
1152
+ [name: string]: unknown;
1153
+ };
1154
+ content: {
1155
+ "application/json": components["schemas"]["Error"];
1156
+ };
1157
+ };
1158
+ /** @description Session not found */
1159
+ 404: {
1160
+ headers: {
1161
+ [name: string]: unknown;
1162
+ };
1163
+ content: {
1164
+ "application/json": components["schemas"]["Error"];
1165
+ };
1166
+ };
1167
+ /** @description Validation error */
1168
+ 422: {
1169
+ headers: {
1170
+ [name: string]: unknown;
1171
+ };
1172
+ content: {
1173
+ "application/json": components["schemas"]["Error"];
1174
+ };
1175
+ };
1176
+ };
1177
+ };
1178
+ delete?: never;
1179
+ options?: never;
1180
+ head?: never;
1181
+ patch?: never;
1182
+ trace?: never;
1183
+ };
1184
+ "/v1/score/difficulty": {
1185
+ parameters: {
1186
+ query?: never;
1187
+ header?: never;
1188
+ path?: never;
1189
+ cookie?: never;
1190
+ };
1191
+ get?: never;
1192
+ put?: never;
1193
+ /**
1194
+ * Skill-conditioned scoring
1195
+ * @description Same scoring engine, but conditioned on a rider/operator skill level. Returns the score curve as a function of skill so a booking flow can branch ("good for beginners" vs "experts only").
1196
+ */
1197
+ post: {
1198
+ parameters: {
1199
+ query?: never;
1200
+ header?: never;
1201
+ path?: never;
1202
+ cookie?: never;
1203
+ };
1204
+ requestBody: {
1205
+ content: {
1206
+ "application/json": {
1207
+ activity: string;
1208
+ location: components["schemas"]["GeoPoint"];
1209
+ window?: components["schemas"]["TimeWindow"];
1210
+ /** @description Skill points (0-1) to score. Defaults to 5 quantile points. */
1211
+ riderSkillLevels?: number[];
1212
+ };
1213
+ };
1214
+ };
1215
+ responses: {
1216
+ /** @description Score per skill level + difficulty band */
1217
+ 200: {
1218
+ headers: {
1219
+ [name: string]: unknown;
1220
+ };
1221
+ content: {
1222
+ "application/json": {
1223
+ [key: string]: unknown;
1224
+ };
1225
+ };
1226
+ };
1227
+ /** @description No profile for activity */
1228
+ 404: {
1229
+ headers: {
1230
+ [name: string]: unknown;
1231
+ };
1232
+ content: {
1233
+ "application/json": components["schemas"]["Error"];
1234
+ };
1235
+ };
1236
+ /** @description Validation error */
1237
+ 422: {
1238
+ headers: {
1239
+ [name: string]: unknown;
1240
+ };
1241
+ content: {
1242
+ "application/json": components["schemas"]["Error"];
1243
+ };
1244
+ };
1245
+ };
1246
+ };
1247
+ delete?: never;
1248
+ options?: never;
1249
+ head?: never;
1250
+ patch?: never;
1251
+ trace?: never;
1252
+ };
1253
+ "/v1/recommend-spot": {
1254
+ parameters: {
1255
+ query?: never;
1256
+ header?: never;
1257
+ path?: never;
1258
+ cookie?: never;
1259
+ };
1260
+ get?: never;
1261
+ put?: never;
1262
+ /**
1263
+ * Spot recommender — inverse query (L10)
1264
+ * @description Given (activity, region center, radius, window) → top-K ranked sub-spots in the catalog. Composition of L1-L3 scoring + L4.6 confidence + L6 personal blend (Pro+, when pseudonym supplied). Plan caps: radius 25/50/200/1000 km, topK 5/10/20/50 across Free / Starter / Pro / Scale. Personalization Pro+ only. Hard-gated candidates (lightning ≥ 0.85, AQI hazardous) are dropped from results; `allGated=true` distinguishes 'all in-radius spots were unsafe' from 'no spots in radius at all'.
1265
+ */
1266
+ post: {
1267
+ parameters: {
1268
+ query?: never;
1269
+ header?: never;
1270
+ path?: never;
1271
+ cookie?: never;
1272
+ };
1273
+ requestBody: {
1274
+ content: {
1275
+ "application/json": {
1276
+ activity: string;
1277
+ regionCenter: components["schemas"]["GeoPoint"];
1278
+ radiusKm: number;
1279
+ topK: number;
1280
+ window?: components["schemas"]["TimeWindow"];
1281
+ /** @description Optional booking-platform-side pseudonym. When present, Pro+ tenants get personalization via the L6 cold-start blend (cap 0.5 weight). */
1282
+ userPseudonym?: string;
1283
+ };
1284
+ };
1285
+ };
1286
+ responses: {
1287
+ /** @description Ranked top-K sub-spots + observability metadata. The optional `coverage` field appears only on empty results from a catalog gap (not from hard-gating). */
1288
+ 200: {
1289
+ headers: {
1290
+ [name: string]: unknown;
1291
+ };
1292
+ content: {
1293
+ "application/json": {
1294
+ results?: {
1295
+ spotSlug?: string;
1296
+ name?: string;
1297
+ location?: components["schemas"]["GeoPoint"];
1298
+ distanceKm?: number;
1299
+ score?: number;
1300
+ effectiveScore?: number;
1301
+ verdict?: string;
1302
+ personalScore?: number | null;
1303
+ personalWeight?: number;
1304
+ rank?: number;
1305
+ }[];
1306
+ allGated?: boolean;
1307
+ totalCandidates?: number;
1308
+ rankedCandidates?: number;
1309
+ effectiveRadiusKm?: number;
1310
+ effectiveTopK?: number;
1311
+ personalizationApplied?: boolean;
1312
+ latencyMs?: number;
1313
+ coverage?: {
1314
+ /** @enum {string} */
1315
+ status: "no_subspots_in_radius";
1316
+ nearestSubSpot: {
1317
+ slug: string;
1318
+ name: string;
1319
+ distanceKm: number;
1320
+ };
1321
+ /** @enum {string} */
1322
+ suggestedAction: "expand_radius";
1323
+ suggestedRadiusKm: number;
1324
+ } | {
1325
+ /** @enum {string} */
1326
+ status: "no_subspots_for_activity";
1327
+ /** @enum {string} */
1328
+ suggestedAction: "request_coverage";
1329
+ };
1330
+ };
1331
+ };
1332
+ };
1333
+ /** @description Missing/invalid bearer token */
1334
+ 401: {
1335
+ headers: {
1336
+ [name: string]: unknown;
1337
+ };
1338
+ content: {
1339
+ "application/json": components["schemas"]["Error"];
1340
+ };
1341
+ };
1342
+ /** @description Plan limit exceeded (radius or topK above plan cap) */
1343
+ 402: {
1344
+ headers: {
1345
+ [name: string]: unknown;
1346
+ };
1347
+ content: {
1348
+ "application/json": components["schemas"]["Error"];
1349
+ };
1350
+ };
1351
+ /** @description Validation error or unknown activity */
1352
+ 422: {
1353
+ headers: {
1354
+ [name: string]: unknown;
1355
+ };
1356
+ content: {
1357
+ "application/json": components["schemas"]["Error"];
1358
+ };
1359
+ };
1360
+ /** @description Spatial resolver not wired */
1361
+ 503: {
1362
+ headers: {
1363
+ [name: string]: unknown;
1364
+ };
1365
+ content: {
1366
+ "application/json": components["schemas"]["Error"];
1367
+ };
1368
+ };
1369
+ };
1370
+ };
1371
+ delete?: never;
1372
+ options?: never;
1373
+ head?: never;
1374
+ patch?: never;
1375
+ trace?: never;
1376
+ };
1377
+ "/v1/intelligence/edge-case": {
1378
+ parameters: {
1379
+ query?: never;
1380
+ header?: never;
1381
+ path?: never;
1382
+ cookie?: never;
1383
+ };
1384
+ get?: never;
1385
+ put?: never;
1386
+ /**
1387
+ * LLM analysis of a borderline / surprising score (L2c, Pro+)
1388
+ * @description Asks the LLM to inspect a score that's near a verdict boundary or contradicts operator intuition. Returns a narrative + a structured `limiting_class` taxonomy entry.
1389
+ */
1390
+ post: {
1391
+ parameters: {
1392
+ query?: never;
1393
+ header?: never;
1394
+ path?: never;
1395
+ cookie?: never;
1396
+ };
1397
+ requestBody: {
1398
+ content: {
1399
+ "application/json": {
1400
+ location: components["schemas"]["GeoPoint"];
1401
+ scoreResult?: components["schemas"]["ScoreResponse"];
1402
+ /** Format: uuid */
1403
+ session_id?: string;
1404
+ /** @enum {string} */
1405
+ locale?: "en" | "it";
1406
+ /** @enum {string} */
1407
+ model?: "claude-haiku-4-5-20251001" | "claude-sonnet-4-6";
1408
+ };
1409
+ };
1410
+ };
1411
+ responses: {
1412
+ /** @description Narrative + limiting_class */
1413
+ 200: {
1414
+ headers: {
1415
+ [name: string]: unknown;
1416
+ };
1417
+ content: {
1418
+ "application/json": {
1419
+ [key: string]: unknown;
1420
+ };
1421
+ };
1422
+ };
1423
+ /** @description Requires Pro+ plan */
1424
+ 402: {
1425
+ headers: {
1426
+ [name: string]: unknown;
1427
+ };
1428
+ content: {
1429
+ "application/json": components["schemas"]["Error"];
1430
+ };
1431
+ };
1432
+ /** @description Validation error */
1433
+ 422: {
1434
+ headers: {
1435
+ [name: string]: unknown;
1436
+ };
1437
+ content: {
1438
+ "application/json": components["schemas"]["Error"];
1439
+ };
1440
+ };
1441
+ };
1442
+ };
1443
+ delete?: never;
1444
+ options?: never;
1445
+ head?: never;
1446
+ patch?: never;
1447
+ trace?: never;
1448
+ };
1449
+ "/v1/projections/portfolio": {
1450
+ parameters: {
1451
+ query?: never;
1452
+ header?: never;
1453
+ path?: never;
1454
+ cookie?: never;
1455
+ };
1456
+ get?: never;
1457
+ put?: never;
1458
+ /** Climate projections across a portfolio of spots (Scale) */
1459
+ post: {
1460
+ parameters: {
1461
+ query?: never;
1462
+ header?: never;
1463
+ path?: never;
1464
+ cookie?: never;
1465
+ };
1466
+ requestBody: {
1467
+ content: {
1468
+ "application/json": {
1469
+ spots: {
1470
+ location: components["schemas"]["GeoPoint"];
1471
+ activity: string;
1472
+ spotId?: string;
1473
+ }[];
1474
+ scenarios: ("SSP1-2.6" | "SSP2-4.5" | "SSP3-7.0" | "SSP5-8.5")[];
1475
+ horizonDecades?: string[];
1476
+ /** @enum {string} */
1477
+ baselineDecade?: "2020s" | "2030s";
1478
+ };
1479
+ };
1480
+ };
1481
+ responses: {
1482
+ /** @description Per-spot per-decade projection distributions */
1483
+ 200: {
1484
+ headers: {
1485
+ [name: string]: unknown;
1486
+ };
1487
+ content: {
1488
+ "application/json": {
1489
+ [key: string]: unknown;
1490
+ };
1491
+ };
1492
+ };
1493
+ /** @description Requires Scale plan */
1494
+ 402: {
1495
+ headers: {
1496
+ [name: string]: unknown;
1497
+ };
1498
+ content: {
1499
+ "application/json": components["schemas"]["Error"];
1500
+ };
1501
+ };
1502
+ /** @description Validation error */
1503
+ 422: {
1504
+ headers: {
1505
+ [name: string]: unknown;
1506
+ };
1507
+ content: {
1508
+ "application/json": components["schemas"]["Error"];
1509
+ };
1510
+ };
1511
+ };
1512
+ };
1513
+ delete?: never;
1514
+ options?: never;
1515
+ head?: never;
1516
+ patch?: never;
1517
+ trace?: never;
1518
+ };
1519
+ "/v1/projections/adaptation-report": {
1520
+ parameters: {
1521
+ query?: never;
1522
+ header?: never;
1523
+ path?: never;
1524
+ cookie?: never;
1525
+ };
1526
+ get?: never;
1527
+ put?: never;
1528
+ /**
1529
+ * Climate adaptation report for an operator (Scale)
1530
+ * @description Combines projections across a portfolio + qualitative summary of which dimensions are likely to bind (wind shifts, water-temp shifts, etc.). Designed as input for a tourism-board adaptation plan.
1531
+ */
1532
+ post: {
1533
+ parameters: {
1534
+ query?: never;
1535
+ header?: never;
1536
+ path?: never;
1537
+ cookie?: never;
1538
+ };
1539
+ requestBody: {
1540
+ content: {
1541
+ "application/json": {
1542
+ spots: ({
1543
+ location: components["schemas"]["GeoPoint"];
1544
+ activity: string;
1545
+ spotId?: string;
1546
+ subSpotSlug?: string;
1547
+ } & {
1548
+ [key: string]: unknown;
1549
+ })[];
1550
+ scenarios: ("SSP1-2.6" | "SSP2-4.5" | "SSP3-7.0" | "SSP5-8.5")[];
1551
+ horizonDecades?: string[];
1552
+ } & {
1553
+ [key: string]: unknown;
1554
+ };
1555
+ };
1556
+ };
1557
+ responses: {
1558
+ /** @description Adaptation report + binding-dimension summary */
1559
+ 200: {
1560
+ headers: {
1561
+ [name: string]: unknown;
1562
+ };
1563
+ content: {
1564
+ "application/json": {
1565
+ [key: string]: unknown;
1566
+ };
1567
+ };
1568
+ };
1569
+ /** @description Requires Scale plan */
1570
+ 402: {
1571
+ headers: {
1572
+ [name: string]: unknown;
1573
+ };
1574
+ content: {
1575
+ "application/json": components["schemas"]["Error"];
1576
+ };
1577
+ };
1578
+ /** @description Validation error */
1579
+ 422: {
1580
+ headers: {
1581
+ [name: string]: unknown;
1582
+ };
1583
+ content: {
1584
+ "application/json": components["schemas"]["Error"];
1585
+ };
1586
+ };
1587
+ };
1588
+ };
1589
+ delete?: never;
1590
+ options?: never;
1591
+ head?: never;
1592
+ patch?: never;
1593
+ trace?: never;
1594
+ };
1595
+ "/v1/observations": {
1596
+ parameters: {
1597
+ query?: never;
1598
+ header?: never;
1599
+ path?: never;
1600
+ cookie?: never;
1601
+ };
1602
+ get?: never;
1603
+ put?: never;
1604
+ /**
1605
+ * Submit station observation for data assimilation (Pro+)
1606
+ * @description Push tenant-station observations (wind / wave / temperature / etc.) into the 0-6h assimilation window. The optimal-interpolation blending pulls them into forecast samples for nearby spots, improving short-horizon skill.
1607
+ */
1608
+ post: {
1609
+ parameters: {
1610
+ query?: never;
1611
+ header?: never;
1612
+ path?: never;
1613
+ cookie?: never;
1614
+ };
1615
+ requestBody: {
1616
+ content: {
1617
+ "application/json": {
1618
+ /** Format: uuid */
1619
+ stationId: string;
1620
+ /** Format: date-time */
1621
+ observedAt: string;
1622
+ values: {
1623
+ [key: string]: number;
1624
+ };
1625
+ qualityFlags?: {
1626
+ [key: string]: unknown;
1627
+ };
1628
+ };
1629
+ };
1630
+ };
1631
+ responses: {
1632
+ /** @description Accepted */
1633
+ 202: {
1634
+ headers: {
1635
+ [name: string]: unknown;
1636
+ };
1637
+ content: {
1638
+ "application/json": {
1639
+ [key: string]: unknown;
1640
+ };
1641
+ };
1642
+ };
1643
+ /** @description Requires Pro+ plan */
1644
+ 402: {
1645
+ headers: {
1646
+ [name: string]: unknown;
1647
+ };
1648
+ content: {
1649
+ "application/json": components["schemas"]["Error"];
1650
+ };
1651
+ };
1652
+ /** @description Station not found */
1653
+ 404: {
1654
+ headers: {
1655
+ [name: string]: unknown;
1656
+ };
1657
+ content: {
1658
+ "application/json": components["schemas"]["Error"];
1659
+ };
1660
+ };
1661
+ /** @description Validation error */
1662
+ 422: {
1663
+ headers: {
1664
+ [name: string]: unknown;
1665
+ };
1666
+ content: {
1667
+ "application/json": components["schemas"]["Error"];
1668
+ };
1669
+ };
1670
+ };
1671
+ };
1672
+ delete?: never;
1673
+ options?: never;
1674
+ head?: never;
1675
+ patch?: never;
1676
+ trace?: never;
1677
+ };
1678
+ "/v1/observations/stations": {
1679
+ parameters: {
1680
+ query?: never;
1681
+ header?: never;
1682
+ path?: never;
1683
+ cookie?: never;
1684
+ };
1685
+ /** List tenant stations */
1686
+ get: {
1687
+ parameters: {
1688
+ query?: never;
1689
+ header?: never;
1690
+ path?: never;
1691
+ cookie?: never;
1692
+ };
1693
+ requestBody?: never;
1694
+ responses: {
1695
+ /** @description Array of stations */
1696
+ 200: {
1697
+ headers: {
1698
+ [name: string]: unknown;
1699
+ };
1700
+ content: {
1701
+ "application/json": {
1702
+ [key: string]: unknown;
1703
+ };
1704
+ };
1705
+ };
1706
+ };
1707
+ };
1708
+ put?: never;
1709
+ /** Register a tenant observation station (Pro+) */
1710
+ post: {
1711
+ parameters: {
1712
+ query?: never;
1713
+ header?: never;
1714
+ path?: never;
1715
+ cookie?: never;
1716
+ };
1717
+ requestBody: {
1718
+ content: {
1719
+ "application/json": {
1720
+ name: string;
1721
+ location: components["schemas"]["GeoPoint"];
1722
+ elevationM?: number;
1723
+ metadata?: {
1724
+ [key: string]: unknown;
1725
+ };
1726
+ } & {
1727
+ [key: string]: unknown;
1728
+ };
1729
+ };
1730
+ };
1731
+ responses: {
1732
+ /** @description Station created */
1733
+ 201: {
1734
+ headers: {
1735
+ [name: string]: unknown;
1736
+ };
1737
+ content: {
1738
+ "application/json": {
1739
+ [key: string]: unknown;
1740
+ };
1741
+ };
1742
+ };
1743
+ /** @description Requires Pro+ plan */
1744
+ 402: {
1745
+ headers: {
1746
+ [name: string]: unknown;
1747
+ };
1748
+ content: {
1749
+ "application/json": components["schemas"]["Error"];
1750
+ };
1751
+ };
1752
+ /** @description Validation error */
1753
+ 422: {
1754
+ headers: {
1755
+ [name: string]: unknown;
1756
+ };
1757
+ content: {
1758
+ "application/json": components["schemas"]["Error"];
1759
+ };
1760
+ };
1761
+ };
1762
+ };
1763
+ delete?: never;
1764
+ options?: never;
1765
+ head?: never;
1766
+ patch?: never;
1767
+ trace?: never;
1768
+ };
1769
+ "/v1/observations/stations/{stationId}": {
1770
+ parameters: {
1771
+ query?: never;
1772
+ header?: never;
1773
+ path?: never;
1774
+ cookie?: never;
1775
+ };
1776
+ get?: never;
1777
+ put?: never;
1778
+ post?: never;
1779
+ delete?: never;
1780
+ options?: never;
1781
+ head?: never;
1782
+ /** Update a station (Pro+) */
1783
+ patch: {
1784
+ parameters: {
1785
+ query?: never;
1786
+ header?: never;
1787
+ path: {
1788
+ stationId: string;
1789
+ };
1790
+ cookie?: never;
1791
+ };
1792
+ requestBody: {
1793
+ content: {
1794
+ "application/json": {
1795
+ name?: string;
1796
+ location?: components["schemas"]["GeoPoint"];
1797
+ elevationM?: number;
1798
+ metadata?: {
1799
+ [key: string]: unknown;
1800
+ };
1801
+ } & {
1802
+ [key: string]: unknown;
1803
+ };
1804
+ };
1805
+ };
1806
+ responses: {
1807
+ /** @description Updated station */
1808
+ 200: {
1809
+ headers: {
1810
+ [name: string]: unknown;
1811
+ };
1812
+ content: {
1813
+ "application/json": {
1814
+ [key: string]: unknown;
1815
+ };
1816
+ };
1817
+ };
1818
+ /** @description Requires Pro+ plan */
1819
+ 402: {
1820
+ headers: {
1821
+ [name: string]: unknown;
1822
+ };
1823
+ content: {
1824
+ "application/json": components["schemas"]["Error"];
1825
+ };
1826
+ };
1827
+ /** @description Station not found */
1828
+ 404: {
1829
+ headers: {
1830
+ [name: string]: unknown;
1831
+ };
1832
+ content: {
1833
+ "application/json": components["schemas"]["Error"];
1834
+ };
1835
+ };
1836
+ };
1837
+ };
1838
+ trace?: never;
1839
+ };
1840
+ "/v1/public/signup": {
1841
+ parameters: {
1842
+ query?: never;
1843
+ header?: never;
1844
+ path?: never;
1845
+ cookie?: never;
1846
+ };
1847
+ get?: never;
1848
+ put?: never;
1849
+ /**
1850
+ * Self-service tenant signup (no auth)
1851
+ * @description Public endpoint, IP-rate-limited (3 attempts / 24h / IP). Creates a tenant + sends a magic-link to the contact email. Always returns 202 on success — never reveals whether an email is already registered. Optional Cloudflare Turnstile token strengthens the gate.
1852
+ */
1853
+ post: {
1854
+ parameters: {
1855
+ query?: never;
1856
+ header?: never;
1857
+ path?: never;
1858
+ cookie?: never;
1859
+ };
1860
+ requestBody: {
1861
+ content: {
1862
+ "application/json": {
1863
+ displayName: string;
1864
+ /** Format: email */
1865
+ contactEmail: string;
1866
+ /**
1867
+ * @description Must be true — records ToS / Privacy / DPA acceptance.
1868
+ * @enum {boolean}
1869
+ */
1870
+ acceptTerms: true;
1871
+ turnstileToken?: string;
1872
+ };
1873
+ };
1874
+ };
1875
+ responses: {
1876
+ /** @description Accepted — magic-link sent if signup valid */
1877
+ 202: {
1878
+ headers: {
1879
+ [name: string]: unknown;
1880
+ };
1881
+ content: {
1882
+ "application/json": {
1883
+ [key: string]: unknown;
1884
+ };
1885
+ };
1886
+ };
1887
+ /** @description Validation error */
1888
+ 422: {
1889
+ headers: {
1890
+ [name: string]: unknown;
1891
+ };
1892
+ content: {
1893
+ "application/json": components["schemas"]["Error"];
1894
+ };
1895
+ };
1896
+ /** @description IP rate limit exceeded */
1897
+ 429: {
1898
+ headers: {
1899
+ [name: string]: unknown;
1900
+ };
1901
+ content: {
1902
+ "application/json": components["schemas"]["Error"];
1903
+ };
1904
+ };
1905
+ };
1906
+ };
1907
+ delete?: never;
1908
+ options?: never;
1909
+ head?: never;
1910
+ patch?: never;
1911
+ trace?: never;
1912
+ };
1913
+ "/v1/public/catalog-stats": {
1914
+ parameters: {
1915
+ query?: never;
1916
+ header?: never;
1917
+ path?: never;
1918
+ cookie?: never;
1919
+ };
1920
+ /**
1921
+ * Open catalogue coverage stats (no auth)
1922
+ * @description Live coverage numbers for the open activity catalogue (CC BY 4.0). Returns totals across activities · sub-spots · clusters · regions · countries plus a per-activity breakdown with country codes + status (`seeded` ≥10 sub-spots / `partial` 1-9 / `empty` 0). Edge-cached for 5 minutes — new sub-spots ship via PR + release cycle, not at runtime. Same JSON the /catalog landing renders; expose this surface for marketing / partner sites that want to embed live numbers without scraping HTML.
1923
+ */
1924
+ get: {
1925
+ parameters: {
1926
+ query?: never;
1927
+ header?: never;
1928
+ path?: never;
1929
+ cookie?: never;
1930
+ };
1931
+ requestBody?: never;
1932
+ responses: {
1933
+ /** @description Live coverage stats from the @goable-io/profiles-catalog package */
1934
+ 200: {
1935
+ headers: {
1936
+ [name: string]: unknown;
1937
+ };
1938
+ content: {
1939
+ "application/json": {
1940
+ /**
1941
+ * Format: date-time
1942
+ * @description ISO timestamp the bundled JSON was computed at
1943
+ */
1944
+ computedAt: string;
1945
+ /** @description Catalog package version (mirrors package.json) */
1946
+ catalogVersion: string;
1947
+ totals: {
1948
+ activities: number;
1949
+ subSpots: number;
1950
+ clusters: number;
1951
+ regions: number;
1952
+ countries: number;
1953
+ };
1954
+ /** @description One entry per base profile, sorted DESC by subSpotCount. */
1955
+ byActivity: {
1956
+ slug?: string;
1957
+ /** @enum {string} */
1958
+ family?: "water" | "snow" | "air" | "land";
1959
+ displayName?: string;
1960
+ subSpotCount?: number;
1961
+ clusterCount?: number;
1962
+ countryCount?: number;
1963
+ countries?: string[];
1964
+ clusters?: {
1965
+ slug?: string;
1966
+ displayName?: string;
1967
+ countryCode?: string;
1968
+ subSpotCount?: number;
1969
+ }[];
1970
+ /**
1971
+ * @description seeded ≥10 sub-spots · partial 1-9 · empty 0
1972
+ * @enum {string}
1973
+ */
1974
+ status?: "seeded" | "partial" | "empty";
1975
+ /**
1976
+ * Format: date-time
1977
+ * @description Newest commit touching the activity dir (null when no sub-spots yet)
1978
+ */
1979
+ lastUpdatedAt?: string | null;
1980
+ }[];
1981
+ };
1982
+ };
1983
+ };
1984
+ };
1985
+ };
1986
+ put?: never;
1987
+ post?: never;
1988
+ delete?: never;
1989
+ options?: never;
1990
+ head?: never;
1991
+ patch?: never;
1992
+ trace?: never;
1993
+ };
950
1994
  }
951
1995
  export type webhooks = Record<string, never>;
952
1996
  export interface components {