@medalsocial/sdk 1.4.0 → 1.6.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.
@@ -53,6 +53,18 @@
53
53
  {
54
54
  "name": "Webhooks",
55
55
  "description": "Manage webhook endpoints and inspect their deliveries."
56
+ },
57
+ {
58
+ "name": "Capabilities",
59
+ "description": "Mint short-lived capability confirmation tokens for confirmable write routes."
60
+ },
61
+ {
62
+ "name": "Channels",
63
+ "description": "Partner channel connect — mint hosted connect links and manage the resulting channel connections."
64
+ },
65
+ {
66
+ "name": "Scan",
67
+ "description": "Company & website scans (Nettsjekk) — queue a scan by URL, organisation number, or company name, poll the result, and search the Norwegian company registry."
56
68
  }
57
69
  ],
58
70
  "paths": {
@@ -1576,6 +1588,327 @@
1576
1588
  }
1577
1589
  }
1578
1590
  }
1591
+ },
1592
+ "/api/v1/capability-confirmations": {
1593
+ "post": {
1594
+ "tags": [
1595
+ "Capabilities"
1596
+ ],
1597
+ "operationId": "issueCapabilityConfirmation",
1598
+ "summary": "Issue a capability confirmation token",
1599
+ "description": "Mints a short-lived `X-Capability-Confirmation` token for one pending write. Confirmable write routes require BOTH `Idempotency-Key` and `X-Capability-Confirmation` when the credential holds the capability scope directly; API keys with legacy scopes are exempt. The token is bound to the workspace, auth subject, method, path, required scopes and idempotency key, and expires within 15 minutes. `user_approved: true` asserts that a human on the caller's side approved this exact action.",
1600
+ "requestBody": {
1601
+ "required": true,
1602
+ "content": {
1603
+ "application/json": {
1604
+ "schema": {
1605
+ "$ref": "#/components/schemas/IssueCapabilityConfirmationInput"
1606
+ }
1607
+ }
1608
+ }
1609
+ },
1610
+ "responses": {
1611
+ "200": {
1612
+ "description": "Minted confirmation token.",
1613
+ "content": {
1614
+ "application/json": {
1615
+ "schema": {
1616
+ "$ref": "#/components/schemas/ApiResponse_CapabilityConfirmation"
1617
+ }
1618
+ }
1619
+ }
1620
+ },
1621
+ "default": {
1622
+ "$ref": "#/components/responses/ApiError"
1623
+ }
1624
+ }
1625
+ }
1626
+ },
1627
+ "/api/v1/channels/connect-links": {
1628
+ "post": {
1629
+ "tags": [
1630
+ "Channels"
1631
+ ],
1632
+ "operationId": "createChannelConnectLink",
1633
+ "summary": "Mint a hosted connect link",
1634
+ "description": "Mints a single-use hosted connect link that lets an external person (no Medal account required) attach a channel account (e.g. `telegram_inbox`) to the workspace's helpdesk. The response's `data.url` contains the one-time link token EXACTLY ONCE — an idempotent replay (same `Idempotency-Key`) returns the link WITHOUT `url`. Requires the `channel.connect.manage` scope; OAuth callers additionally need the workspace `admin` role.",
1635
+ "requestBody": {
1636
+ "required": true,
1637
+ "content": {
1638
+ "application/json": {
1639
+ "schema": {
1640
+ "$ref": "#/components/schemas/CreateConnectLinkInput"
1641
+ }
1642
+ }
1643
+ }
1644
+ },
1645
+ "responses": {
1646
+ "201": {
1647
+ "description": "Minted connect link, including the one-time `url`.",
1648
+ "content": {
1649
+ "application/json": {
1650
+ "schema": {
1651
+ "$ref": "#/components/schemas/ApiResponse_ConnectLinkCreateResult"
1652
+ }
1653
+ }
1654
+ }
1655
+ },
1656
+ "default": {
1657
+ "$ref": "#/components/responses/ApiError"
1658
+ }
1659
+ }
1660
+ },
1661
+ "get": {
1662
+ "tags": [
1663
+ "Channels"
1664
+ ],
1665
+ "operationId": "listChannelConnectLinks",
1666
+ "summary": "List connect links",
1667
+ "description": "Link tokens are never returned. Newest first, cursor-paginated. The `channel_type` / `status` filters are applied within each page, so a page may hold fewer than `limit` items while `pagination.has_more` is still true — page off `has_more`, not the item count.",
1668
+ "parameters": [
1669
+ {
1670
+ "name": "limit",
1671
+ "in": "query",
1672
+ "schema": {
1673
+ "type": "integer",
1674
+ "minimum": 1,
1675
+ "maximum": 100
1676
+ },
1677
+ "description": "Page size (default 50, capped at 100)."
1678
+ },
1679
+ {
1680
+ "$ref": "#/components/parameters/Cursor"
1681
+ },
1682
+ {
1683
+ "name": "channel_type",
1684
+ "in": "query",
1685
+ "schema": {
1686
+ "type": "string"
1687
+ }
1688
+ },
1689
+ {
1690
+ "name": "status",
1691
+ "in": "query",
1692
+ "schema": {
1693
+ "$ref": "#/components/schemas/ConnectLinkStatus"
1694
+ }
1695
+ }
1696
+ ],
1697
+ "responses": {
1698
+ "200": {
1699
+ "description": "Connect links page.",
1700
+ "content": {
1701
+ "application/json": {
1702
+ "schema": {
1703
+ "$ref": "#/components/schemas/PaginatedResponse_ConnectLink"
1704
+ }
1705
+ }
1706
+ }
1707
+ },
1708
+ "default": {
1709
+ "$ref": "#/components/responses/ApiError"
1710
+ }
1711
+ }
1712
+ }
1713
+ },
1714
+ "/api/v1/channels/connect-links/{id}": {
1715
+ "parameters": [
1716
+ {
1717
+ "$ref": "#/components/parameters/Id"
1718
+ }
1719
+ ],
1720
+ "delete": {
1721
+ "tags": [
1722
+ "Channels"
1723
+ ],
1724
+ "operationId": "revokeChannelConnectLink",
1725
+ "summary": "Revoke a connect link",
1726
+ "description": "Revokes a pending connect link so it can no longer be consumed. OAuth callers need the workspace `admin` role.",
1727
+ "responses": {
1728
+ "200": {
1729
+ "description": "Revoke result.",
1730
+ "content": {
1731
+ "application/json": {
1732
+ "schema": {
1733
+ "$ref": "#/components/schemas/ApiResponse_ConnectLinkRevokeResult"
1734
+ }
1735
+ }
1736
+ }
1737
+ },
1738
+ "default": {
1739
+ "$ref": "#/components/responses/ApiError"
1740
+ }
1741
+ }
1742
+ }
1743
+ },
1744
+ "/api/v1/channels/connections": {
1745
+ "get": {
1746
+ "tags": [
1747
+ "Channels"
1748
+ ],
1749
+ "operationId": "listChannelConnections",
1750
+ "summary": "List channel connections",
1751
+ "description": "The workspace's channel connections in a generic, channel-agnostic shape. Newest first, cursor-paginated. Rows that are not projectable as connections are dropped within the page, so a page may hold fewer than `limit` items while `pagination.has_more` is still true — page off `has_more`, not the item count.",
1752
+ "parameters": [
1753
+ {
1754
+ "name": "limit",
1755
+ "in": "query",
1756
+ "schema": {
1757
+ "type": "integer",
1758
+ "minimum": 1,
1759
+ "maximum": 100
1760
+ },
1761
+ "description": "Page size (default 50, capped at 100)."
1762
+ },
1763
+ {
1764
+ "$ref": "#/components/parameters/Cursor"
1765
+ }
1766
+ ],
1767
+ "responses": {
1768
+ "200": {
1769
+ "description": "Channel connections page.",
1770
+ "content": {
1771
+ "application/json": {
1772
+ "schema": {
1773
+ "$ref": "#/components/schemas/PaginatedResponse_ChannelConnection"
1774
+ }
1775
+ }
1776
+ }
1777
+ },
1778
+ "default": {
1779
+ "$ref": "#/components/responses/ApiError"
1780
+ }
1781
+ }
1782
+ }
1783
+ },
1784
+ "/api/v1/channels/connections/{id}": {
1785
+ "parameters": [
1786
+ {
1787
+ "$ref": "#/components/parameters/Id"
1788
+ }
1789
+ ],
1790
+ "delete": {
1791
+ "tags": [
1792
+ "Channels"
1793
+ ],
1794
+ "operationId": "disconnectChannelConnection",
1795
+ "summary": "Disconnect a channel connection",
1796
+ "description": "Disconnects a connected channel account (best-effort platform logout, then local revoke). Emits a `helpdesk.channel_disconnected` webhook event with `reason: \"api_disconnect\"` if the account was previously connected. OAuth callers need the workspace `admin` role.",
1797
+ "responses": {
1798
+ "200": {
1799
+ "description": "Disconnect result.",
1800
+ "content": {
1801
+ "application/json": {
1802
+ "schema": {
1803
+ "$ref": "#/components/schemas/ApiResponse_ChannelConnectionDisconnectResult"
1804
+ }
1805
+ }
1806
+ }
1807
+ },
1808
+ "default": {
1809
+ "$ref": "#/components/responses/ApiError"
1810
+ }
1811
+ }
1812
+ }
1813
+ },
1814
+ "/api/v1/scan": {
1815
+ "post": {
1816
+ "tags": [
1817
+ "Scan"
1818
+ ],
1819
+ "operationId": "createScan",
1820
+ "summary": "Queue a company/site scan",
1821
+ "description": "Queues an asynchronous scan. Provide exactly one of `url`, `orgnr`, or `name`; poll the returned id via `GET /api/v1/scan/{id}`.",
1822
+ "requestBody": {
1823
+ "required": true,
1824
+ "content": {
1825
+ "application/json": {
1826
+ "schema": {
1827
+ "$ref": "#/components/schemas/ScanCreateInput"
1828
+ }
1829
+ }
1830
+ }
1831
+ },
1832
+ "responses": {
1833
+ "202": {
1834
+ "description": "Scan job queued.",
1835
+ "content": {
1836
+ "application/json": {
1837
+ "schema": {
1838
+ "$ref": "#/components/schemas/ApiResponse_ScanCreateResult"
1839
+ }
1840
+ }
1841
+ }
1842
+ },
1843
+ "default": {
1844
+ "$ref": "#/components/responses/ApiError"
1845
+ }
1846
+ }
1847
+ }
1848
+ },
1849
+ "/api/v1/scan/companies": {
1850
+ "get": {
1851
+ "tags": [
1852
+ "Scan"
1853
+ ],
1854
+ "operationId": "searchScanCompanies",
1855
+ "summary": "Search the Norwegian company registry",
1856
+ "parameters": [
1857
+ {
1858
+ "name": "q",
1859
+ "in": "query",
1860
+ "required": true,
1861
+ "schema": {
1862
+ "type": "string",
1863
+ "minLength": 2
1864
+ }
1865
+ }
1866
+ ],
1867
+ "responses": {
1868
+ "200": {
1869
+ "description": "Registry matches (top 5, relevance-ranked).",
1870
+ "content": {
1871
+ "application/json": {
1872
+ "schema": {
1873
+ "$ref": "#/components/schemas/ApiResponse_ScanCompanyArray"
1874
+ }
1875
+ }
1876
+ }
1877
+ },
1878
+ "default": {
1879
+ "$ref": "#/components/responses/ApiError"
1880
+ }
1881
+ }
1882
+ }
1883
+ },
1884
+ "/api/v1/scan/{id}": {
1885
+ "parameters": [
1886
+ {
1887
+ "$ref": "#/components/parameters/Id"
1888
+ }
1889
+ ],
1890
+ "get": {
1891
+ "tags": [
1892
+ "Scan"
1893
+ ],
1894
+ "operationId": "getScan",
1895
+ "summary": "Get a scan job",
1896
+ "responses": {
1897
+ "200": {
1898
+ "description": "Scan job status and, once done, the findings payload.",
1899
+ "content": {
1900
+ "application/json": {
1901
+ "schema": {
1902
+ "$ref": "#/components/schemas/ApiResponse_ScanJob"
1903
+ }
1904
+ }
1905
+ }
1906
+ },
1907
+ "default": {
1908
+ "$ref": "#/components/responses/ApiError"
1909
+ }
1910
+ }
1911
+ }
1579
1912
  }
1580
1913
  },
1581
1914
  "components": {
@@ -3635,6 +3968,8 @@
3635
3968
  "author_user_id",
3636
3969
  "author_name",
3637
3970
  "body",
3971
+ "delivery_status",
3972
+ "delivery_error",
3638
3973
  "created_at"
3639
3974
  ],
3640
3975
  "properties": {
@@ -3665,12 +4000,39 @@
3665
4000
  "body": {
3666
4001
  "type": "string"
3667
4002
  },
4003
+ "delivery_status": {
4004
+ "oneOf": [
4005
+ {
4006
+ "$ref": "#/components/schemas/HelpdeskMessageDeliveryStatus"
4007
+ },
4008
+ {
4009
+ "type": "null"
4010
+ }
4011
+ ],
4012
+ "description": "Outbound delivery state, or `null` for inbound messages and internal notes. A `201` from `POST /api/v1/helpdesk/replies` means the reply was accepted, NOT delivered — the channel hand-off is asynchronous, so poll this field (or subscribe to `helpdesk.message_delivery_updated`) to learn the outcome."
4013
+ },
4014
+ "delivery_error": {
4015
+ "type": [
4016
+ "string",
4017
+ "null"
4018
+ ],
4019
+ "description": "Last send error for a `failed` outbound message, otherwise `null`."
4020
+ },
3668
4021
  "created_at": {
3669
4022
  "type": "integer",
3670
4023
  "description": "Unix timestamp in milliseconds."
3671
4024
  }
3672
4025
  }
3673
4026
  },
4027
+ "HelpdeskMessageDeliveryStatus": {
4028
+ "type": "string",
4029
+ "enum": [
4030
+ "pending",
4031
+ "sent",
4032
+ "delivered",
4033
+ "failed"
4034
+ ]
4035
+ },
3674
4036
  "UpdateHelpdeskConversationInput": {
3675
4037
  "type": "object",
3676
4038
  "minProperties": 1,
@@ -3968,9 +4330,16 @@
3968
4330
  },
3969
4331
  "WebhookDelivery": {
3970
4332
  "type": "object",
4333
+ "description": "A delivery attempt record. `id` is the same value sent as the `X-Medal-Delivery-Id` and `Idempotency-Key` headers on the outbound request. Deliveries never carry payload bodies (payloads can contain customer PII). The correlation fields are derived from the stored event and fail closed to `null` when no canonical event exists — e.g. `test.ping` deliveries or events that have aged out of retention.",
3971
4334
  "required": [
3972
4335
  "id",
3973
4336
  "event_type",
4337
+ "resource_id",
4338
+ "conversation_id",
4339
+ "message_id",
4340
+ "connection_ref",
4341
+ "channel",
4342
+ "channel_connection_id",
3974
4343
  "status",
3975
4344
  "attempt_count",
3976
4345
  "next_attempt_at",
@@ -3987,6 +4356,43 @@
3987
4356
  "event_type": {
3988
4357
  "type": "string"
3989
4358
  },
4359
+ "resource_id": {
4360
+ "type": [
4361
+ "string",
4362
+ "null"
4363
+ ],
4364
+ "description": "Primary subject id of the announced event, or `null`."
4365
+ },
4366
+ "conversation_id": {
4367
+ "type": [
4368
+ "string",
4369
+ "null"
4370
+ ]
4371
+ },
4372
+ "message_id": {
4373
+ "type": [
4374
+ "string",
4375
+ "null"
4376
+ ]
4377
+ },
4378
+ "connection_ref": {
4379
+ "type": [
4380
+ "string",
4381
+ "null"
4382
+ ]
4383
+ },
4384
+ "channel": {
4385
+ "type": [
4386
+ "string",
4387
+ "null"
4388
+ ]
4389
+ },
4390
+ "channel_connection_id": {
4391
+ "type": [
4392
+ "string",
4393
+ "null"
4394
+ ]
4395
+ },
3990
4396
  "status": {
3991
4397
  "type": "string",
3992
4398
  "enum": [
@@ -4052,6 +4458,207 @@
4052
4458
  }
4053
4459
  }
4054
4460
  },
4461
+ "ConnectLinkStatus": {
4462
+ "type": "string",
4463
+ "enum": [
4464
+ "pending",
4465
+ "consumed",
4466
+ "expired",
4467
+ "revoked"
4468
+ ]
4469
+ },
4470
+ "ChannelConnectionState": {
4471
+ "type": "string",
4472
+ "enum": [
4473
+ "connecting",
4474
+ "active",
4475
+ "disconnected",
4476
+ "disabled"
4477
+ ]
4478
+ },
4479
+ "CreateConnectLinkInput": {
4480
+ "type": "object",
4481
+ "required": [
4482
+ "channel_type"
4483
+ ],
4484
+ "properties": {
4485
+ "channel_type": {
4486
+ "type": "string",
4487
+ "maxLength": 64,
4488
+ "description": "Channel type to connect (e.g. `telegram_inbox`)."
4489
+ },
4490
+ "label": {
4491
+ "type": "string",
4492
+ "maxLength": 100,
4493
+ "description": "Display label shown on the hosted connect page."
4494
+ },
4495
+ "redirect_url": {
4496
+ "type": "string",
4497
+ "format": "uri",
4498
+ "maxLength": 2000,
4499
+ "description": "URL the hosted page redirects to after a successful connect — must be https."
4500
+ }
4501
+ }
4502
+ },
4503
+ "ConnectLinkCreateResult": {
4504
+ "type": "object",
4505
+ "required": [
4506
+ "id",
4507
+ "channel_type",
4508
+ "label",
4509
+ "status",
4510
+ "expires_at"
4511
+ ],
4512
+ "properties": {
4513
+ "id": {
4514
+ "type": "string"
4515
+ },
4516
+ "url": {
4517
+ "type": "string",
4518
+ "format": "uri",
4519
+ "description": "Single-use hosted connect URL containing the one-time link token — present ONLY in the live create response. An idempotent replay of the create request omits it; the token can never be retrieved again."
4520
+ },
4521
+ "channel_type": {
4522
+ "type": "string"
4523
+ },
4524
+ "label": {
4525
+ "type": [
4526
+ "string",
4527
+ "null"
4528
+ ]
4529
+ },
4530
+ "status": {
4531
+ "$ref": "#/components/schemas/ConnectLinkStatus"
4532
+ },
4533
+ "expires_at": {
4534
+ "type": "integer",
4535
+ "description": "Unix timestamp in milliseconds."
4536
+ }
4537
+ }
4538
+ },
4539
+ "ConnectLink": {
4540
+ "type": "object",
4541
+ "required": [
4542
+ "id",
4543
+ "channel_type",
4544
+ "label",
4545
+ "status",
4546
+ "consumed_connection_ref",
4547
+ "expires_at",
4548
+ "created_at"
4549
+ ],
4550
+ "properties": {
4551
+ "id": {
4552
+ "type": "string"
4553
+ },
4554
+ "channel_type": {
4555
+ "type": "string"
4556
+ },
4557
+ "label": {
4558
+ "type": [
4559
+ "string",
4560
+ "null"
4561
+ ]
4562
+ },
4563
+ "status": {
4564
+ "$ref": "#/components/schemas/ConnectLinkStatus"
4565
+ },
4566
+ "consumed_connection_ref": {
4567
+ "type": [
4568
+ "string",
4569
+ "null"
4570
+ ],
4571
+ "description": "Stable ref of the connection created by consuming this link, or `null`."
4572
+ },
4573
+ "expires_at": {
4574
+ "type": "integer",
4575
+ "description": "Unix timestamp in milliseconds."
4576
+ },
4577
+ "created_at": {
4578
+ "type": "integer",
4579
+ "description": "Unix timestamp in milliseconds."
4580
+ }
4581
+ }
4582
+ },
4583
+ "ConnectLinkRevokeResult": {
4584
+ "type": "object",
4585
+ "required": [
4586
+ "id",
4587
+ "status"
4588
+ ],
4589
+ "properties": {
4590
+ "id": {
4591
+ "type": "string"
4592
+ },
4593
+ "status": {
4594
+ "type": "string",
4595
+ "const": "revoked"
4596
+ }
4597
+ }
4598
+ },
4599
+ "ChannelConnection": {
4600
+ "type": "object",
4601
+ "required": [
4602
+ "id",
4603
+ "channel_type",
4604
+ "label",
4605
+ "state",
4606
+ "masked_identity",
4607
+ "last_activity_at",
4608
+ "helpdesk_connection_id"
4609
+ ],
4610
+ "properties": {
4611
+ "id": {
4612
+ "type": "string"
4613
+ },
4614
+ "channel_type": {
4615
+ "type": "string"
4616
+ },
4617
+ "label": {
4618
+ "type": [
4619
+ "string",
4620
+ "null"
4621
+ ]
4622
+ },
4623
+ "state": {
4624
+ "$ref": "#/components/schemas/ChannelConnectionState"
4625
+ },
4626
+ "masked_identity": {
4627
+ "type": "string",
4628
+ "description": "Privacy-preserving identity handle (e.g. a masked phone number)."
4629
+ },
4630
+ "last_activity_at": {
4631
+ "type": [
4632
+ "integer",
4633
+ "null"
4634
+ ],
4635
+ "description": "Unix timestamp in milliseconds, or `null` if never active."
4636
+ },
4637
+ "helpdesk_connection_id": {
4638
+ "type": [
4639
+ "string",
4640
+ "null"
4641
+ ],
4642
+ "description": "Linked helpdesk channel connection ID, or `null`."
4643
+ }
4644
+ }
4645
+ },
4646
+ "ChannelConnectionDisconnectResult": {
4647
+ "type": "object",
4648
+ "required": [
4649
+ "id",
4650
+ "state"
4651
+ ],
4652
+ "properties": {
4653
+ "id": {
4654
+ "type": "string"
4655
+ },
4656
+ "state": {
4657
+ "type": "string",
4658
+ "const": "disconnected"
4659
+ }
4660
+ }
4661
+ },
4055
4662
  "ApiResponse_PostCreateResult": {
4056
4663
  "$ref": "#/components/schemas/Envelope_PostCreateResult"
4057
4664
  },
@@ -4124,6 +4731,15 @@
4124
4731
  "ApiResponse_GdprExport": {
4125
4732
  "$ref": "#/components/schemas/Envelope_GdprExport"
4126
4733
  },
4734
+ "ApiResponse_ScanCreateResult": {
4735
+ "$ref": "#/components/schemas/Envelope_ScanCreateResult"
4736
+ },
4737
+ "ApiResponse_ScanCompanyArray": {
4738
+ "$ref": "#/components/schemas/Envelope_ScanCompanyArray"
4739
+ },
4740
+ "ApiResponse_ScanJob": {
4741
+ "$ref": "#/components/schemas/Envelope_ScanJob"
4742
+ },
4127
4743
  "ApiResponse_ConsentResult": {
4128
4744
  "$ref": "#/components/schemas/Envelope_ConsentResult"
4129
4745
  },
@@ -4157,6 +4773,21 @@
4157
4773
  "ApiResponse_WebhookTestResult": {
4158
4774
  "$ref": "#/components/schemas/Envelope_WebhookTestResult"
4159
4775
  },
4776
+ "ApiResponse_ConnectLinkCreateResult": {
4777
+ "$ref": "#/components/schemas/Envelope_ConnectLinkCreateResult"
4778
+ },
4779
+ "ApiResponse_ConnectLinkArray": {
4780
+ "$ref": "#/components/schemas/Envelope_ConnectLinkArray"
4781
+ },
4782
+ "ApiResponse_ConnectLinkRevokeResult": {
4783
+ "$ref": "#/components/schemas/Envelope_ConnectLinkRevokeResult"
4784
+ },
4785
+ "ApiResponse_ChannelConnectionArray": {
4786
+ "$ref": "#/components/schemas/Envelope_ChannelConnectionArray"
4787
+ },
4788
+ "ApiResponse_ChannelConnectionDisconnectResult": {
4789
+ "$ref": "#/components/schemas/Envelope_ChannelConnectionDisconnectResult"
4790
+ },
4160
4791
  "PaginatedResponse_Post": {
4161
4792
  "type": "object",
4162
4793
  "required": [
@@ -4265,6 +4896,42 @@
4265
4896
  }
4266
4897
  }
4267
4898
  },
4899
+ "PaginatedResponse_ConnectLink": {
4900
+ "type": "object",
4901
+ "required": [
4902
+ "data",
4903
+ "pagination"
4904
+ ],
4905
+ "properties": {
4906
+ "data": {
4907
+ "type": "array",
4908
+ "items": {
4909
+ "$ref": "#/components/schemas/ConnectLink"
4910
+ }
4911
+ },
4912
+ "pagination": {
4913
+ "$ref": "#/components/schemas/Pagination"
4914
+ }
4915
+ }
4916
+ },
4917
+ "PaginatedResponse_ChannelConnection": {
4918
+ "type": "object",
4919
+ "required": [
4920
+ "data",
4921
+ "pagination"
4922
+ ],
4923
+ "properties": {
4924
+ "data": {
4925
+ "type": "array",
4926
+ "items": {
4927
+ "$ref": "#/components/schemas/ChannelConnection"
4928
+ }
4929
+ },
4930
+ "pagination": {
4931
+ "$ref": "#/components/schemas/Pagination"
4932
+ }
4933
+ }
4934
+ },
4268
4935
  "Envelope_PostCreateResult": {
4269
4936
  "type": "object",
4270
4937
  "required": [
@@ -4502,28 +5169,335 @@
4502
5169
  }
4503
5170
  }
4504
5171
  },
4505
- "Envelope_GdprExportRequest": {
4506
- "type": "object",
4507
- "required": [
4508
- "data"
4509
- ],
4510
- "properties": {
4511
- "data": {
4512
- "$ref": "#/components/schemas/GdprExportRequest"
4513
- }
4514
- }
4515
- },
4516
- "Envelope_GdprExportArray": {
5172
+ "ScanCreateInput": {
4517
5173
  "type": "object",
4518
- "required": [
4519
- "data"
4520
- ],
4521
- "properties": {
4522
- "data": {
4523
- "type": "array",
4524
- "items": {
4525
- "$ref": "#/components/schemas/GdprExport"
4526
- }
5174
+ "description": "Provide exactly one of `url`, `orgnr`, or `name`.",
5175
+ "oneOf": [
5176
+ {
5177
+ "required": [
5178
+ "url"
5179
+ ],
5180
+ "not": {
5181
+ "anyOf": [
5182
+ {
5183
+ "required": [
5184
+ "orgnr"
5185
+ ]
5186
+ },
5187
+ {
5188
+ "required": [
5189
+ "name"
5190
+ ]
5191
+ }
5192
+ ]
5193
+ }
5194
+ },
5195
+ {
5196
+ "required": [
5197
+ "orgnr"
5198
+ ],
5199
+ "not": {
5200
+ "anyOf": [
5201
+ {
5202
+ "required": [
5203
+ "url"
5204
+ ]
5205
+ },
5206
+ {
5207
+ "required": [
5208
+ "name"
5209
+ ]
5210
+ }
5211
+ ]
5212
+ }
5213
+ },
5214
+ {
5215
+ "required": [
5216
+ "name"
5217
+ ],
5218
+ "not": {
5219
+ "anyOf": [
5220
+ {
5221
+ "required": [
5222
+ "url"
5223
+ ]
5224
+ },
5225
+ {
5226
+ "required": [
5227
+ "orgnr"
5228
+ ]
5229
+ }
5230
+ ]
5231
+ }
5232
+ }
5233
+ ],
5234
+ "properties": {
5235
+ "url": {
5236
+ "type": "string",
5237
+ "minLength": 4,
5238
+ "maxLength": 500
5239
+ },
5240
+ "orgnr": {
5241
+ "type": "string",
5242
+ "pattern": "^\\d{9}$"
5243
+ },
5244
+ "name": {
5245
+ "type": "string",
5246
+ "minLength": 2,
5247
+ "maxLength": 120
5248
+ }
5249
+ }
5250
+ },
5251
+ "ScanCreateResult": {
5252
+ "type": "object",
5253
+ "required": [
5254
+ "id",
5255
+ "status"
5256
+ ],
5257
+ "properties": {
5258
+ "id": {
5259
+ "type": "string"
5260
+ },
5261
+ "status": {
5262
+ "type": "string"
5263
+ },
5264
+ "message": {
5265
+ "type": "string"
5266
+ }
5267
+ }
5268
+ },
5269
+ "ScanCompany": {
5270
+ "type": "object",
5271
+ "required": [
5272
+ "orgnr",
5273
+ "name",
5274
+ "org_form",
5275
+ "industry",
5276
+ "city",
5277
+ "website"
5278
+ ],
5279
+ "properties": {
5280
+ "orgnr": {
5281
+ "type": "string"
5282
+ },
5283
+ "name": {
5284
+ "type": "string"
5285
+ },
5286
+ "org_form": {
5287
+ "type": [
5288
+ "string",
5289
+ "null"
5290
+ ]
5291
+ },
5292
+ "industry": {
5293
+ "type": [
5294
+ "string",
5295
+ "null"
5296
+ ]
5297
+ },
5298
+ "city": {
5299
+ "type": [
5300
+ "string",
5301
+ "null"
5302
+ ]
5303
+ },
5304
+ "website": {
5305
+ "type": [
5306
+ "string",
5307
+ "null"
5308
+ ]
5309
+ }
5310
+ }
5311
+ },
5312
+ "ScanJob": {
5313
+ "type": "object",
5314
+ "required": [
5315
+ "id",
5316
+ "status",
5317
+ "input",
5318
+ "resolved",
5319
+ "result",
5320
+ "error",
5321
+ "created_at",
5322
+ "finished_at"
5323
+ ],
5324
+ "properties": {
5325
+ "id": {
5326
+ "type": "string"
5327
+ },
5328
+ "status": {
5329
+ "type": "string",
5330
+ "description": "pending | running | done | failed"
5331
+ },
5332
+ "input": {
5333
+ "$ref": "#/components/schemas/ScanCreateInput"
5334
+ },
5335
+ "resolved": {
5336
+ "type": [
5337
+ "object",
5338
+ "null"
5339
+ ],
5340
+ "properties": {
5341
+ "orgnr": {
5342
+ "type": "string"
5343
+ },
5344
+ "companyName": {
5345
+ "type": "string"
5346
+ },
5347
+ "websiteUrl": {
5348
+ "type": "string"
5349
+ }
5350
+ }
5351
+ },
5352
+ "result": {
5353
+ "type": [
5354
+ "object",
5355
+ "null"
5356
+ ],
5357
+ "description": "Versioned findings payload (see the SDK `ScanResultPayload` type); additive per `version`. The stable core is documented below; further sections (registry, signals, pagespeed, seo, ai, gdpr, mailAuth, httpsOk) evolve additively.",
5358
+ "required": [
5359
+ "version",
5360
+ "nettskaar",
5361
+ "subScores"
5362
+ ],
5363
+ "properties": {
5364
+ "version": {
5365
+ "type": "integer"
5366
+ },
5367
+ "nettskaar": {
5368
+ "type": [
5369
+ "integer",
5370
+ "null"
5371
+ ],
5372
+ "description": "Weighted composite score (0-100); null when unmeasurable."
5373
+ },
5374
+ "subScores": {
5375
+ "type": "object",
5376
+ "description": "Per-axis 0-100 scores; null axes were unmeasurable.",
5377
+ "required": [
5378
+ "fart",
5379
+ "google",
5380
+ "ai",
5381
+ "trygghet",
5382
+ "omdomme"
5383
+ ],
5384
+ "properties": {
5385
+ "fart": {
5386
+ "type": [
5387
+ "integer",
5388
+ "null"
5389
+ ]
5390
+ },
5391
+ "google": {
5392
+ "type": [
5393
+ "integer",
5394
+ "null"
5395
+ ]
5396
+ },
5397
+ "ai": {
5398
+ "type": [
5399
+ "integer",
5400
+ "null"
5401
+ ]
5402
+ },
5403
+ "trygghet": {
5404
+ "type": [
5405
+ "integer",
5406
+ "null"
5407
+ ]
5408
+ },
5409
+ "omdomme": {
5410
+ "type": [
5411
+ "integer",
5412
+ "null"
5413
+ ]
5414
+ }
5415
+ }
5416
+ }
5417
+ },
5418
+ "additionalProperties": true
5419
+ },
5420
+ "error": {
5421
+ "type": [
5422
+ "string",
5423
+ "null"
5424
+ ],
5425
+ "description": "Public-safe failure code (company_not_found, no_website, …)."
5426
+ },
5427
+ "created_at": {
5428
+ "type": [
5429
+ "string",
5430
+ "null"
5431
+ ],
5432
+ "format": "date-time"
5433
+ },
5434
+ "finished_at": {
5435
+ "type": [
5436
+ "string",
5437
+ "null"
5438
+ ],
5439
+ "format": "date-time"
5440
+ }
5441
+ }
5442
+ },
5443
+ "Envelope_ScanCreateResult": {
5444
+ "type": "object",
5445
+ "required": [
5446
+ "data"
5447
+ ],
5448
+ "properties": {
5449
+ "data": {
5450
+ "$ref": "#/components/schemas/ScanCreateResult"
5451
+ }
5452
+ }
5453
+ },
5454
+ "Envelope_ScanCompanyArray": {
5455
+ "type": "object",
5456
+ "required": [
5457
+ "data"
5458
+ ],
5459
+ "properties": {
5460
+ "data": {
5461
+ "type": "array",
5462
+ "items": {
5463
+ "$ref": "#/components/schemas/ScanCompany"
5464
+ }
5465
+ }
5466
+ }
5467
+ },
5468
+ "Envelope_ScanJob": {
5469
+ "type": "object",
5470
+ "required": [
5471
+ "data"
5472
+ ],
5473
+ "properties": {
5474
+ "data": {
5475
+ "$ref": "#/components/schemas/ScanJob"
5476
+ }
5477
+ }
5478
+ },
5479
+ "Envelope_GdprExportRequest": {
5480
+ "type": "object",
5481
+ "required": [
5482
+ "data"
5483
+ ],
5484
+ "properties": {
5485
+ "data": {
5486
+ "$ref": "#/components/schemas/GdprExportRequest"
5487
+ }
5488
+ }
5489
+ },
5490
+ "Envelope_GdprExportArray": {
5491
+ "type": "object",
5492
+ "required": [
5493
+ "data"
5494
+ ],
5495
+ "properties": {
5496
+ "data": {
5497
+ "type": "array",
5498
+ "items": {
5499
+ "$ref": "#/components/schemas/GdprExport"
5500
+ }
4527
5501
  }
4528
5502
  }
4529
5503
  },
@@ -4646,6 +5620,126 @@
4646
5620
  }
4647
5621
  }
4648
5622
  },
5623
+ "IssueCapabilityConfirmationInput": {
5624
+ "type": "object",
5625
+ "required": [
5626
+ "capability_id",
5627
+ "preview_summary",
5628
+ "user_approved"
5629
+ ],
5630
+ "properties": {
5631
+ "capability_id": {
5632
+ "type": "string",
5633
+ "minLength": 1,
5634
+ "maxLength": 160,
5635
+ "description": "Confirmable capability to mint a token for."
5636
+ },
5637
+ "api_path": {
5638
+ "type": "string",
5639
+ "minLength": 1,
5640
+ "maxLength": 512,
5641
+ "description": "Concrete `/api/v1/...` path to bind the token to. Optional when the capability has exactly one API target; required when it has several."
5642
+ },
5643
+ "path_params": {
5644
+ "type": "object",
5645
+ "additionalProperties": {
5646
+ "type": [
5647
+ "string",
5648
+ "number",
5649
+ "boolean"
5650
+ ]
5651
+ },
5652
+ "description": "Values for the capability path template's parameters."
5653
+ },
5654
+ "idempotency_key": {
5655
+ "type": "string",
5656
+ "minLength": 1,
5657
+ "description": "The exact `Idempotency-Key` the confirmed write will send. The token is bound to it."
5658
+ },
5659
+ "preview_summary": {
5660
+ "type": "string",
5661
+ "minLength": 1,
5662
+ "maxLength": 4000,
5663
+ "description": "Human-readable description of the approved action, retained for audit."
5664
+ },
5665
+ "user_approved": {
5666
+ "const": true,
5667
+ "description": "Asserts that a human on the caller's side approved this specific action."
5668
+ }
5669
+ }
5670
+ },
5671
+ "CapabilityConfirmation": {
5672
+ "type": "object",
5673
+ "required": [
5674
+ "confirmation_token",
5675
+ "token_type",
5676
+ "capability_id",
5677
+ "method",
5678
+ "path",
5679
+ "required_scopes",
5680
+ "idempotency_key",
5681
+ "expires_in",
5682
+ "expires_at",
5683
+ "preview_summary"
5684
+ ],
5685
+ "properties": {
5686
+ "confirmation_token": {
5687
+ "type": "string",
5688
+ "description": "Send as the `X-Capability-Confirmation` header on the write."
5689
+ },
5690
+ "token_type": {
5691
+ "type": "string",
5692
+ "const": "medal_capability_confirmation"
5693
+ },
5694
+ "capability_id": {
5695
+ "type": "string"
5696
+ },
5697
+ "method": {
5698
+ "type": "string"
5699
+ },
5700
+ "path": {
5701
+ "type": "string"
5702
+ },
5703
+ "required_scopes": {
5704
+ "type": "array",
5705
+ "items": {
5706
+ "type": "string"
5707
+ }
5708
+ },
5709
+ "idempotency_key": {
5710
+ "type": [
5711
+ "string",
5712
+ "null"
5713
+ ]
5714
+ },
5715
+ "expires_in": {
5716
+ "type": "integer",
5717
+ "minimum": 60,
5718
+ "maximum": 900
5719
+ },
5720
+ "expires_at": {
5721
+ "type": "string",
5722
+ "format": "date-time"
5723
+ },
5724
+ "preview_summary": {
5725
+ "type": "string"
5726
+ }
5727
+ }
5728
+ },
5729
+ "ApiResponse_CapabilityConfirmation": {
5730
+ "$ref": "#/components/schemas/Envelope_CapabilityConfirmation"
5731
+ },
5732
+ "Envelope_CapabilityConfirmation": {
5733
+ "type": "object",
5734
+ "required": [
5735
+ "data"
5736
+ ],
5737
+ "properties": {
5738
+ "data": {
5739
+ "$ref": "#/components/schemas/CapabilityConfirmation"
5740
+ }
5741
+ }
5742
+ },
4649
5743
  "Envelope_WebhookDeliveryArray": {
4650
5744
  "type": "object",
4651
5745
  "required": [
@@ -4670,6 +5764,71 @@
4670
5764
  "$ref": "#/components/schemas/WebhookTestResult"
4671
5765
  }
4672
5766
  }
5767
+ },
5768
+ "Envelope_ConnectLinkCreateResult": {
5769
+ "type": "object",
5770
+ "required": [
5771
+ "data"
5772
+ ],
5773
+ "properties": {
5774
+ "data": {
5775
+ "$ref": "#/components/schemas/ConnectLinkCreateResult"
5776
+ }
5777
+ }
5778
+ },
5779
+ "Envelope_ConnectLinkArray": {
5780
+ "type": "object",
5781
+ "deprecated": true,
5782
+ "description": "Deprecated — `listChannelConnectLinks` responds with `PaginatedResponse_ConnectLink`. Retained for backwards compatibility with consumers of the generated contract types.",
5783
+ "required": [
5784
+ "data"
5785
+ ],
5786
+ "properties": {
5787
+ "data": {
5788
+ "type": "array",
5789
+ "items": {
5790
+ "$ref": "#/components/schemas/ConnectLink"
5791
+ }
5792
+ }
5793
+ }
5794
+ },
5795
+ "Envelope_ConnectLinkRevokeResult": {
5796
+ "type": "object",
5797
+ "required": [
5798
+ "data"
5799
+ ],
5800
+ "properties": {
5801
+ "data": {
5802
+ "$ref": "#/components/schemas/ConnectLinkRevokeResult"
5803
+ }
5804
+ }
5805
+ },
5806
+ "Envelope_ChannelConnectionArray": {
5807
+ "type": "object",
5808
+ "deprecated": true,
5809
+ "description": "Deprecated — `listChannelConnections` responds with `PaginatedResponse_ChannelConnection`. Retained for backwards compatibility with consumers of the generated contract types.",
5810
+ "required": [
5811
+ "data"
5812
+ ],
5813
+ "properties": {
5814
+ "data": {
5815
+ "type": "array",
5816
+ "items": {
5817
+ "$ref": "#/components/schemas/ChannelConnection"
5818
+ }
5819
+ }
5820
+ }
5821
+ },
5822
+ "Envelope_ChannelConnectionDisconnectResult": {
5823
+ "type": "object",
5824
+ "required": [
5825
+ "data"
5826
+ ],
5827
+ "properties": {
5828
+ "data": {
5829
+ "$ref": "#/components/schemas/ChannelConnectionDisconnectResult"
5830
+ }
5831
+ }
4673
5832
  }
4674
5833
  }
4675
5834
  }