@arke-institute/sdk 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/openapi/spec.json CHANGED
@@ -1673,6 +1673,149 @@
1673
1673
  "expect_tip"
1674
1674
  ]
1675
1675
  },
1676
+ "EntityDeletedResponse": {
1677
+ "type": "object",
1678
+ "properties": {
1679
+ "id": {
1680
+ "type": "string",
1681
+ "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
1682
+ "description": "Entity ID (ULID format)",
1683
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
1684
+ },
1685
+ "cid": {
1686
+ "type": "string",
1687
+ "minLength": 1,
1688
+ "description": "IPFS Content Identifier (CID)",
1689
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
1690
+ },
1691
+ "deleted_at": {
1692
+ "type": "string",
1693
+ "format": "date-time",
1694
+ "description": "ISO timestamp when the entity was deleted"
1695
+ },
1696
+ "ver": {
1697
+ "type": "integer",
1698
+ "minimum": 0,
1699
+ "exclusiveMinimum": true,
1700
+ "description": "Entity version number",
1701
+ "example": 1
1702
+ },
1703
+ "prev_cid": {
1704
+ "type": "string",
1705
+ "minLength": 1,
1706
+ "description": "IPFS Content Identifier (CID)",
1707
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
1708
+ }
1709
+ },
1710
+ "required": [
1711
+ "id",
1712
+ "cid",
1713
+ "deleted_at",
1714
+ "ver",
1715
+ "prev_cid"
1716
+ ]
1717
+ },
1718
+ "DeleteEntityRequest": {
1719
+ "type": "object",
1720
+ "properties": {
1721
+ "expect_tip": {
1722
+ "type": "string",
1723
+ "minLength": 1,
1724
+ "description": "Current tip CID for CAS validation. Request fails with 409 if this does not match.",
1725
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
1726
+ },
1727
+ "note": {
1728
+ "type": "string",
1729
+ "description": "Optional note describing this change",
1730
+ "example": "Added Chapter 42: The Whiteness of the Whale"
1731
+ },
1732
+ "reason": {
1733
+ "type": "string",
1734
+ "maxLength": 500,
1735
+ "description": "Reason for deleting the entity",
1736
+ "example": "Duplicate entry"
1737
+ }
1738
+ },
1739
+ "required": [
1740
+ "expect_tip"
1741
+ ]
1742
+ },
1743
+ "EntityUpdateResponse": {
1744
+ "allOf": [
1745
+ {
1746
+ "$ref": "#/components/schemas/EntityResponse"
1747
+ },
1748
+ {
1749
+ "type": "object",
1750
+ "properties": {
1751
+ "prev_cid": {
1752
+ "type": "string",
1753
+ "minLength": 1,
1754
+ "description": "Previous version CID",
1755
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
1756
+ }
1757
+ },
1758
+ "required": [
1759
+ "prev_cid"
1760
+ ]
1761
+ }
1762
+ ]
1763
+ },
1764
+ "EntityRestoredResponse": {
1765
+ "allOf": [
1766
+ {
1767
+ "$ref": "#/components/schemas/EntityUpdateResponse"
1768
+ },
1769
+ {
1770
+ "type": "object",
1771
+ "properties": {
1772
+ "restored_from_ver": {
1773
+ "type": "integer",
1774
+ "minimum": 0,
1775
+ "exclusiveMinimum": true,
1776
+ "description": "The version number that was restored from",
1777
+ "example": 1
1778
+ }
1779
+ },
1780
+ "required": [
1781
+ "restored_from_ver"
1782
+ ]
1783
+ }
1784
+ ]
1785
+ },
1786
+ "RestoreEntityRequest": {
1787
+ "type": "object",
1788
+ "properties": {
1789
+ "expect_tip": {
1790
+ "type": "string",
1791
+ "minLength": 1,
1792
+ "description": "Current tip CID for CAS validation. Request fails with 409 if this does not match.",
1793
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
1794
+ },
1795
+ "note": {
1796
+ "type": "string",
1797
+ "description": "Optional note describing this change",
1798
+ "example": "Added Chapter 42: The Whiteness of the Whale"
1799
+ }
1800
+ },
1801
+ "required": [
1802
+ "expect_tip"
1803
+ ]
1804
+ },
1805
+ "EntityCollectionResponse": {
1806
+ "type": "object",
1807
+ "properties": {
1808
+ "collection_id": {
1809
+ "type": "string",
1810
+ "nullable": true,
1811
+ "description": "The collection ID this entity belongs to, or null if not in any collection",
1812
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
1813
+ }
1814
+ },
1815
+ "required": [
1816
+ "collection_id"
1817
+ ]
1818
+ },
1676
1819
  "AddRelationshipResponse": {
1677
1820
  "type": "object",
1678
1821
  "properties": {
@@ -1929,18 +2072,6 @@
1929
2072
  "exclusiveMinimum": true,
1930
2073
  "description": "Unix timestamp in milliseconds",
1931
2074
  "example": 1735214400000
1932
- },
1933
- "upload_url": {
1934
- "type": "string",
1935
- "format": "uri",
1936
- "description": "Presigned S3 URL for uploading file content",
1937
- "example": "https://arke-blocks.s3.amazonaws.com/01JFILE123.../v1?X-Amz-..."
1938
- },
1939
- "upload_expires_at": {
1940
- "type": "string",
1941
- "format": "date-time",
1942
- "description": "When the upload URL expires (15 minutes)",
1943
- "example": "2025-12-26T12:00:00.000Z"
1944
2075
  }
1945
2076
  },
1946
2077
  "required": [
@@ -1951,9 +2082,7 @@
1951
2082
  "relationships",
1952
2083
  "ver",
1953
2084
  "created_at",
1954
- "ts",
1955
- "upload_url",
1956
- "upload_expires_at"
2085
+ "ts"
1957
2086
  ]
1958
2087
  },
1959
2088
  "CreateFileRequest": {
@@ -1962,7 +2091,7 @@
1962
2091
  "key": {
1963
2092
  "type": "string",
1964
2093
  "minLength": 1,
1965
- "description": "Storage key in S3. Best practice: use the CID.",
2094
+ "description": "Storage key in R2. Best practice: use the CID.",
1966
2095
  "example": "bafkreiabc123..."
1967
2096
  },
1968
2097
  "filename": {
@@ -1980,14 +2109,9 @@
1980
2109
  "size": {
1981
2110
  "type": "integer",
1982
2111
  "minimum": 0,
1983
- "description": "File size in bytes",
2112
+ "description": "Expected file size in bytes (verified on upload)",
1984
2113
  "example": 1048576
1985
2114
  },
1986
- "cid": {
1987
- "type": "string",
1988
- "description": "Content identifier (CID). Not verified, just metadata.",
1989
- "example": "bafkreiabc123..."
1990
- },
1991
2115
  "description": {
1992
2116
  "type": "string",
1993
2117
  "description": "Description of the file",
@@ -2075,43 +2199,31 @@
2075
2199
  }
2076
2200
  ]
2077
2201
  },
2078
- "DownloadResponse": {
2079
- "type": "object",
2080
- "properties": {
2081
- "download_url": {
2082
- "type": "string",
2083
- "format": "uri",
2084
- "description": "Presigned S3 URL for downloading file content",
2085
- "example": "https://arke-blocks.s3.amazonaws.com/01JFILE123.../v1?X-Amz-..."
2086
- },
2087
- "expires_at": {
2088
- "type": "string",
2089
- "format": "date-time",
2090
- "description": "When the download URL expires (5 minutes)",
2091
- "example": "2025-12-26T12:00:00.000Z"
2092
- },
2093
- "filename": {
2094
- "type": "string",
2095
- "description": "Filename for download",
2096
- "example": "document.pdf"
2097
- },
2098
- "content_type": {
2099
- "type": "string",
2100
- "description": "MIME type of the file",
2101
- "example": "application/pdf"
2202
+ "UploadContentResponse": {
2203
+ "allOf": [
2204
+ {
2205
+ "$ref": "#/components/schemas/EntityResponse"
2102
2206
  },
2103
- "size": {
2104
- "type": "integer",
2105
- "description": "File size in bytes",
2106
- "example": 1048576
2207
+ {
2208
+ "type": "object",
2209
+ "properties": {
2210
+ "type": {
2211
+ "type": "string",
2212
+ "enum": [
2213
+ "file"
2214
+ ]
2215
+ },
2216
+ "prev_cid": {
2217
+ "type": "string",
2218
+ "minLength": 1,
2219
+ "description": "Previous version CID",
2220
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
2221
+ }
2222
+ },
2223
+ "required": [
2224
+ "prev_cid"
2225
+ ]
2107
2226
  }
2108
- },
2109
- "required": [
2110
- "download_url",
2111
- "expires_at",
2112
- "filename",
2113
- "content_type",
2114
- "size"
2115
2227
  ]
2116
2228
  },
2117
2229
  "UpdateFileResponse": {
@@ -2269,7 +2381,7 @@
2269
2381
  "key": {
2270
2382
  "type": "string",
2271
2383
  "minLength": 1,
2272
- "description": "New storage key. Must already exist in S3 (for regression to old version)."
2384
+ "description": "New storage key. Must already exist in R2 (for regression to old version)."
2273
2385
  },
2274
2386
  "filename": {
2275
2387
  "type": "string",
@@ -2286,10 +2398,6 @@
2286
2398
  "minimum": 0,
2287
2399
  "description": "New file size in bytes"
2288
2400
  },
2289
- "cid": {
2290
- "type": "string",
2291
- "description": "New content identifier"
2292
- },
2293
2401
  "description": {
2294
2402
  "type": "string",
2295
2403
  "description": "New description"
@@ -2302,26 +2410,20 @@
2302
2410
  "ReuploadFileResponse": {
2303
2411
  "allOf": [
2304
2412
  {
2305
- "$ref": "#/components/schemas/UpdateFileResponse"
2413
+ "$ref": "#/components/schemas/FileResponse"
2306
2414
  },
2307
2415
  {
2308
2416
  "type": "object",
2309
2417
  "properties": {
2310
- "upload_url": {
2311
- "type": "string",
2312
- "format": "uri",
2313
- "description": "Presigned S3 URL for uploading new file content"
2314
- },
2315
- "upload_expires_at": {
2418
+ "prev_cid": {
2316
2419
  "type": "string",
2317
- "format": "date-time",
2318
- "description": "When the upload URL expires (15 minutes)",
2319
- "example": "2025-12-26T12:00:00.000Z"
2420
+ "minLength": 1,
2421
+ "description": "Previous version CID",
2422
+ "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
2320
2423
  }
2321
2424
  },
2322
2425
  "required": [
2323
- "upload_url",
2324
- "upload_expires_at"
2426
+ "prev_cid"
2325
2427
  ]
2326
2428
  }
2327
2429
  ]
@@ -2343,7 +2445,7 @@
2343
2445
  "key": {
2344
2446
  "type": "string",
2345
2447
  "minLength": 1,
2346
- "description": "New storage key. Must NOT already exist in S3.",
2448
+ "description": "New storage key. Must NOT already exist in R2.",
2347
2449
  "example": "v2"
2348
2450
  },
2349
2451
  "content_type": {
@@ -2355,7 +2457,7 @@
2355
2457
  "size": {
2356
2458
  "type": "integer",
2357
2459
  "minimum": 0,
2358
- "description": "Size of the new file in bytes",
2460
+ "description": "Expected size of the new file in bytes (verified on upload)",
2359
2461
  "example": 2097152
2360
2462
  },
2361
2463
  "filename": {
@@ -2363,10 +2465,6 @@
2363
2465
  "minLength": 1,
2364
2466
  "description": "New filename (optional, keeps current if not provided)"
2365
2467
  },
2366
- "cid": {
2367
- "type": "string",
2368
- "description": "Content identifier for new file"
2369
- },
2370
2468
  "description": {
2371
2469
  "type": "string",
2372
2470
  "description": "New description"
@@ -2379,51 +2477,6 @@
2379
2477
  "size"
2380
2478
  ]
2381
2479
  },
2382
- "ConfirmUploadResponse": {
2383
- "allOf": [
2384
- {
2385
- "$ref": "#/components/schemas/FileResponse"
2386
- },
2387
- {
2388
- "type": "object",
2389
- "properties": {
2390
- "prev_cid": {
2391
- "type": "string",
2392
- "minLength": 1,
2393
- "description": "Previous version CID. Not present if upload was already confirmed.",
2394
- "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
2395
- },
2396
- "already_confirmed": {
2397
- "type": "boolean",
2398
- "description": "True if upload was already confirmed. Entity was not modified.",
2399
- "example": false
2400
- }
2401
- },
2402
- "required": [
2403
- "already_confirmed"
2404
- ]
2405
- }
2406
- ]
2407
- },
2408
- "ConfirmUploadRequest": {
2409
- "type": "object",
2410
- "properties": {
2411
- "expect_tip": {
2412
- "type": "string",
2413
- "minLength": 1,
2414
- "description": "Current tip CID for CAS validation. Request fails with 409 if this does not match.",
2415
- "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
2416
- },
2417
- "note": {
2418
- "type": "string",
2419
- "description": "Optional note describing this change",
2420
- "example": "Added Chapter 42: The Whiteness of the Whale"
2421
- }
2422
- },
2423
- "required": [
2424
- "expect_tip"
2425
- ]
2426
- },
2427
2480
  "CreateFolderResponse": {
2428
2481
  "type": "object",
2429
2482
  "properties": {
@@ -4354,99 +4407,64 @@
4354
4407
  "keys"
4355
4408
  ]
4356
4409
  },
4357
- "EventItem": {
4410
+ "Event": {
4358
4411
  "type": "object",
4359
4412
  "properties": {
4360
- "event_cid": {
4361
- "type": "string",
4362
- "minLength": 1,
4363
- "description": "CID of this event in the event chain",
4364
- "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
4365
- },
4366
- "type": {
4367
- "type": "string",
4368
- "enum": [
4369
- "create",
4370
- "update"
4371
- ],
4372
- "description": "Type of entity change event",
4373
- "example": "create"
4413
+ "id": {
4414
+ "type": "integer",
4415
+ "description": "Auto-increment event ID (use as cursor)",
4416
+ "example": 12346
4374
4417
  },
4375
4418
  "pi": {
4376
4419
  "type": "string",
4377
4420
  "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
4378
- "description": "Entity ID that was created or updated",
4421
+ "description": "Entity ID that changed",
4379
4422
  "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
4380
4423
  },
4381
- "ver": {
4382
- "type": "integer",
4383
- "minimum": 0,
4384
- "exclusiveMinimum": true,
4385
- "description": "Entity version number",
4386
- "example": 1
4387
- },
4388
- "tip_cid": {
4424
+ "cid": {
4389
4425
  "type": "string",
4390
4426
  "minLength": 1,
4391
- "description": "CID of the entity manifest at this version",
4427
+ "description": "New manifest CID",
4392
4428
  "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
4393
4429
  },
4394
4430
  "ts": {
4395
4431
  "type": "string",
4396
- "format": "date-time",
4397
- "description": "When the event was recorded",
4398
- "example": "2025-12-26T12:00:00.000Z"
4432
+ "description": "ISO timestamp of the event",
4433
+ "example": "2025-01-15T12:00:01Z"
4399
4434
  }
4400
4435
  },
4401
4436
  "required": [
4402
- "event_cid",
4403
- "type",
4437
+ "id",
4404
4438
  "pi",
4405
- "ver",
4406
- "tip_cid",
4439
+ "cid",
4407
4440
  "ts"
4408
4441
  ]
4409
4442
  },
4410
4443
  "EventsListResponse": {
4411
4444
  "type": "object",
4412
4445
  "properties": {
4413
- "items": {
4446
+ "events": {
4414
4447
  "type": "array",
4415
4448
  "items": {
4416
- "$ref": "#/components/schemas/EventItem"
4449
+ "$ref": "#/components/schemas/Event"
4417
4450
  },
4418
- "description": "Events in reverse chronological order"
4419
- },
4420
- "total_events": {
4421
- "type": "integer",
4422
- "minimum": 0,
4423
- "description": "Total events in the event chain",
4424
- "example": 1542
4425
- },
4426
- "total_pis": {
4427
- "type": "integer",
4428
- "minimum": 0,
4429
- "description": "Total unique entity IDs across all events",
4430
- "example": 987
4451
+ "description": "List of events"
4431
4452
  },
4432
4453
  "has_more": {
4433
4454
  "type": "boolean",
4434
- "description": "Whether more events exist beyond this page"
4455
+ "description": "Whether there are more events available",
4456
+ "example": true
4435
4457
  },
4436
- "next_cursor": {
4437
- "type": "string",
4438
- "nullable": true,
4439
- "minLength": 1,
4440
- "description": "CID to use as \"cursor\" parameter for next page",
4441
- "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
4458
+ "cursor": {
4459
+ "type": "integer",
4460
+ "description": "Cursor for the next page (pass as ?after= parameter)",
4461
+ "example": 12347
4442
4462
  }
4443
4463
  },
4444
4464
  "required": [
4445
- "items",
4446
- "total_events",
4447
- "total_pis",
4465
+ "events",
4448
4466
  "has_more",
4449
- "next_cursor"
4467
+ "cursor"
4450
4468
  ]
4451
4469
  }
4452
4470
  },
@@ -6098,7 +6116,248 @@
6098
6116
  "content": {
6099
6117
  "application/json": {
6100
6118
  "schema": {
6101
- "$ref": "#/components/schemas/EntityResponse"
6119
+ "$ref": "#/components/schemas/EntityResponse"
6120
+ }
6121
+ }
6122
+ }
6123
+ },
6124
+ "403": {
6125
+ "description": "Forbidden - Insufficient permissions",
6126
+ "content": {
6127
+ "application/json": {
6128
+ "schema": {
6129
+ "$ref": "#/components/schemas/ErrorResponse"
6130
+ },
6131
+ "example": {
6132
+ "error": "Forbidden: You do not have permission to perform this action"
6133
+ }
6134
+ }
6135
+ }
6136
+ },
6137
+ "404": {
6138
+ "description": "Not Found - Resource does not exist",
6139
+ "content": {
6140
+ "application/json": {
6141
+ "schema": {
6142
+ "$ref": "#/components/schemas/ErrorResponse"
6143
+ },
6144
+ "example": {
6145
+ "error": "Entity not found"
6146
+ }
6147
+ }
6148
+ }
6149
+ }
6150
+ }
6151
+ },
6152
+ "put": {
6153
+ "tags": [
6154
+ "Entities"
6155
+ ],
6156
+ "summary": "Update entity",
6157
+ "description": "Updates any entity with merge semantics. Properties are deep merged, relationships use upsert semantics. Use properties_remove and relationships_remove for deletions. Note: entity:update on a collection requires collection:update permission.",
6158
+ "x-arke-action": "entity:update",
6159
+ "x-arke-auth": "required",
6160
+ "security": [
6161
+ {
6162
+ "bearerAuth": []
6163
+ }
6164
+ ],
6165
+ "parameters": [
6166
+ {
6167
+ "schema": {
6168
+ "type": "string",
6169
+ "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
6170
+ "description": "Entity ID (ULID format)",
6171
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
6172
+ },
6173
+ "required": true,
6174
+ "description": "Entity ID (ULID)",
6175
+ "name": "id",
6176
+ "in": "path"
6177
+ }
6178
+ ],
6179
+ "requestBody": {
6180
+ "content": {
6181
+ "application/json": {
6182
+ "schema": {
6183
+ "$ref": "#/components/schemas/UpdateEntityRequest"
6184
+ }
6185
+ }
6186
+ }
6187
+ },
6188
+ "responses": {
6189
+ "200": {
6190
+ "description": "Entity updated",
6191
+ "content": {
6192
+ "application/json": {
6193
+ "schema": {
6194
+ "$ref": "#/components/schemas/EntityUpdatedResponse"
6195
+ }
6196
+ }
6197
+ }
6198
+ },
6199
+ "400": {
6200
+ "description": "Bad Request - Invalid input",
6201
+ "content": {
6202
+ "application/json": {
6203
+ "schema": {
6204
+ "$ref": "#/components/schemas/ValidationErrorResponse"
6205
+ },
6206
+ "example": {
6207
+ "error": "Validation failed",
6208
+ "details": {
6209
+ "issues": [
6210
+ {
6211
+ "path": [
6212
+ "properties",
6213
+ "label"
6214
+ ],
6215
+ "message": "Required"
6216
+ }
6217
+ ]
6218
+ }
6219
+ }
6220
+ }
6221
+ }
6222
+ },
6223
+ "401": {
6224
+ "description": "Unauthorized - Missing or invalid authentication",
6225
+ "content": {
6226
+ "application/json": {
6227
+ "schema": {
6228
+ "$ref": "#/components/schemas/ErrorResponse"
6229
+ },
6230
+ "example": {
6231
+ "error": "Unauthorized: Missing or invalid authentication token"
6232
+ }
6233
+ }
6234
+ }
6235
+ },
6236
+ "403": {
6237
+ "description": "Forbidden - Insufficient permissions",
6238
+ "content": {
6239
+ "application/json": {
6240
+ "schema": {
6241
+ "$ref": "#/components/schemas/ErrorResponse"
6242
+ },
6243
+ "example": {
6244
+ "error": "Forbidden: You do not have permission to perform this action"
6245
+ }
6246
+ }
6247
+ }
6248
+ },
6249
+ "404": {
6250
+ "description": "Not Found - Resource does not exist",
6251
+ "content": {
6252
+ "application/json": {
6253
+ "schema": {
6254
+ "$ref": "#/components/schemas/ErrorResponse"
6255
+ },
6256
+ "example": {
6257
+ "error": "Entity not found"
6258
+ }
6259
+ }
6260
+ }
6261
+ },
6262
+ "409": {
6263
+ "description": "Conflict - CAS validation failed (entity was modified)",
6264
+ "content": {
6265
+ "application/json": {
6266
+ "schema": {
6267
+ "$ref": "#/components/schemas/CASErrorResponse"
6268
+ },
6269
+ "example": {
6270
+ "error": "Conflict: entity was modified",
6271
+ "details": {
6272
+ "expected": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy",
6273
+ "actual": "bafyreinewabc123456789defghijklmnopqrstuvwxyz"
6274
+ }
6275
+ }
6276
+ }
6277
+ }
6278
+ }
6279
+ }
6280
+ },
6281
+ "delete": {
6282
+ "tags": [
6283
+ "Entities"
6284
+ ],
6285
+ "summary": "Delete entity",
6286
+ "description": "Soft-deletes an entity by creating a tombstone version. The entity can be restored later via POST /entities/:id/restore. Note: entity:delete on a collection requires collection:delete permission.",
6287
+ "x-arke-action": "entity:delete",
6288
+ "x-arke-auth": "required",
6289
+ "security": [
6290
+ {
6291
+ "bearerAuth": []
6292
+ }
6293
+ ],
6294
+ "parameters": [
6295
+ {
6296
+ "schema": {
6297
+ "type": "string",
6298
+ "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
6299
+ "description": "Entity ID (ULID format)",
6300
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
6301
+ },
6302
+ "required": true,
6303
+ "description": "Entity ID (ULID)",
6304
+ "name": "id",
6305
+ "in": "path"
6306
+ }
6307
+ ],
6308
+ "requestBody": {
6309
+ "content": {
6310
+ "application/json": {
6311
+ "schema": {
6312
+ "$ref": "#/components/schemas/DeleteEntityRequest"
6313
+ }
6314
+ }
6315
+ }
6316
+ },
6317
+ "responses": {
6318
+ "200": {
6319
+ "description": "Entity deleted",
6320
+ "content": {
6321
+ "application/json": {
6322
+ "schema": {
6323
+ "$ref": "#/components/schemas/EntityDeletedResponse"
6324
+ }
6325
+ }
6326
+ }
6327
+ },
6328
+ "400": {
6329
+ "description": "Bad Request - Invalid input",
6330
+ "content": {
6331
+ "application/json": {
6332
+ "schema": {
6333
+ "$ref": "#/components/schemas/ValidationErrorResponse"
6334
+ },
6335
+ "example": {
6336
+ "error": "Validation failed",
6337
+ "details": {
6338
+ "issues": [
6339
+ {
6340
+ "path": [
6341
+ "properties",
6342
+ "label"
6343
+ ],
6344
+ "message": "Required"
6345
+ }
6346
+ ]
6347
+ }
6348
+ }
6349
+ }
6350
+ }
6351
+ },
6352
+ "401": {
6353
+ "description": "Unauthorized - Missing or invalid authentication",
6354
+ "content": {
6355
+ "application/json": {
6356
+ "schema": {
6357
+ "$ref": "#/components/schemas/ErrorResponse"
6358
+ },
6359
+ "example": {
6360
+ "error": "Unauthorized: Missing or invalid authentication token"
6102
6361
  }
6103
6362
  }
6104
6363
  }
@@ -6128,16 +6387,35 @@
6128
6387
  }
6129
6388
  }
6130
6389
  }
6390
+ },
6391
+ "409": {
6392
+ "description": "Conflict - CAS validation failed (entity was modified)",
6393
+ "content": {
6394
+ "application/json": {
6395
+ "schema": {
6396
+ "$ref": "#/components/schemas/CASErrorResponse"
6397
+ },
6398
+ "example": {
6399
+ "error": "Conflict: entity was modified",
6400
+ "details": {
6401
+ "expected": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy",
6402
+ "actual": "bafyreinewabc123456789defghijklmnopqrstuvwxyz"
6403
+ }
6404
+ }
6405
+ }
6406
+ }
6131
6407
  }
6132
6408
  }
6133
- },
6134
- "put": {
6409
+ }
6410
+ },
6411
+ "/entities/{id}/restore": {
6412
+ "post": {
6135
6413
  "tags": [
6136
6414
  "Entities"
6137
6415
  ],
6138
- "summary": "Update entity",
6139
- "description": "Updates any entity with merge semantics. Properties are deep merged, relationships use upsert semantics. Use properties_remove and relationships_remove for deletions. Note: entity:update on a collection requires collection:update permission.",
6140
- "x-arke-action": "entity:update",
6416
+ "summary": "Restore deleted entity",
6417
+ "description": "Restores a deleted entity by finding the last non-deleted version and creating a new version from it. Note: entity:restore on a collection requires collection:restore permission.",
6418
+ "x-arke-action": "entity:restore",
6141
6419
  "x-arke-auth": "required",
6142
6420
  "security": [
6143
6421
  {
@@ -6162,18 +6440,18 @@
6162
6440
  "content": {
6163
6441
  "application/json": {
6164
6442
  "schema": {
6165
- "$ref": "#/components/schemas/UpdateEntityRequest"
6443
+ "$ref": "#/components/schemas/RestoreEntityRequest"
6166
6444
  }
6167
6445
  }
6168
6446
  }
6169
6447
  },
6170
6448
  "responses": {
6171
6449
  "200": {
6172
- "description": "Entity updated",
6450
+ "description": "Entity restored",
6173
6451
  "content": {
6174
6452
  "application/json": {
6175
6453
  "schema": {
6176
- "$ref": "#/components/schemas/EntityUpdatedResponse"
6454
+ "$ref": "#/components/schemas/EntityRestoredResponse"
6177
6455
  }
6178
6456
  }
6179
6457
  }
@@ -6261,6 +6539,69 @@
6261
6539
  }
6262
6540
  }
6263
6541
  },
6542
+ "/entities/{id}/collection": {
6543
+ "get": {
6544
+ "tags": [
6545
+ "Entities"
6546
+ ],
6547
+ "summary": "Get entity collection",
6548
+ "description": "Returns the collection ID that this entity belongs to. Returns null if the entity is not in any collection. If the entity IS a collection, returns its own ID.",
6549
+ "x-arke-action": "entity:view",
6550
+ "x-arke-auth": "optional",
6551
+ "parameters": [
6552
+ {
6553
+ "schema": {
6554
+ "type": "string",
6555
+ "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
6556
+ "description": "Entity ID (ULID format)",
6557
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
6558
+ },
6559
+ "required": true,
6560
+ "description": "Entity ID (ULID)",
6561
+ "name": "id",
6562
+ "in": "path"
6563
+ }
6564
+ ],
6565
+ "responses": {
6566
+ "200": {
6567
+ "description": "Collection lookup result",
6568
+ "content": {
6569
+ "application/json": {
6570
+ "schema": {
6571
+ "$ref": "#/components/schemas/EntityCollectionResponse"
6572
+ }
6573
+ }
6574
+ }
6575
+ },
6576
+ "403": {
6577
+ "description": "Forbidden - Insufficient permissions",
6578
+ "content": {
6579
+ "application/json": {
6580
+ "schema": {
6581
+ "$ref": "#/components/schemas/ErrorResponse"
6582
+ },
6583
+ "example": {
6584
+ "error": "Forbidden: You do not have permission to perform this action"
6585
+ }
6586
+ }
6587
+ }
6588
+ },
6589
+ "404": {
6590
+ "description": "Not Found - Resource does not exist",
6591
+ "content": {
6592
+ "application/json": {
6593
+ "schema": {
6594
+ "$ref": "#/components/schemas/ErrorResponse"
6595
+ },
6596
+ "example": {
6597
+ "error": "Entity not found"
6598
+ }
6599
+ }
6600
+ }
6601
+ }
6602
+ }
6603
+ }
6604
+ },
6264
6605
  "/relationships": {
6265
6606
  "post": {
6266
6607
  "tags": [
@@ -6499,7 +6840,7 @@
6499
6840
  "Files"
6500
6841
  ],
6501
6842
  "summary": "Create file entity",
6502
- "description": "Creates a new file entity and returns a presigned upload URL.\n\n## Flow\n1. Call this endpoint with file metadata (key, filename, content_type, size)\n2. Receive entity data + presigned S3 upload URL (uploaded: false)\n3. PUT the file content to the upload URL\n4. Call POST /{id}/confirm-upload to verify and set uploaded: true\n\n## Key Best Practice\nUse the file's CID as the key for content-addressable storage.\nThe system does NOT verify the CID - it's just metadata.",
6843
+ "description": "Creates a new file entity.\n\n## Flow\n1. Call this endpoint with file metadata (key, filename, content_type, size)\n2. Receive entity data (uploaded: false)\n3. POST the file content to /{id}/content\n4. Entity will be updated with uploaded: true and verified CID\n\n## Key Best Practice\nUse a unique identifier as the key (e.g., version number, timestamp).\nThe actual CID is computed during upload.",
6503
6844
  "x-arke-action": "file:create",
6504
6845
  "x-arke-auth": "required",
6505
6846
  "security": [
@@ -6603,7 +6944,7 @@
6603
6944
  "Files"
6604
6945
  ],
6605
6946
  "summary": "Get file metadata",
6606
- "description": "Returns file entity metadata. Use /download to get the file content.",
6947
+ "description": "Returns file entity metadata. Use /{id}/content to download the file content.",
6607
6948
  "x-arke-action": "file:view",
6608
6949
  "x-arke-auth": "optional",
6609
6950
  "parameters": [
@@ -6664,7 +7005,7 @@
6664
7005
  "Files"
6665
7006
  ],
6666
7007
  "summary": "Update file metadata",
6667
- "description": "Updates file metadata without changing the file content.\n\n## Key Changes\nThe key can be changed, but ONLY to a key that already exists in S3.\nThis allows \"regressing\" to a previous file version.\n\nTo upload a new file, use POST /{id}/reupload instead.",
7008
+ "description": "Updates file metadata without changing the file content.\n\n## Key Changes\nThe key can be changed, but ONLY to a key that already exists in R2.\nThis allows \"regressing\" to a previous file version.\n\nTo upload a new file, use POST /{id}/reupload instead.",
6668
7009
  "x-arke-action": "file:update",
6669
7010
  "x-arke-auth": "required",
6670
7011
  "security": [
@@ -6789,77 +7130,14 @@
6789
7130
  }
6790
7131
  }
6791
7132
  },
6792
- "/files/{id}/download": {
6793
- "get": {
6794
- "tags": [
6795
- "Files"
6796
- ],
6797
- "summary": "Get download URL",
6798
- "description": "Returns a presigned URL for downloading the file content. URL expires in 5 minutes.",
6799
- "x-arke-action": "file:download",
6800
- "x-arke-auth": "optional",
6801
- "parameters": [
6802
- {
6803
- "schema": {
6804
- "type": "string",
6805
- "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
6806
- "description": "Entity ID (ULID format)",
6807
- "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
6808
- },
6809
- "required": true,
6810
- "description": "Entity ID (ULID)",
6811
- "name": "id",
6812
- "in": "path"
6813
- }
6814
- ],
6815
- "responses": {
6816
- "200": {
6817
- "description": "Download URL generated",
6818
- "content": {
6819
- "application/json": {
6820
- "schema": {
6821
- "$ref": "#/components/schemas/DownloadResponse"
6822
- }
6823
- }
6824
- }
6825
- },
6826
- "403": {
6827
- "description": "Forbidden - Insufficient permissions",
6828
- "content": {
6829
- "application/json": {
6830
- "schema": {
6831
- "$ref": "#/components/schemas/ErrorResponse"
6832
- },
6833
- "example": {
6834
- "error": "Forbidden: You do not have permission to perform this action"
6835
- }
6836
- }
6837
- }
6838
- },
6839
- "404": {
6840
- "description": "Not Found - Resource does not exist",
6841
- "content": {
6842
- "application/json": {
6843
- "schema": {
6844
- "$ref": "#/components/schemas/ErrorResponse"
6845
- },
6846
- "example": {
6847
- "error": "Entity not found"
6848
- }
6849
- }
6850
- }
6851
- }
6852
- }
6853
- }
6854
- },
6855
- "/files/{id}/reupload": {
7133
+ "/files/{id}/content": {
6856
7134
  "post": {
6857
7135
  "tags": [
6858
7136
  "Files"
6859
7137
  ],
6860
- "summary": "Upload new file version",
6861
- "description": "Uploads a new version of a file.\n\n## Flow\n1. Call this endpoint with new key and file metadata\n2. Receive updated entity + presigned upload URL (uploaded: false)\n3. PUT the new file content to the upload URL\n4. Call POST /{id}/confirm-upload to verify and set uploaded: true\n5. Old file versions remain accessible via manifest history\n\n## Key Requirement\nThe new key must NOT already exist in S3 (no overwrites).\nPrevious file versions are preserved.",
6862
- "x-arke-action": "file:reupload",
7138
+ "summary": "Upload file content",
7139
+ "description": "Uploads the binary content for a file entity.\n\n## Request\n- Content-Type: The MIME type of the file (must match entity's content_type)\n- Body: Binary file content (streaming supported)\n\n## Limits\n- Maximum file size: 500 MB\n\n## Behavior\n- Streams content directly to R2\n- Computes CID from file bytes\n- Updates entity with uploaded: true, verified size, and computed CID\n- Atomic operation - either fully succeeds or fails\n\n## Idempotency\nRe-uploading content for an already-uploaded file will fail with 409 Conflict.\nUse POST /{id}/reupload first to create a new version.",
7140
+ "x-arke-action": "file:upload",
6863
7141
  "x-arke-auth": "required",
6864
7142
  "security": [
6865
7143
  {
@@ -6880,22 +7158,13 @@
6880
7158
  "in": "path"
6881
7159
  }
6882
7160
  ],
6883
- "requestBody": {
6884
- "content": {
6885
- "application/json": {
6886
- "schema": {
6887
- "$ref": "#/components/schemas/ReuploadFileRequest"
6888
- }
6889
- }
6890
- }
6891
- },
6892
7161
  "responses": {
6893
7162
  "200": {
6894
- "description": "File version created",
7163
+ "description": "File content uploaded",
6895
7164
  "content": {
6896
7165
  "application/json": {
6897
7166
  "schema": {
6898
- "$ref": "#/components/schemas/ReuploadFileResponse"
7167
+ "$ref": "#/components/schemas/UploadContentResponse"
6899
7168
  }
6900
7169
  }
6901
7170
  }
@@ -6979,18 +7248,103 @@
6979
7248
  }
6980
7249
  }
6981
7250
  }
7251
+ },
7252
+ "413": {
7253
+ "description": "File too large (max 500 MB)",
7254
+ "content": {
7255
+ "application/json": {
7256
+ "schema": {
7257
+ "$ref": "#/components/schemas/ValidationErrorResponse"
7258
+ }
7259
+ }
7260
+ }
7261
+ },
7262
+ "500": {
7263
+ "description": "Internal Server Error",
7264
+ "content": {
7265
+ "application/json": {
7266
+ "schema": {
7267
+ "$ref": "#/components/schemas/ErrorResponse"
7268
+ },
7269
+ "example": {
7270
+ "error": "Internal server error"
7271
+ }
7272
+ }
7273
+ }
7274
+ }
7275
+ }
7276
+ },
7277
+ "get": {
7278
+ "tags": [
7279
+ "Files"
7280
+ ],
7281
+ "summary": "Download file content",
7282
+ "description": "Downloads the binary content of a file entity.\n\n## Response Headers\n- Content-Type: The MIME type of the file\n- Content-Length: File size in bytes\n- Content-Disposition: attachment; filename=\"original_filename\"\n\n## Streaming\nResponse is streamed directly from R2 storage.",
7283
+ "x-arke-action": "file:download",
7284
+ "x-arke-auth": "optional",
7285
+ "parameters": [
7286
+ {
7287
+ "schema": {
7288
+ "type": "string",
7289
+ "pattern": "^(?:II[0-9A-HJKMNP-TV-Z]{24}|[FC][0-9A-HJKMNP-TV-Z]{25}|[0-9A-HJKMNP-TV-Z]{26})$",
7290
+ "description": "Entity ID (ULID format)",
7291
+ "example": "01KDETYWYWM0MJVKM8DK3AEXPY"
7292
+ },
7293
+ "required": true,
7294
+ "description": "Entity ID (ULID)",
7295
+ "name": "id",
7296
+ "in": "path"
7297
+ }
7298
+ ],
7299
+ "responses": {
7300
+ "200": {
7301
+ "description": "File content",
7302
+ "content": {
7303
+ "application/octet-stream": {
7304
+ "schema": {
7305
+ "type": "string",
7306
+ "format": "binary"
7307
+ }
7308
+ }
7309
+ }
7310
+ },
7311
+ "403": {
7312
+ "description": "Forbidden - Insufficient permissions",
7313
+ "content": {
7314
+ "application/json": {
7315
+ "schema": {
7316
+ "$ref": "#/components/schemas/ErrorResponse"
7317
+ },
7318
+ "example": {
7319
+ "error": "Forbidden: You do not have permission to perform this action"
7320
+ }
7321
+ }
7322
+ }
7323
+ },
7324
+ "404": {
7325
+ "description": "Not Found - Resource does not exist",
7326
+ "content": {
7327
+ "application/json": {
7328
+ "schema": {
7329
+ "$ref": "#/components/schemas/ErrorResponse"
7330
+ },
7331
+ "example": {
7332
+ "error": "Entity not found"
7333
+ }
7334
+ }
7335
+ }
6982
7336
  }
6983
7337
  }
6984
7338
  }
6985
7339
  },
6986
- "/files/{id}/confirm-upload": {
7340
+ "/files/{id}/reupload": {
6987
7341
  "post": {
6988
7342
  "tags": [
6989
7343
  "Files"
6990
7344
  ],
6991
- "summary": "Confirm upload completed",
6992
- "description": "Confirms that file content has been uploaded to S3.\n\n## Flow\n1. Create file entity (POST /files) - sets uploaded: false\n2. PUT file content to the presigned upload URL\n3. Call this endpoint to confirm - verifies file exists in S3, sets uploaded: true\n\n## Verification\nThe server verifies the file exists in S3 before setting uploaded: true.\nIf the file doesn't exist, returns 400 error.\n\n## Idempotency\nIf already uploaded: true, returns success without modification.",
6993
- "x-arke-action": "file:update",
7345
+ "summary": "Prepare for new file version",
7346
+ "description": "Prepares the entity for uploading a new file version.\n\n## Flow\n1. Call this endpoint with new key and file metadata\n2. Receive updated entity (uploaded: false)\n3. POST the new file content to /{id}/content\n4. Entity will be updated with uploaded: true and verified CID\n\n## Key Requirement\nThe new key must NOT already exist in R2 (no overwrites).\nPrevious file versions remain accessible via manifest history.",
7347
+ "x-arke-action": "file:reupload",
6994
7348
  "x-arke-auth": "required",
6995
7349
  "security": [
6996
7350
  {
@@ -7015,18 +7369,18 @@
7015
7369
  "content": {
7016
7370
  "application/json": {
7017
7371
  "schema": {
7018
- "$ref": "#/components/schemas/ConfirmUploadRequest"
7372
+ "$ref": "#/components/schemas/ReuploadFileRequest"
7019
7373
  }
7020
7374
  }
7021
7375
  }
7022
7376
  },
7023
7377
  "responses": {
7024
7378
  "200": {
7025
- "description": "Upload confirmed",
7379
+ "description": "Ready for new file version upload",
7026
7380
  "content": {
7027
7381
  "application/json": {
7028
7382
  "schema": {
7029
- "$ref": "#/components/schemas/ConfirmUploadResponse"
7383
+ "$ref": "#/components/schemas/ReuploadFileResponse"
7030
7384
  }
7031
7385
  }
7032
7386
  }
@@ -8970,40 +9324,53 @@
8970
9324
  "tags": [
8971
9325
  "Events"
8972
9326
  ],
8973
- "summary": "List events",
8974
- "description": "Returns entity change events in reverse chronological order (newest first).\n\nEach event represents a create or update operation on an entity. Use cursor-based pagination to walk through the event history.\n\n**Use cases:**\n- Syncing entity changes to external systems\n- Building search indexes\n- Change tracking and audit logs\n\n**Note:** This endpoint is public. Access control is enforced at the entity level - if you don't have permission to view an entity, you won't be able to fetch its manifest even if you see an event for it.",
9327
+ "summary": "List entity change events",
9328
+ "description": "Returns a cursor-based list of entity change events for client synchronization.\n\n**Usage:**\n- Start with `?after=0` to get all events\n- Use the returned `cursor` as `?after=` for the next page\n- Poll periodically (e.g., every 10s) to stay in sync\n\n**Event data:**\n- `id`: Auto-increment ID (use as cursor)\n- `pi`: Entity ID that changed\n- `cid`: New manifest CID\n- `ts`: ISO timestamp\n\nEvents are ephemeral (30-day rolling window) - for full sync, use snapshots.",
8975
9329
  "x-arke-action": "events:list",
8976
9330
  "x-arke-auth": "none",
8977
9331
  "parameters": [
9332
+ {
9333
+ "schema": {
9334
+ "type": "integer",
9335
+ "nullable": true,
9336
+ "minimum": 0,
9337
+ "example": 12345
9338
+ },
9339
+ "required": false,
9340
+ "description": "Return events with id > after (cursor for pagination)",
9341
+ "name": "after",
9342
+ "in": "query"
9343
+ },
8978
9344
  {
8979
9345
  "schema": {
8980
9346
  "type": "integer",
8981
9347
  "minimum": 1,
8982
- "maximum": 100,
8983
- "default": 50,
8984
- "example": 50
9348
+ "maximum": 1000,
9349
+ "example": 100
8985
9350
  },
8986
9351
  "required": false,
8987
- "description": "Maximum events to return (1-100, default 50)",
9352
+ "description": "Maximum number of events to return (default: 100, max: 1000)",
8988
9353
  "name": "limit",
8989
9354
  "in": "query"
8990
9355
  },
8991
9356
  {
8992
9357
  "schema": {
8993
9358
  "type": "string",
8994
- "minLength": 1,
8995
- "description": "IPFS Content Identifier (CID)",
8996
- "example": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy"
9359
+ "enum": [
9360
+ "main",
9361
+ "test"
9362
+ ],
9363
+ "example": "main"
8997
9364
  },
8998
9365
  "required": false,
8999
- "description": "Event CID to continue from (for pagination)",
9000
- "name": "cursor",
9366
+ "description": "Network to query (default: main)",
9367
+ "name": "network",
9001
9368
  "in": "query"
9002
9369
  }
9003
9370
  ],
9004
9371
  "responses": {
9005
9372
  "200": {
9006
- "description": "Event list",
9373
+ "description": "Events list",
9007
9374
  "content": {
9008
9375
  "application/json": {
9009
9376
  "schema": {