@medalsocial/sdk 1.5.0 → 1.7.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.
@@ -21,6 +21,11 @@ tags:
21
21
  description: Manage workspace CRM contacts.
22
22
  - name: Deals
23
23
  description: Manage sponsorship and brand deals.
24
+ - name: Bookings
25
+ description: >-
26
+ Appointment bookings — the service catalogue, free slots, staff actions
27
+ on a booking, and the customer-facing manage-token routes. Money is
28
+ always integer øre.
24
29
  - name: GDPR
25
30
  description: Manage exports, consent records, and cookie consent.
26
31
  - name: Workspaces
@@ -29,10 +34,19 @@ tags:
29
34
  description: Read helpdesk conversations, reply, and manage assignment/status.
30
35
  - name: Webhooks
31
36
  description: Manage webhook endpoints and inspect their deliveries.
37
+ - name: Capabilities
38
+ description: >-
39
+ Mint short-lived capability confirmation tokens for confirmable write
40
+ routes.
32
41
  - name: Channels
33
42
  description: >-
34
43
  Partner channel connect — mint hosted connect links and manage the
35
44
  resulting channel connections.
45
+ - name: Scan
46
+ description: >-
47
+ Company & website scans (Nettsjekk) — queue a scan by URL, organisation
48
+ number, or company name, poll the result, and search the Norwegian
49
+ company registry.
36
50
  paths:
37
51
  /api/v1/posts:
38
52
  get:
@@ -534,6 +548,356 @@ paths:
534
548
  $ref: "#/components/schemas/ApiResponse_DealRemoveResult"
535
549
  default:
536
550
  $ref: "#/components/responses/ApiError"
551
+ /api/v1/bookings:
552
+ get:
553
+ tags: [Bookings]
554
+ operationId: listBookings
555
+ summary: List bookings
556
+ parameters:
557
+ - $ref: "#/components/parameters/Limit"
558
+ - $ref: "#/components/parameters/Cursor"
559
+ - name: from_ts
560
+ in: query
561
+ description: Only bookings starting at or after this instant.
562
+ schema:
563
+ $ref: "#/components/schemas/BookingTimestampInput"
564
+ - name: to_ts
565
+ in: query
566
+ description: Only bookings starting before this instant.
567
+ schema:
568
+ $ref: "#/components/schemas/BookingTimestampInput"
569
+ - name: status
570
+ in: query
571
+ schema:
572
+ $ref: "#/components/schemas/BookingStatus"
573
+ - name: resource_id
574
+ in: query
575
+ schema:
576
+ type: string
577
+ responses:
578
+ "200":
579
+ description: Bookings page.
580
+ content:
581
+ application/json:
582
+ schema:
583
+ $ref: "#/components/schemas/PaginatedResponse_Booking"
584
+ default:
585
+ $ref: "#/components/responses/ApiError"
586
+ post:
587
+ tags: [Bookings]
588
+ operationId: createBooking
589
+ summary: Create a booking or party
590
+ description: >-
591
+ Books every item or none of them. Each created booking carries a
592
+ `manage_token` returned exactly once — only its hash is stored, and an
593
+ idempotent replay omits it.
594
+ requestBody:
595
+ required: true
596
+ content:
597
+ application/json:
598
+ schema:
599
+ $ref: "#/components/schemas/CreateBookingInput"
600
+ responses:
601
+ "201":
602
+ description: Created bookings, in request order.
603
+ content:
604
+ application/json:
605
+ schema:
606
+ $ref: "#/components/schemas/ApiResponse_BookingCreateResult"
607
+ default:
608
+ $ref: "#/components/responses/ApiError"
609
+ /api/v1/bookings/services:
610
+ get:
611
+ tags: [Bookings]
612
+ operationId: listBookingServices
613
+ summary: List bookable services
614
+ parameters:
615
+ - name: include_inactive
616
+ in: query
617
+ description: >-
618
+ Include services with `active: false`. Defaults to active-only.
619
+ schema:
620
+ type: boolean
621
+ responses:
622
+ "200":
623
+ description: Bookable service catalogue.
624
+ content:
625
+ application/json:
626
+ schema:
627
+ $ref: "#/components/schemas/ApiResponse_BookingServiceArray"
628
+ default:
629
+ $ref: "#/components/responses/ApiError"
630
+ /api/v1/bookings/resources:
631
+ get:
632
+ tags: [Bookings]
633
+ operationId: listBookingResources
634
+ summary: List bookable resources
635
+ responses:
636
+ "200":
637
+ description: Bookable resources — staff, rooms, and equipment.
638
+ content:
639
+ application/json:
640
+ schema:
641
+ $ref: "#/components/schemas/ApiResponse_BookingResourceArray"
642
+ default:
643
+ $ref: "#/components/responses/ApiError"
644
+ /api/v1/bookings/availability:
645
+ get:
646
+ tags: [Bookings]
647
+ operationId: listBookingAvailability
648
+ summary: List free slots for a service
649
+ description: >-
650
+ Slots reflect opening hours, time off, buffers, and existing bookings
651
+ at the moment of the call. They are not held.
652
+ parameters:
653
+ - name: service_id
654
+ in: query
655
+ required: true
656
+ schema:
657
+ type: string
658
+ - name: from_ts
659
+ in: query
660
+ required: true
661
+ description: Start of the window.
662
+ schema:
663
+ $ref: "#/components/schemas/BookingTimestampInput"
664
+ - name: to_ts
665
+ in: query
666
+ required: true
667
+ description: End of the window; must be after `from_ts`.
668
+ schema:
669
+ $ref: "#/components/schemas/BookingTimestampInput"
670
+ - name: resource_id
671
+ in: query
672
+ description: Restrict slots to one resource.
673
+ schema:
674
+ type: string
675
+ responses:
676
+ "200":
677
+ description: Free slots.
678
+ content:
679
+ application/json:
680
+ schema:
681
+ $ref: "#/components/schemas/ApiResponse_BookingSlotArray"
682
+ default:
683
+ $ref: "#/components/responses/ApiError"
684
+ /api/v1/bookings/schedule:
685
+ get:
686
+ tags: [Bookings]
687
+ operationId: listBookingSchedule
688
+ summary: List the dates a service can be booked on
689
+ description: >-
690
+ The other half of `availability`. Availability returns free slots and
691
+ nothing else, so a closed day, an evening past closing and a fully
692
+ booked day all come back as the same empty array. This returns one
693
+ entry per date the workspace keeps opening hours on; a date ABSENT from
694
+ the response is closed. `last_start_ts` is the last start this service
695
+ could occupy on that date (it depends on the service's duration and
696
+ buffers, not just the closing time) and is `null` for a date with
697
+ posted hours that is shut outright, such as a public holiday.
698
+ parameters:
699
+ - name: service_id
700
+ in: query
701
+ required: true
702
+ schema:
703
+ type: string
704
+ - name: from_ts
705
+ in: query
706
+ required: true
707
+ description: Start of the window.
708
+ schema:
709
+ $ref: "#/components/schemas/BookingTimestampInput"
710
+ - name: to_ts
711
+ in: query
712
+ required: true
713
+ description: End of the window; must be after `from_ts`.
714
+ schema:
715
+ $ref: "#/components/schemas/BookingTimestampInput"
716
+ - name: resource_id
717
+ in: query
718
+ description: Restrict to one resource's hours.
719
+ schema:
720
+ type: string
721
+ responses:
722
+ "200":
723
+ description: Open dates.
724
+ content:
725
+ application/json:
726
+ schema:
727
+ $ref: "#/components/schemas/ApiResponse_BookingScheduleDayArray"
728
+ default:
729
+ $ref: "#/components/responses/ApiError"
730
+ /api/v1/bookings/{id}:
731
+ parameters:
732
+ - $ref: "#/components/parameters/Id"
733
+ get:
734
+ tags: [Bookings]
735
+ operationId: getBooking
736
+ summary: Get a booking
737
+ responses:
738
+ "200":
739
+ description: Booking.
740
+ content:
741
+ application/json:
742
+ schema:
743
+ $ref: "#/components/schemas/ApiResponse_Booking"
744
+ default:
745
+ $ref: "#/components/responses/ApiError"
746
+ patch:
747
+ tags: [Bookings]
748
+ operationId: updateBooking
749
+ summary: Annotate a booking
750
+ requestBody:
751
+ required: true
752
+ content:
753
+ application/json:
754
+ schema:
755
+ $ref: "#/components/schemas/UpdateBookingInput"
756
+ responses:
757
+ "200":
758
+ description: The updated booking.
759
+ content:
760
+ application/json:
761
+ schema:
762
+ $ref: "#/components/schemas/ApiResponse_Booking"
763
+ default:
764
+ $ref: "#/components/responses/ApiError"
765
+ /api/v1/bookings/{id}/cancel:
766
+ parameters:
767
+ - $ref: "#/components/parameters/Id"
768
+ post:
769
+ tags: [Bookings]
770
+ operationId: cancelBooking
771
+ summary: Cancel a booking as the business
772
+ description: >-
773
+ Staff semantics — the workspace's cancel window is bypassed and the
774
+ cancellation is attributed to staff.
775
+ requestBody:
776
+ required: true
777
+ content:
778
+ application/json:
779
+ schema:
780
+ $ref: "#/components/schemas/CancelBookingInput"
781
+ responses:
782
+ "200":
783
+ description: Cancel result.
784
+ content:
785
+ application/json:
786
+ schema:
787
+ $ref: "#/components/schemas/ApiResponse_BookingActionResult"
788
+ default:
789
+ $ref: "#/components/responses/ApiError"
790
+ /api/v1/bookings/{id}/reschedule:
791
+ parameters:
792
+ - $ref: "#/components/parameters/Id"
793
+ post:
794
+ tags: [Bookings]
795
+ operationId: rescheduleBooking
796
+ summary: Reschedule a booking as the business
797
+ description: >-
798
+ Staff semantics — the reschedule window is bypassed. The old booking is
799
+ cancelled and a new one inserted, so the response carries a new booking
800
+ id and a freshly minted manage token.
801
+ requestBody:
802
+ required: true
803
+ content:
804
+ application/json:
805
+ schema:
806
+ $ref: "#/components/schemas/RescheduleBookingInput"
807
+ responses:
808
+ "200":
809
+ description: Reschedule result.
810
+ content:
811
+ application/json:
812
+ schema:
813
+ $ref: "#/components/schemas/ApiResponse_BookingRescheduleResult"
814
+ default:
815
+ $ref: "#/components/responses/ApiError"
816
+ /api/v1/bookings/{id}/no-show:
817
+ parameters:
818
+ - $ref: "#/components/parameters/Id"
819
+ post:
820
+ tags: [Bookings]
821
+ operationId: markBookingNoShow
822
+ summary: Mark a booking as a no-show
823
+ responses:
824
+ "200":
825
+ description: No-show result.
826
+ content:
827
+ application/json:
828
+ schema:
829
+ $ref: "#/components/schemas/ApiResponse_BookingActionResult"
830
+ default:
831
+ $ref: "#/components/responses/ApiError"
832
+ /api/v1/bookings/manage/{token}:
833
+ parameters:
834
+ - $ref: "#/components/parameters/ManageToken"
835
+ get:
836
+ tags: [Bookings]
837
+ operationId: getManagedBooking
838
+ summary: Get the customer manage summary for a token
839
+ responses:
840
+ "200":
841
+ description: >-
842
+ Manage summary. An unknown token and a token belonging to another
843
+ workspace both answer 404, so this is not an existence oracle.
844
+ content:
845
+ application/json:
846
+ schema:
847
+ $ref: "#/components/schemas/ApiResponse_ManageSummary"
848
+ default:
849
+ $ref: "#/components/responses/ApiError"
850
+ /api/v1/bookings/manage/{token}/cancel:
851
+ parameters:
852
+ - $ref: "#/components/parameters/ManageToken"
853
+ post:
854
+ tags: [Bookings]
855
+ operationId: cancelManagedBooking
856
+ summary: Cancel on the customer's behalf
857
+ description: >-
858
+ Customer semantics — the workspace's cancel window is ENFORCED and the
859
+ cancellation is attributed to the customer.
860
+ requestBody:
861
+ required: true
862
+ content:
863
+ application/json:
864
+ schema:
865
+ $ref: "#/components/schemas/CancelBookingInput"
866
+ responses:
867
+ "200":
868
+ description: Cancel result.
869
+ content:
870
+ application/json:
871
+ schema:
872
+ $ref: "#/components/schemas/ApiResponse_BookingActionResult"
873
+ default:
874
+ $ref: "#/components/responses/ApiError"
875
+ /api/v1/bookings/manage/{token}/reschedule:
876
+ parameters:
877
+ - $ref: "#/components/parameters/ManageToken"
878
+ post:
879
+ tags: [Bookings]
880
+ operationId: rescheduleManagedBooking
881
+ summary: Reschedule on the customer's behalf
882
+ description: >-
883
+ Customer semantics — the reschedule window is ENFORCED. The response
884
+ carries a new booking id and a new manage token; the old token stops
885
+ working.
886
+ requestBody:
887
+ required: true
888
+ content:
889
+ application/json:
890
+ schema:
891
+ $ref: "#/components/schemas/RescheduleBookingInput"
892
+ responses:
893
+ "200":
894
+ description: Reschedule result.
895
+ content:
896
+ application/json:
897
+ schema:
898
+ $ref: "#/components/schemas/ApiResponse_BookingRescheduleResult"
899
+ default:
900
+ $ref: "#/components/responses/ApiError"
537
901
  /api/v1/gdpr/export:
538
902
  post:
539
903
  tags: [GDPR]
@@ -930,6 +1294,34 @@ paths:
930
1294
  $ref: "#/components/schemas/ApiResponse_WebhookTestResult"
931
1295
  default:
932
1296
  $ref: "#/components/responses/ApiError"
1297
+ /api/v1/capability-confirmations:
1298
+ post:
1299
+ tags: [Capabilities]
1300
+ operationId: issueCapabilityConfirmation
1301
+ summary: Issue a capability confirmation token
1302
+ description: >-
1303
+ Mints a short-lived `X-Capability-Confirmation` token for one pending
1304
+ write. Confirmable write routes require BOTH `Idempotency-Key` and
1305
+ `X-Capability-Confirmation` when the credential holds the capability
1306
+ scope directly; API keys with legacy scopes are exempt. The token is
1307
+ bound to the workspace, auth subject, method, path, required scopes and
1308
+ idempotency key, and expires within 15 minutes. `user_approved: true`
1309
+ asserts that a human on the caller's side approved this exact action.
1310
+ requestBody:
1311
+ required: true
1312
+ content:
1313
+ application/json:
1314
+ schema:
1315
+ $ref: "#/components/schemas/IssueCapabilityConfirmationInput"
1316
+ responses:
1317
+ "200":
1318
+ description: Minted confirmation token.
1319
+ content:
1320
+ application/json:
1321
+ schema:
1322
+ $ref: "#/components/schemas/ApiResponse_CapabilityConfirmation"
1323
+ default:
1324
+ $ref: "#/components/responses/ApiError"
933
1325
  /api/v1/channels/connect-links:
934
1326
  post:
935
1327
  tags: [Channels]
@@ -962,8 +1354,20 @@ paths:
962
1354
  tags: [Channels]
963
1355
  operationId: listChannelConnectLinks
964
1356
  summary: List connect links
965
- description: Link tokens are never returned.
1357
+ description: >-
1358
+ Link tokens are never returned. Newest first, cursor-paginated. The
1359
+ `channel_type` / `status` filters are applied within each page, so a
1360
+ page may hold fewer than `limit` items while `pagination.has_more` is
1361
+ still true — page off `has_more`, not the item count.
966
1362
  parameters:
1363
+ - name: limit
1364
+ in: query
1365
+ schema:
1366
+ type: integer
1367
+ minimum: 1
1368
+ maximum: 100
1369
+ description: Page size (default 50, capped at 100).
1370
+ - $ref: "#/components/parameters/Cursor"
967
1371
  - name: channel_type
968
1372
  in: query
969
1373
  schema:
@@ -974,11 +1378,11 @@ paths:
974
1378
  $ref: "#/components/schemas/ConnectLinkStatus"
975
1379
  responses:
976
1380
  "200":
977
- description: The workspace's connect links.
1381
+ description: Connect links page.
978
1382
  content:
979
1383
  application/json:
980
1384
  schema:
981
- $ref: "#/components/schemas/ApiResponse_ConnectLinkArray"
1385
+ $ref: "#/components/schemas/PaginatedResponse_ConnectLink"
982
1386
  default:
983
1387
  $ref: "#/components/responses/ApiError"
984
1388
  /api/v1/channels/connect-links/{id}:
@@ -1005,13 +1409,28 @@ paths:
1005
1409
  tags: [Channels]
1006
1410
  operationId: listChannelConnections
1007
1411
  summary: List channel connections
1412
+ description: >-
1413
+ The workspace's channel connections in a generic, channel-agnostic
1414
+ shape. Newest first, cursor-paginated. Rows that are not projectable
1415
+ as connections are dropped within the page, so a page may hold fewer
1416
+ than `limit` items while `pagination.has_more` is still true — page
1417
+ off `has_more`, not the item count.
1418
+ parameters:
1419
+ - name: limit
1420
+ in: query
1421
+ schema:
1422
+ type: integer
1423
+ minimum: 1
1424
+ maximum: 100
1425
+ description: Page size (default 50, capped at 100).
1426
+ - $ref: "#/components/parameters/Cursor"
1008
1427
  responses:
1009
1428
  "200":
1010
- description: The workspace's channel connections (generic shape).
1429
+ description: Channel connections page.
1011
1430
  content:
1012
1431
  application/json:
1013
1432
  schema:
1014
- $ref: "#/components/schemas/ApiResponse_ChannelConnectionArray"
1433
+ $ref: "#/components/schemas/PaginatedResponse_ChannelConnection"
1015
1434
  default:
1016
1435
  $ref: "#/components/responses/ApiError"
1017
1436
  /api/v1/channels/connections/{id}:
@@ -1035,28 +1454,97 @@ paths:
1035
1454
  $ref: "#/components/schemas/ApiResponse_ChannelConnectionDisconnectResult"
1036
1455
  default:
1037
1456
  $ref: "#/components/responses/ApiError"
1038
- components:
1039
- securitySchemes:
1040
- bearerAuth:
1041
- type: http
1042
- scheme: bearer
1043
- parameters:
1044
- Id:
1045
- name: id
1046
- in: path
1047
- required: true
1048
- schema:
1049
- type: string
1050
- Slug:
1051
- name: slug
1052
- in: path
1053
- required: true
1054
- schema:
1055
- type: string
1056
- Cursor:
1057
- name: cursor
1058
- in: query
1059
- schema:
1457
+ /api/v1/scan:
1458
+ post:
1459
+ tags: [Scan]
1460
+ operationId: createScan
1461
+ summary: Queue a company/site scan
1462
+ description: >-
1463
+ Queues an asynchronous scan. Provide exactly one of `url`, `orgnr`, or
1464
+ `name`; poll the returned id via `GET /api/v1/scan/{id}`.
1465
+ requestBody:
1466
+ required: true
1467
+ content:
1468
+ application/json:
1469
+ schema:
1470
+ $ref: "#/components/schemas/ScanCreateInput"
1471
+ responses:
1472
+ "202":
1473
+ description: Scan job queued.
1474
+ content:
1475
+ application/json:
1476
+ schema:
1477
+ $ref: "#/components/schemas/ApiResponse_ScanCreateResult"
1478
+ default:
1479
+ $ref: "#/components/responses/ApiError"
1480
+ /api/v1/scan/companies:
1481
+ get:
1482
+ tags: [Scan]
1483
+ operationId: searchScanCompanies
1484
+ summary: Search the Norwegian company registry
1485
+ parameters:
1486
+ - name: q
1487
+ in: query
1488
+ required: true
1489
+ schema:
1490
+ type: string
1491
+ minLength: 2
1492
+ responses:
1493
+ "200":
1494
+ description: Registry matches (top 5, relevance-ranked).
1495
+ content:
1496
+ application/json:
1497
+ schema:
1498
+ $ref: "#/components/schemas/ApiResponse_ScanCompanyArray"
1499
+ default:
1500
+ $ref: "#/components/responses/ApiError"
1501
+ /api/v1/scan/{id}:
1502
+ parameters:
1503
+ - $ref: "#/components/parameters/Id"
1504
+ get:
1505
+ tags: [Scan]
1506
+ operationId: getScan
1507
+ summary: Get a scan job
1508
+ responses:
1509
+ "200":
1510
+ description: Scan job status and, once done, the findings payload.
1511
+ content:
1512
+ application/json:
1513
+ schema:
1514
+ $ref: "#/components/schemas/ApiResponse_ScanJob"
1515
+ default:
1516
+ $ref: "#/components/responses/ApiError"
1517
+ components:
1518
+ securitySchemes:
1519
+ bearerAuth:
1520
+ type: http
1521
+ scheme: bearer
1522
+ parameters:
1523
+ Id:
1524
+ name: id
1525
+ in: path
1526
+ required: true
1527
+ schema:
1528
+ type: string
1529
+ Slug:
1530
+ name: slug
1531
+ in: path
1532
+ required: true
1533
+ schema:
1534
+ type: string
1535
+ ManageToken:
1536
+ name: token
1537
+ in: path
1538
+ required: true
1539
+ description: >-
1540
+ The show-once manage token handed out when the booking was created.
1541
+ Possession of it authorizes the customer's own cancel or reschedule.
1542
+ schema:
1543
+ type: string
1544
+ Cursor:
1545
+ name: cursor
1546
+ in: query
1547
+ schema:
1060
1548
  type: string
1061
1549
  Limit:
1062
1550
  name: limit
@@ -1927,6 +2415,496 @@ components:
1927
2415
  format: date
1928
2416
  notes:
1929
2417
  type: string
2418
+ BookingTimestampInput:
2419
+ description: >-
2420
+ A timestamp on the way in — Unix milliseconds, or an ISO 8601
2421
+ date-time string. Responses always render timestamps as ISO 8601.
2422
+ type: [integer, string]
2423
+ BookingStatus:
2424
+ type: string
2425
+ enum: [pending, confirmed, completed, cancelled, no_show]
2426
+ BookingCancelledBy:
2427
+ description: >-
2428
+ Who cancelled. `staff` for the id-addressed cancel, `customer` for the
2429
+ manage-token cancel, `system` for an automated one.
2430
+ type: string
2431
+ enum: [customer, staff, system]
2432
+ BookingPaymentStatus:
2433
+ type: string
2434
+ enum: [none, reserved, captured, refunded]
2435
+ BookingCreatedVia:
2436
+ type: string
2437
+ enum: [web, dashboard, walk_in, api]
2438
+ BookingResourceType:
2439
+ type: string
2440
+ enum: [staff, room, equipment]
2441
+ Booking:
2442
+ type: object
2443
+ required:
2444
+ - id
2445
+ - contact_id
2446
+ - service_id
2447
+ - resource_id
2448
+ - start_ts
2449
+ - end_ts
2450
+ - booked_for_name
2451
+ - booked_for_birth_year
2452
+ - party_sequence_id
2453
+ - status
2454
+ - cancelled_by
2455
+ - cancel_reason
2456
+ - rescheduled_from_id
2457
+ - payment_status
2458
+ - amount_ore
2459
+ - notes
2460
+ - internal_notes
2461
+ - created_via
2462
+ - created_at
2463
+ - updated_at
2464
+ properties:
2465
+ id:
2466
+ type: string
2467
+ contact_id:
2468
+ type: [string, "null"]
2469
+ service_id:
2470
+ type: [string, "null"]
2471
+ resource_id:
2472
+ type: [string, "null"]
2473
+ start_ts:
2474
+ type: [string, "null"]
2475
+ format: date-time
2476
+ end_ts:
2477
+ type: [string, "null"]
2478
+ format: date-time
2479
+ booked_for_name:
2480
+ type: [string, "null"]
2481
+ booked_for_birth_year:
2482
+ description: A birth year, not a birthdate — the age bracket is all that is stored.
2483
+ type: [integer, "null"]
2484
+ party_sequence_id:
2485
+ description: Shared by every booking created in the same party request.
2486
+ type: [string, "null"]
2487
+ status:
2488
+ $ref: "#/components/schemas/BookingStatus"
2489
+ cancelled_by:
2490
+ oneOf:
2491
+ - $ref: "#/components/schemas/BookingCancelledBy"
2492
+ - type: "null"
2493
+ cancel_reason:
2494
+ type: [string, "null"]
2495
+ rescheduled_from_id:
2496
+ description: On a booking created by a reschedule, the booking it replaced.
2497
+ type: [string, "null"]
2498
+ payment_status:
2499
+ $ref: "#/components/schemas/BookingPaymentStatus"
2500
+ amount_ore:
2501
+ description: Price in integer øre. Never a float and never kroner.
2502
+ type: [integer, "null"]
2503
+ notes:
2504
+ description: Customer-visible note.
2505
+ type: [string, "null"]
2506
+ internal_notes:
2507
+ description: Staff-only note; never shown to the customer.
2508
+ type: [string, "null"]
2509
+ created_via:
2510
+ oneOf:
2511
+ - $ref: "#/components/schemas/BookingCreatedVia"
2512
+ - type: "null"
2513
+ created_at:
2514
+ type: [string, "null"]
2515
+ format: date-time
2516
+ updated_at:
2517
+ type: [string, "null"]
2518
+ format: date-time
2519
+ BookingService:
2520
+ type: object
2521
+ required:
2522
+ - id
2523
+ - name
2524
+ - description
2525
+ - category
2526
+ - duration_minutes
2527
+ - buffer_before_minutes
2528
+ - buffer_after_minutes
2529
+ - price_ore
2530
+ - weekend_surcharge_pct
2531
+ - resource_requirements
2532
+ - bookable_online
2533
+ - max_per_booking
2534
+ - color
2535
+ - sort_order
2536
+ - active
2537
+ - created_at
2538
+ - updated_at
2539
+ properties:
2540
+ id:
2541
+ type: string
2542
+ name:
2543
+ type: [string, "null"]
2544
+ description:
2545
+ type: [string, "null"]
2546
+ category:
2547
+ type: [string, "null"]
2548
+ duration_minutes:
2549
+ type: [integer, "null"]
2550
+ buffer_before_minutes:
2551
+ type: [integer, "null"]
2552
+ buffer_after_minutes:
2553
+ type: [integer, "null"]
2554
+ price_ore:
2555
+ description: Price in integer øre.
2556
+ type: [integer, "null"]
2557
+ weekend_surcharge_pct:
2558
+ type: [number, "null"]
2559
+ resource_requirements:
2560
+ description: Resource types this service needs, e.g. `["staff"]`.
2561
+ type: array
2562
+ items:
2563
+ type: string
2564
+ bookable_online:
2565
+ type: boolean
2566
+ max_per_booking:
2567
+ type: [integer, "null"]
2568
+ color:
2569
+ type: [string, "null"]
2570
+ sort_order:
2571
+ type: [integer, "null"]
2572
+ active:
2573
+ type: boolean
2574
+ created_at:
2575
+ type: [string, "null"]
2576
+ format: date-time
2577
+ updated_at:
2578
+ type: [string, "null"]
2579
+ format: date-time
2580
+ BookingResource:
2581
+ type: object
2582
+ required:
2583
+ - id
2584
+ - type
2585
+ - name
2586
+ - photo_url
2587
+ - bio
2588
+ - service_ids
2589
+ - capacity
2590
+ - sort_order
2591
+ - active
2592
+ - created_at
2593
+ - updated_at
2594
+ properties:
2595
+ id:
2596
+ type: string
2597
+ type:
2598
+ oneOf:
2599
+ - $ref: "#/components/schemas/BookingResourceType"
2600
+ - type: "null"
2601
+ name:
2602
+ type: [string, "null"]
2603
+ photo_url:
2604
+ type: [string, "null"]
2605
+ format: uri
2606
+ bio:
2607
+ type: [string, "null"]
2608
+ service_ids:
2609
+ description: Services this resource can perform.
2610
+ type: array
2611
+ items:
2612
+ type: string
2613
+ capacity:
2614
+ type: [integer, "null"]
2615
+ sort_order:
2616
+ type: [integer, "null"]
2617
+ active:
2618
+ type: boolean
2619
+ created_at:
2620
+ type: [string, "null"]
2621
+ format: date-time
2622
+ updated_at:
2623
+ type: [string, "null"]
2624
+ format: date-time
2625
+ BookingSlot:
2626
+ type: object
2627
+ required: [start_ts, end_ts, resource_id]
2628
+ properties:
2629
+ start_ts:
2630
+ type: [string, "null"]
2631
+ format: date-time
2632
+ end_ts:
2633
+ type: [string, "null"]
2634
+ format: date-time
2635
+ resource_id:
2636
+ type: [string, "null"]
2637
+ BookingScheduleDay:
2638
+ description: One date a service can be booked on. `date` is the workspace's own calendar date, not a timestamp.
2639
+ type: object
2640
+ required: [date, opens_ts, closes_ts, last_start_ts]
2641
+ properties:
2642
+ date:
2643
+ type: [string, "null"]
2644
+ format: date
2645
+ opens_ts:
2646
+ type: [string, "null"]
2647
+ format: date-time
2648
+ closes_ts:
2649
+ type: [string, "null"]
2650
+ format: date-time
2651
+ last_start_ts:
2652
+ description: Last start this service could occupy on the date; `null` when the date is shut outright.
2653
+ type: [string, "null"]
2654
+ format: date-time
2655
+ BookingContactInput:
2656
+ description: The person the booking is made under. Phone is the CRM dedupe key.
2657
+ type: object
2658
+ required: [phone]
2659
+ properties:
2660
+ phone:
2661
+ type: string
2662
+ maxLength: 40
2663
+ email:
2664
+ type: string
2665
+ maxLength: 320
2666
+ name:
2667
+ type: string
2668
+ maxLength: 200
2669
+ CreateBookingItemInput:
2670
+ description: One line of a party — a single service on a single slot.
2671
+ type: object
2672
+ required: [service_id, start_ts]
2673
+ properties:
2674
+ service_id:
2675
+ type: string
2676
+ resource_id:
2677
+ description: Omit to let the engine pick a free resource.
2678
+ type: string
2679
+ start_ts:
2680
+ $ref: "#/components/schemas/BookingTimestampInput"
2681
+ booked_for_name:
2682
+ type: string
2683
+ maxLength: 200
2684
+ booked_for_birth_year:
2685
+ type: integer
2686
+ minimum: 1900
2687
+ maximum: 2200
2688
+ CreateBookingInput:
2689
+ type: object
2690
+ required: [items, contact]
2691
+ properties:
2692
+ items:
2693
+ description: >-
2694
+ A PARTY — one request books a whole family in one all-or-nothing
2695
+ transaction.
2696
+ type: array
2697
+ minItems: 1
2698
+ maxItems: 50
2699
+ items:
2700
+ $ref: "#/components/schemas/CreateBookingItemInput"
2701
+ contact:
2702
+ $ref: "#/components/schemas/BookingContactInput"
2703
+ notes:
2704
+ type: string
2705
+ maxLength: 5000
2706
+ created_via:
2707
+ description: >-
2708
+ Where the booking came from. Defaults to `api`. A workspace's OWN
2709
+ website should send `web`, so its bookings can be told apart from
2710
+ integrations. `dashboard` and `walk_in` are staff-only and are
2711
+ rejected with 400 — a bearer token proves which workspace is calling,
2712
+ not that a member typed the booking in.
2713
+ type: string
2714
+ enum: [web, api]
2715
+ CreatedBooking:
2716
+ type: object
2717
+ required: [id]
2718
+ properties:
2719
+ id:
2720
+ type: string
2721
+ manage_token:
2722
+ description: >-
2723
+ Show-once secret for the customer's manage link. Only its hash is
2724
+ stored, and an idempotent replay omits this field entirely.
2725
+ type: string
2726
+ BookingCreateResult:
2727
+ type: object
2728
+ required: [bookings, contact_id]
2729
+ properties:
2730
+ bookings:
2731
+ description: One entry per created booking, in request order.
2732
+ type: array
2733
+ items:
2734
+ $ref: "#/components/schemas/CreatedBooking"
2735
+ contact_id:
2736
+ type: string
2737
+ BookingActionResult:
2738
+ type: object
2739
+ required: [success]
2740
+ properties:
2741
+ success:
2742
+ type: boolean
2743
+ const: true
2744
+ BookingRescheduleResult:
2745
+ type: object
2746
+ required: [success, booking_id]
2747
+ properties:
2748
+ success:
2749
+ type: boolean
2750
+ const: true
2751
+ booking_id:
2752
+ description: >-
2753
+ The NEW booking's id — a reschedule cancels the old row and inserts
2754
+ a new one.
2755
+ type: string
2756
+ manage_token:
2757
+ description: >-
2758
+ Freshly minted manage token for the new booking; omitted on an
2759
+ idempotent replay.
2760
+ type: string
2761
+ ManageSummary:
2762
+ description: >-
2763
+ What the holder of a manage token may see and do. `can_cancel` and
2764
+ `can_reschedule` already apply the workspace's policy windows.
2765
+ type: object
2766
+ required:
2767
+ - booking_id
2768
+ - contact_id
2769
+ - status
2770
+ - cancelled_by
2771
+ - cancel_reason
2772
+ - rescheduled_from_id
2773
+ - start_ts
2774
+ - end_ts
2775
+ - service_id
2776
+ - service_name
2777
+ - resource_id
2778
+ - resource_name
2779
+ - booked_for_name
2780
+ - party_sequence_id
2781
+ - amount_ore
2782
+ - payment_status
2783
+ - time_zone
2784
+ - cancel_window_hours
2785
+ - reschedule_window_hours
2786
+ - can_cancel
2787
+ - can_reschedule
2788
+ properties:
2789
+ booking_id:
2790
+ type: string
2791
+ contact_id:
2792
+ type: [string, "null"]
2793
+ status:
2794
+ oneOf:
2795
+ - $ref: "#/components/schemas/BookingStatus"
2796
+ - type: "null"
2797
+ cancelled_by:
2798
+ oneOf:
2799
+ - $ref: "#/components/schemas/BookingCancelledBy"
2800
+ - type: "null"
2801
+ cancel_reason:
2802
+ type: [string, "null"]
2803
+ rescheduled_from_id:
2804
+ type: [string, "null"]
2805
+ start_ts:
2806
+ type: [string, "null"]
2807
+ format: date-time
2808
+ end_ts:
2809
+ type: [string, "null"]
2810
+ format: date-time
2811
+ service_id:
2812
+ type: [string, "null"]
2813
+ service_name:
2814
+ type: [string, "null"]
2815
+ resource_id:
2816
+ type: [string, "null"]
2817
+ resource_name:
2818
+ type: [string, "null"]
2819
+ booked_for_name:
2820
+ type: [string, "null"]
2821
+ party_sequence_id:
2822
+ type: [string, "null"]
2823
+ amount_ore:
2824
+ description: Price in integer øre.
2825
+ type: [integer, "null"]
2826
+ payment_status:
2827
+ oneOf:
2828
+ - $ref: "#/components/schemas/BookingPaymentStatus"
2829
+ - type: "null"
2830
+ time_zone:
2831
+ description: IANA zone the booking's local times should be rendered in.
2832
+ type: [string, "null"]
2833
+ cancel_window_hours:
2834
+ type: [number, "null"]
2835
+ reschedule_window_hours:
2836
+ type: [number, "null"]
2837
+ can_cancel:
2838
+ type: boolean
2839
+ can_reschedule:
2840
+ type: boolean
2841
+ UpdateBookingInput:
2842
+ description: >-
2843
+ At least one of `notes` or `internal_notes` is required — the API
2844
+ rejects a body carrying neither with a 400. `""` is a meaningful value
2845
+ that clears the field, so the constraint is on presence.
2846
+ # Spelled out as two fully-typed branches rather than the terser
2847
+ # `anyOf: [{required: [notes]}, {required: [internal_notes]}]`, because a
2848
+ # branch carrying only `required` generates as `unknown` — and `T |
2849
+ # unknown` collapses to `unknown`, which accepts everything and is worse
2850
+ # than the unconstrained object. Each branch therefore repeats the
2851
+ # properties so openapi-typescript emits a real discriminating union.
2852
+ #
2853
+ # `minProperties: 1` is deliberately absent: `anyOf` on two named
2854
+ # properties already implies it and is strictly stronger (it also rejects
2855
+ # `{ unrelated_key: 1 }`), so keeping both would be two statements of one
2856
+ # invariant to drift apart.
2857
+ anyOf:
2858
+ - type: object
2859
+ required: [notes]
2860
+ properties:
2861
+ notes:
2862
+ description: Customer-visible note.
2863
+ type: string
2864
+ maxLength: 5000
2865
+ internal_notes:
2866
+ description: Staff-only note.
2867
+ type: string
2868
+ maxLength: 5000
2869
+ - type: object
2870
+ required: [internal_notes]
2871
+ properties:
2872
+ notes:
2873
+ description: Customer-visible note.
2874
+ type: string
2875
+ maxLength: 5000
2876
+ internal_notes:
2877
+ description: Staff-only note.
2878
+ type: string
2879
+ maxLength: 5000
2880
+ CancelBookingInput:
2881
+ type: object
2882
+ properties:
2883
+ reason:
2884
+ type: string
2885
+ maxLength: 500
2886
+ RescheduleBookingInput:
2887
+ type: object
2888
+ required: [new_start_ts]
2889
+ properties:
2890
+ new_start_ts:
2891
+ $ref: "#/components/schemas/BookingTimestampInput"
2892
+ new_resource_id:
2893
+ type: string
2894
+ BookingsPagination:
2895
+ description: >-
2896
+ Pagination for a bookings page. `truncated` is the extra statement:
2897
+ the underlying read is capped, and when the cap binds there are
2898
+ matching bookings no cursor from this call reaches — narrow the window.
2899
+ type: object
2900
+ required: [has_more, next_cursor, truncated]
2901
+ properties:
2902
+ has_more:
2903
+ type: boolean
2904
+ next_cursor:
2905
+ type: [string, "null"]
2906
+ truncated:
2907
+ type: boolean
1930
2908
  GdprExport:
1931
2909
  type: object
1932
2910
  required: [id, request_type, status, submitted_at, completed_at]
@@ -2154,6 +3132,8 @@ components:
2154
3132
  - author_user_id
2155
3133
  - author_name
2156
3134
  - body
3135
+ - delivery_status
3136
+ - delivery_error
2157
3137
  - created_at
2158
3138
  properties:
2159
3139
  id:
@@ -2170,9 +3150,26 @@ components:
2170
3150
  type: [string, "null"]
2171
3151
  body:
2172
3152
  type: string
3153
+ delivery_status:
3154
+ oneOf:
3155
+ - $ref: "#/components/schemas/HelpdeskMessageDeliveryStatus"
3156
+ - type: "null"
3157
+ description: >-
3158
+ Outbound delivery state, or `null` for inbound messages and
3159
+ internal notes. A `201` from `POST /api/v1/helpdesk/replies` means
3160
+ the reply was accepted, NOT delivered — the channel hand-off is
3161
+ asynchronous, so poll this field (or subscribe to
3162
+ `helpdesk.message_delivery_updated`) to learn the outcome.
3163
+ delivery_error:
3164
+ type: [string, "null"]
3165
+ description: >-
3166
+ Last send error for a `failed` outbound message, otherwise `null`.
2173
3167
  created_at:
2174
3168
  type: integer
2175
3169
  description: Unix timestamp in milliseconds.
3170
+ HelpdeskMessageDeliveryStatus:
3171
+ type: string
3172
+ enum: [pending, sent, delivered, failed]
2176
3173
  UpdateHelpdeskConversationInput:
2177
3174
  type: object
2178
3175
  minProperties: 1
@@ -2363,9 +3360,22 @@ components:
2363
3360
  const: deleted
2364
3361
  WebhookDelivery:
2365
3362
  type: object
3363
+ description: >-
3364
+ A delivery attempt record. `id` is the same value sent as the
3365
+ `X-Medal-Delivery-Id` and `Idempotency-Key` headers on the outbound
3366
+ request. Deliveries never carry payload bodies (payloads can contain
3367
+ customer PII). The correlation fields are derived from the stored event
3368
+ and fail closed to `null` when no canonical event exists — e.g.
3369
+ `test.ping` deliveries or events that have aged out of retention.
2366
3370
  required:
2367
3371
  - id
2368
3372
  - event_type
3373
+ - resource_id
3374
+ - conversation_id
3375
+ - message_id
3376
+ - connection_ref
3377
+ - channel
3378
+ - channel_connection_id
2369
3379
  - status
2370
3380
  - attempt_count
2371
3381
  - next_attempt_at
@@ -2379,6 +3389,19 @@ components:
2379
3389
  type: string
2380
3390
  event_type:
2381
3391
  type: string
3392
+ resource_id:
3393
+ type: [string, "null"]
3394
+ description: Primary subject id of the announced event, or `null`.
3395
+ conversation_id:
3396
+ type: [string, "null"]
3397
+ message_id:
3398
+ type: [string, "null"]
3399
+ connection_ref:
3400
+ type: [string, "null"]
3401
+ channel:
3402
+ type: [string, "null"]
3403
+ channel_connection_id:
3404
+ type: [string, "null"]
2382
3405
  status:
2383
3406
  type: string
2384
3407
  enum: [pending, delivered, dead_letter]
@@ -2574,12 +3597,36 @@ components:
2574
3597
  $ref: "#/components/schemas/Envelope_DealUpdateResult"
2575
3598
  ApiResponse_DealRemoveResult:
2576
3599
  $ref: "#/components/schemas/Envelope_DealRemoveResult"
3600
+ ApiResponse_Booking:
3601
+ $ref: "#/components/schemas/Envelope_Booking"
3602
+ ApiResponse_BookingServiceArray:
3603
+ $ref: "#/components/schemas/Envelope_BookingServiceArray"
3604
+ ApiResponse_BookingResourceArray:
3605
+ $ref: "#/components/schemas/Envelope_BookingResourceArray"
3606
+ ApiResponse_BookingSlotArray:
3607
+ $ref: "#/components/schemas/Envelope_BookingSlotArray"
3608
+ ApiResponse_BookingScheduleDayArray:
3609
+ $ref: "#/components/schemas/Envelope_BookingScheduleDayArray"
3610
+ ApiResponse_BookingCreateResult:
3611
+ $ref: "#/components/schemas/Envelope_BookingCreateResult"
3612
+ ApiResponse_BookingActionResult:
3613
+ $ref: "#/components/schemas/Envelope_BookingActionResult"
3614
+ ApiResponse_BookingRescheduleResult:
3615
+ $ref: "#/components/schemas/Envelope_BookingRescheduleResult"
3616
+ ApiResponse_ManageSummary:
3617
+ $ref: "#/components/schemas/Envelope_ManageSummary"
2577
3618
  ApiResponse_GdprExportRequest:
2578
3619
  $ref: "#/components/schemas/Envelope_GdprExportRequest"
2579
3620
  ApiResponse_GdprExportArray:
2580
3621
  $ref: "#/components/schemas/Envelope_GdprExportArray"
2581
3622
  ApiResponse_GdprExport:
2582
3623
  $ref: "#/components/schemas/Envelope_GdprExport"
3624
+ ApiResponse_ScanCreateResult:
3625
+ $ref: "#/components/schemas/Envelope_ScanCreateResult"
3626
+ ApiResponse_ScanCompanyArray:
3627
+ $ref: "#/components/schemas/Envelope_ScanCompanyArray"
3628
+ ApiResponse_ScanJob:
3629
+ $ref: "#/components/schemas/Envelope_ScanJob"
2583
3630
  ApiResponse_ConsentResult:
2584
3631
  $ref: "#/components/schemas/Envelope_ConsentResult"
2585
3632
  ApiResponse_ConsentRecordArray:
@@ -2604,6 +3651,11 @@ components:
2604
3651
  $ref: "#/components/schemas/Envelope_WebhookTestResult"
2605
3652
  ApiResponse_ConnectLinkCreateResult:
2606
3653
  $ref: "#/components/schemas/Envelope_ConnectLinkCreateResult"
3654
+ # Deprecated: the channels listings are cursor-paginated and now respond
3655
+ # with PaginatedResponse_ConnectLink / PaginatedResponse_ChannelConnection.
3656
+ # These unpaginated aliases are retained (unreferenced by any operation)
3657
+ # so consumers importing the generated contract via
3658
+ # `@medalsocial/sdk/openapi-types` or `OpenApiComponents` keep compiling.
2607
3659
  ApiResponse_ConnectLinkArray:
2608
3660
  $ref: "#/components/schemas/Envelope_ConnectLinkArray"
2609
3661
  ApiResponse_ConnectLinkRevokeResult:
@@ -2652,6 +3704,16 @@ components:
2652
3704
  $ref: "#/components/schemas/Deal"
2653
3705
  pagination:
2654
3706
  $ref: "#/components/schemas/Pagination"
3707
+ PaginatedResponse_Booking:
3708
+ type: object
3709
+ required: [data, pagination]
3710
+ properties:
3711
+ data:
3712
+ type: array
3713
+ items:
3714
+ $ref: "#/components/schemas/Booking"
3715
+ pagination:
3716
+ $ref: "#/components/schemas/BookingsPagination"
2655
3717
  PaginatedResponse_HelpdeskConversation:
2656
3718
  type: object
2657
3719
  required: [data, pagination]
@@ -2672,6 +3734,26 @@ components:
2672
3734
  $ref: "#/components/schemas/HelpdeskMessage"
2673
3735
  pagination:
2674
3736
  $ref: "#/components/schemas/Pagination"
3737
+ PaginatedResponse_ConnectLink:
3738
+ type: object
3739
+ required: [data, pagination]
3740
+ properties:
3741
+ data:
3742
+ type: array
3743
+ items:
3744
+ $ref: "#/components/schemas/ConnectLink"
3745
+ pagination:
3746
+ $ref: "#/components/schemas/Pagination"
3747
+ PaginatedResponse_ChannelConnection:
3748
+ type: object
3749
+ required: [data, pagination]
3750
+ properties:
3751
+ data:
3752
+ type: array
3753
+ items:
3754
+ $ref: "#/components/schemas/ChannelConnection"
3755
+ pagination:
3756
+ $ref: "#/components/schemas/Pagination"
2675
3757
  Envelope_PostCreateResult:
2676
3758
  type: object
2677
3759
  required: [data]
@@ -2802,6 +3884,193 @@ components:
2802
3884
  properties:
2803
3885
  data:
2804
3886
  $ref: "#/components/schemas/DealRemoveResult"
3887
+ Envelope_Booking:
3888
+ type: object
3889
+ required: [data]
3890
+ properties:
3891
+ data:
3892
+ $ref: "#/components/schemas/Booking"
3893
+ Envelope_BookingServiceArray:
3894
+ type: object
3895
+ required: [data]
3896
+ properties:
3897
+ data:
3898
+ type: array
3899
+ items:
3900
+ $ref: "#/components/schemas/BookingService"
3901
+ Envelope_BookingResourceArray:
3902
+ type: object
3903
+ required: [data]
3904
+ properties:
3905
+ data:
3906
+ type: array
3907
+ items:
3908
+ $ref: "#/components/schemas/BookingResource"
3909
+ Envelope_BookingSlotArray:
3910
+ type: object
3911
+ required: [data]
3912
+ properties:
3913
+ data:
3914
+ type: array
3915
+ items:
3916
+ $ref: "#/components/schemas/BookingSlot"
3917
+ Envelope_BookingScheduleDayArray:
3918
+ type: object
3919
+ required: [data]
3920
+ properties:
3921
+ data:
3922
+ type: array
3923
+ items:
3924
+ $ref: "#/components/schemas/BookingScheduleDay"
3925
+ Envelope_BookingCreateResult:
3926
+ type: object
3927
+ required: [data]
3928
+ properties:
3929
+ data:
3930
+ $ref: "#/components/schemas/BookingCreateResult"
3931
+ Envelope_BookingActionResult:
3932
+ type: object
3933
+ required: [data]
3934
+ properties:
3935
+ data:
3936
+ $ref: "#/components/schemas/BookingActionResult"
3937
+ Envelope_BookingRescheduleResult:
3938
+ type: object
3939
+ required: [data]
3940
+ properties:
3941
+ data:
3942
+ $ref: "#/components/schemas/BookingRescheduleResult"
3943
+ Envelope_ManageSummary:
3944
+ type: object
3945
+ required: [data]
3946
+ properties:
3947
+ data:
3948
+ $ref: "#/components/schemas/ManageSummary"
3949
+ ScanCreateInput:
3950
+ type: object
3951
+ description: Provide exactly one of `url`, `orgnr`, or `name`.
3952
+ oneOf:
3953
+ - required: [url]
3954
+ not:
3955
+ anyOf: [{ required: [orgnr] }, { required: [name] }]
3956
+ - required: [orgnr]
3957
+ not:
3958
+ anyOf: [{ required: [url] }, { required: [name] }]
3959
+ - required: [name]
3960
+ not:
3961
+ anyOf: [{ required: [url] }, { required: [orgnr] }]
3962
+ properties:
3963
+ url:
3964
+ type: string
3965
+ minLength: 4
3966
+ maxLength: 500
3967
+ orgnr:
3968
+ type: string
3969
+ pattern: "^\\d{9}$"
3970
+ name:
3971
+ type: string
3972
+ minLength: 2
3973
+ maxLength: 120
3974
+ ScanCreateResult:
3975
+ type: object
3976
+ required: [id, status]
3977
+ properties:
3978
+ id:
3979
+ type: string
3980
+ status:
3981
+ type: string
3982
+ message:
3983
+ type: string
3984
+ ScanCompany:
3985
+ type: object
3986
+ required: [orgnr, name, org_form, industry, city, website]
3987
+ properties:
3988
+ orgnr:
3989
+ type: string
3990
+ name:
3991
+ type: string
3992
+ org_form:
3993
+ type: [string, "null"]
3994
+ industry:
3995
+ type: [string, "null"]
3996
+ city:
3997
+ type: [string, "null"]
3998
+ website:
3999
+ type: [string, "null"]
4000
+ ScanJob:
4001
+ type: object
4002
+ required: [id, status, input, resolved, result, error, created_at, finished_at]
4003
+ properties:
4004
+ id:
4005
+ type: string
4006
+ status:
4007
+ type: string
4008
+ description: pending | running | done | failed
4009
+ input:
4010
+ $ref: "#/components/schemas/ScanCreateInput"
4011
+ resolved:
4012
+ type: [object, "null"]
4013
+ properties:
4014
+ orgnr:
4015
+ type: string
4016
+ companyName:
4017
+ type: string
4018
+ websiteUrl:
4019
+ type: string
4020
+ result:
4021
+ type: [object, "null"]
4022
+ description: >-
4023
+ Versioned findings payload (see the SDK `ScanResultPayload` type);
4024
+ additive per `version`. The stable core is documented below;
4025
+ further sections (registry, signals, pagespeed, seo, ai, gdpr,
4026
+ mailAuth, httpsOk) evolve additively.
4027
+ required: [version, nettskaar, subScores]
4028
+ properties:
4029
+ version:
4030
+ type: integer
4031
+ nettskaar:
4032
+ type: [integer, "null"]
4033
+ description: Weighted composite score (0-100); null when unmeasurable.
4034
+ subScores:
4035
+ type: object
4036
+ description: Per-axis 0-100 scores; null axes were unmeasurable.
4037
+ required: [fart, google, ai, trygghet, omdomme]
4038
+ properties:
4039
+ fart: { type: [integer, "null"] }
4040
+ google: { type: [integer, "null"] }
4041
+ ai: { type: [integer, "null"] }
4042
+ trygghet: { type: [integer, "null"] }
4043
+ omdomme: { type: [integer, "null"] }
4044
+ additionalProperties: true
4045
+ error:
4046
+ type: [string, "null"]
4047
+ description: Public-safe failure code (company_not_found, no_website, …).
4048
+ created_at:
4049
+ type: [string, "null"]
4050
+ format: date-time
4051
+ finished_at:
4052
+ type: [string, "null"]
4053
+ format: date-time
4054
+ Envelope_ScanCreateResult:
4055
+ type: object
4056
+ required: [data]
4057
+ properties:
4058
+ data:
4059
+ $ref: "#/components/schemas/ScanCreateResult"
4060
+ Envelope_ScanCompanyArray:
4061
+ type: object
4062
+ required: [data]
4063
+ properties:
4064
+ data:
4065
+ type: array
4066
+ items:
4067
+ $ref: "#/components/schemas/ScanCompany"
4068
+ Envelope_ScanJob:
4069
+ type: object
4070
+ required: [data]
4071
+ properties:
4072
+ data:
4073
+ $ref: "#/components/schemas/ScanJob"
2805
4074
  Envelope_GdprExportRequest:
2806
4075
  type: object
2807
4076
  required: [data]
@@ -2882,6 +4151,94 @@ components:
2882
4151
  properties:
2883
4152
  data:
2884
4153
  $ref: "#/components/schemas/WebhookDeleteResult"
4154
+ IssueCapabilityConfirmationInput:
4155
+ type: object
4156
+ required: [capability_id, preview_summary, user_approved]
4157
+ properties:
4158
+ capability_id:
4159
+ type: string
4160
+ minLength: 1
4161
+ maxLength: 160
4162
+ description: Confirmable capability to mint a token for.
4163
+ api_path:
4164
+ type: string
4165
+ minLength: 1
4166
+ maxLength: 512
4167
+ description: >-
4168
+ Concrete `/api/v1/...` path to bind the token to. Optional when the
4169
+ capability has exactly one API target; required when it has several.
4170
+ path_params:
4171
+ type: object
4172
+ additionalProperties:
4173
+ type: [string, number, boolean]
4174
+ description: Values for the capability path template's parameters.
4175
+ idempotency_key:
4176
+ type: string
4177
+ minLength: 1
4178
+ description: >-
4179
+ The exact `Idempotency-Key` the confirmed write will send. The token
4180
+ is bound to it.
4181
+ preview_summary:
4182
+ type: string
4183
+ minLength: 1
4184
+ maxLength: 4000
4185
+ description: >-
4186
+ Human-readable description of the approved action, retained for
4187
+ audit.
4188
+ user_approved:
4189
+ const: true
4190
+ description: >-
4191
+ Asserts that a human on the caller's side approved this specific
4192
+ action.
4193
+ CapabilityConfirmation:
4194
+ type: object
4195
+ required:
4196
+ - confirmation_token
4197
+ - token_type
4198
+ - capability_id
4199
+ - method
4200
+ - path
4201
+ - required_scopes
4202
+ - idempotency_key
4203
+ - expires_in
4204
+ - expires_at
4205
+ - preview_summary
4206
+ properties:
4207
+ confirmation_token:
4208
+ type: string
4209
+ description: Send as the `X-Capability-Confirmation` header on the write.
4210
+ token_type:
4211
+ type: string
4212
+ const: medal_capability_confirmation
4213
+ capability_id:
4214
+ type: string
4215
+ method:
4216
+ type: string
4217
+ path:
4218
+ type: string
4219
+ required_scopes:
4220
+ type: array
4221
+ items:
4222
+ type: string
4223
+ idempotency_key:
4224
+ type: [string, "null"]
4225
+ expires_in:
4226
+ type: integer
4227
+ minimum: 60
4228
+ maximum: 900
4229
+ expires_at:
4230
+ type: string
4231
+ format: date-time
4232
+ preview_summary:
4233
+ type: string
4234
+ ApiResponse_CapabilityConfirmation:
4235
+ $ref: "#/components/schemas/Envelope_CapabilityConfirmation"
4236
+ Envelope_CapabilityConfirmation:
4237
+ type: object
4238
+ required: [data]
4239
+ properties:
4240
+ data:
4241
+ $ref: "#/components/schemas/CapabilityConfirmation"
2885
4242
  Envelope_WebhookDeliveryArray:
2886
4243
  type: object
2887
4244
  required: [data]
@@ -2904,6 +4261,11 @@ components:
2904
4261
  $ref: "#/components/schemas/ConnectLinkCreateResult"
2905
4262
  Envelope_ConnectLinkArray:
2906
4263
  type: object
4264
+ deprecated: true
4265
+ description: >-
4266
+ Deprecated — `listChannelConnectLinks` responds with
4267
+ `PaginatedResponse_ConnectLink`. Retained for backwards compatibility
4268
+ with consumers of the generated contract types.
2907
4269
  required: [data]
2908
4270
  properties:
2909
4271
  data:
@@ -2918,6 +4280,11 @@ components:
2918
4280
  $ref: "#/components/schemas/ConnectLinkRevokeResult"
2919
4281
  Envelope_ChannelConnectionArray:
2920
4282
  type: object
4283
+ deprecated: true
4284
+ description: >-
4285
+ Deprecated — `listChannelConnections` responds with
4286
+ `PaginatedResponse_ChannelConnection`. Retained for backwards
4287
+ compatibility with consumers of the generated contract types.
2921
4288
  required: [data]
2922
4289
  properties:
2923
4290
  data: