Skip to content

Commit b7bb614

Browse files
committed
docs(v2): correct the upload transfer contract and 16 other published claims
The upload transfer step was documented as Sim's own data plane on every deployment: "success is 204" and "a failure is the v2 error envelope". That holds only when Sim stores objects itself. With object storage configured the URL is the provider's presigned URL, so S3 and GCS answer 200 and Azure 201, and a failure is the provider's XML — a client written to the old text reads a successful cloud upload as a failure. Also states that part ETags do not need retaining: completion takes no body because Sim lists the parts from the provider itself. Other corrections, all to shipped descriptions rather than behaviour: - DELETE table and bulk-delete files archive rather than erase, and neither said so; bulk delete also cannot emit the 409 it declared - complete knowledge upload published a 402 only the create leg can raise - billing status conceals a foreign workspace id as 404, not the 403 its TSDoc and description both claimed - audit entries null a folder's resourceId and strip folder ids from metadata at every level; neither redaction was documented - details=full adds the workflow summary to workflow runs only, never to job runs; GET /logs folderPaths covers a subtree like its two siblings; getLog now carries the retention sentence - list secrets returns description too, and the logs and resources documents described only part of what they serve
1 parent e06130a commit b7bb614

18 files changed

Lines changed: 64 additions & 49 deletions

apps/docs/openapi-v2-billing.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
"name": "workspaceId",
4444
"in": "query",
4545
"required": false,
46-
"description": "Workspace whose payer should be resolved. Workspace API keys are pinned to their own workspace.",
46+
"description": "Workspace whose payer should be resolved. A workspace API key is pinned to its own workspace: any other id answers `404 Workspace not found`, which is also what an id that does not exist answers.",
4747
"schema": {
48-
"description": "Workspace whose payer should be resolved. Workspace API keys are pinned to their own workspace.",
48+
"description": "Workspace whose payer should be resolved. A workspace API key is pinned to its own workspace: any other id answers `404 Workspace not found`, which is also what an id that does not exist answers.",
4949
"type": "string",
5050
"minLength": 1,
5151
"maxLength": 128

apps/docs/openapi-v2-files-audit.json

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,7 +2010,7 @@
20102010
"post": {
20112011
"operationId": "bulkDeleteFiles",
20122012
"summary": "Delete Files",
2013-
"description": "Delete up to 1,000 workspace files in one operation.",
2013+
"description": "Delete up to 1,000 workspace files in one operation. This is the same soft delete as `DELETE /api/v2/files/{fileId}`: files are archived, not erased, and `POST /api/v2/files/{fileId}/restore` reverses each one.",
20142014
"tags": ["Files"],
20152015
"requestBody": {
20162016
"required": true,
@@ -2057,9 +2057,6 @@
20572057
"404": {
20582058
"$ref": "#/components/responses/NotFound"
20592059
},
2060-
"409": {
2061-
"$ref": "#/components/responses/Conflict"
2062-
},
20632060
"413": {
20642061
"$ref": "#/components/responses/PayloadTooLarge"
20652062
},
@@ -3105,7 +3102,7 @@
31053102
"url": {
31063103
"type": "string",
31073104
"format": "uri",
3108-
"description": "Signed URL to which the file bytes are uploaded. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. Success is `204` with an empty body. A failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response: `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. The URL is signed and self-describing — construct it from this field only, never by hand."
3105+
"description": "Signed URL to which the file bytes are uploaded. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. The URL is signed and self-describing — construct it from this field only, never by hand.\n\n**Where this URL points depends on the deployment, and so does what answers you.** When Sim stores objects itself the URL is Sim's own data plane: success is `204` with an empty body, and a failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response — `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. When object storage is configured — S3, Google Cloud Storage, or Azure Blob — the URL is that provider's own presigned URL, and the provider answers directly: treat **any `2xx` as success** (S3 and GCS answer `200`, Azure `201`), and on failure expect the provider's error document, typically XML, not the v2 envelope. Do not branch on `204` and do not parse a failure as JSON."
31093106
},
31103107
"headers": {
31113108
"type": "object",
@@ -3259,7 +3256,7 @@
32593256
"url": {
32603257
"type": "string",
32613258
"format": "uri",
3262-
"description": "Signed URL for this upload part. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. Success is `204` with an empty body. A failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response: `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. The URL is signed and self-describing — construct it from this field only, never by hand."
3259+
"description": "Signed URL for this upload part. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. The URL is signed and self-describing — construct it from this field only, never by hand.\n\n**Where this URL points depends on the deployment, and so does what answers you.** When Sim stores objects itself the URL is Sim's own data plane: success is `204` with an empty body, and a failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response — `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. When object storage is configured — S3, Google Cloud Storage, or Azure Blob — the URL is that provider's own presigned URL, and the provider answers directly: treat **any `2xx` as success** (S3 and GCS answer `200`, Azure `201`), and on failure expect the provider's error document, typically XML, not the v2 envelope. Do not branch on `204` and do not parse a failure as JSON.\n\nYou do not need to retain the `ETag` each part upload returns. Unlike a raw S3 multipart flow, completion takes no request body: Sim lists the uploaded parts from the provider itself and reads their entity tags there, so `POST .../complete` only has to happen after every part has been sent."
32633260
},
32643261
"headers": {
32653262
"type": "object",
@@ -3859,7 +3856,7 @@
38593856
"type": "null"
38603857
}
38613858
],
3862-
"description": "Identifier of the affected resource."
3859+
"description": "Identifier of the affected resource. Always null when `resourceType` is `folder`: folders are addressed by canonical path on this API, so their internal identifiers are withheld rather than published as an id no other endpoint accepts."
38633860
},
38643861
"resourceName": {
38653862
"anyOf": [
@@ -3884,7 +3881,7 @@
38843881
"description": "Human-readable description of the action."
38853882
},
38863883
"metadata": {
3887-
"description": "Arbitrary per-action JSON metadata."
3884+
"description": "Arbitrary per-action JSON metadata. Internal folder identifiers are stripped at every nesting level, for the same reason `resourceId` is null on a folder entry."
38883885
},
38893886
"createdAt": {
38903887
"type": "string",

apps/docs/openapi-v2-knowledge.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,9 +2234,6 @@
22342234
"401": {
22352235
"$ref": "#/components/responses/Unauthorized"
22362236
},
2237-
"402": {
2238-
"$ref": "#/components/responses/UsageLimitExceeded"
2239-
},
22402237
"403": {
22412238
"$ref": "#/components/responses/Forbidden"
22422239
},
@@ -6798,7 +6795,7 @@
67986795
"url": {
67996796
"type": "string",
68006797
"format": "uri",
6801-
"description": "Signed URL to which the file bytes are uploaded. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. Success is `204` with an empty body. A failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response: `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. The URL is signed and self-describing — construct it from this field only, never by hand."
6798+
"description": "Signed URL to which the file bytes are uploaded. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. The URL is signed and self-describing — construct it from this field only, never by hand.\n\n**Where this URL points depends on the deployment, and so does what answers you.** When Sim stores objects itself the URL is Sim's own data plane: success is `204` with an empty body, and a failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response — `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. When object storage is configured — S3, Google Cloud Storage, or Azure Blob — the URL is that provider's own presigned URL, and the provider answers directly: treat **any `2xx` as success** (S3 and GCS answer `200`, Azure `201`), and on failure expect the provider's error document, typically XML, not the v2 envelope. Do not branch on `204` and do not parse a failure as JSON."
68026799
},
68036800
"headers": {
68046801
"type": "object",
@@ -7002,7 +6999,7 @@
70026999
"url": {
70037000
"type": "string",
70047001
"format": "uri",
7005-
"description": "Signed URL for this upload part. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. Success is `204` with an empty body. A failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response: `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. The URL is signed and self-describing — construct it from this field only, never by hand."
7002+
"description": "Signed URL for this upload part. Send the bytes with `PUT` to this URL, including exactly the headers in `headers` and nothing that alters the body. The URL is signed and self-describing — construct it from this field only, never by hand.\n\n**Where this URL points depends on the deployment, and so does what answers you.** When Sim stores objects itself the URL is Sim's own data plane: success is `204` with an empty body, and a failure is the same `{ \"error\": { \"code\", \"message\" } }` envelope as every other v2 response — `400` when the body does not match the size or content type the session was created for, `403` when the token is invalid, expired, or belongs to another session, and `409` when the session is no longer accepting bytes. When object storage is configured — S3, Google Cloud Storage, or Azure Blob — the URL is that provider's own presigned URL, and the provider answers directly: treat **any `2xx` as success** (S3 and GCS answer `200`, Azure `201`), and on failure expect the provider's error document, typically XML, not the v2 envelope. Do not branch on `204` and do not parse a failure as JSON.\n\nYou do not need to retain the `ETag` each part upload returns. Unlike a raw S3 multipart flow, completion takes no request body: Sim lists the uploaded parts from the provider itself and reads their entity tags there, so `POST .../complete` only has to happen after every part has been sent."
70067003
},
70077004
"headers": {
70087005
"type": "object",

apps/docs/openapi-v2-logs.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"openapi": "3.1.0",
33
"info": {
44
"title": "Sim API v2 — Logs",
5-
"description": "Version 2 of the Sim REST API for listing workflow execution logs and retrieving complete diagnostic run snapshots.",
5+
"description": "Version 2 of the Sim REST API for workflow execution logs: listing runs, searching them with sortable filters, retrieving complete diagnostic run snapshots, and reading bucketed execution statistics.",
66
"version": "2.0.0",
77
"contact": {
88
"name": "Sim Support",
@@ -168,12 +168,12 @@
168168
"name": "details",
169169
"in": "query",
170170
"required": false,
171-
"description": "Response detail level. `full` adds the `workflow` summary to every item. `includeTraceSpans=true` and `includeFinalOutput=true` each imply `full`, so either one adds `workflow` even when `details=basic` is sent explicitly.",
171+
"description": "Response detail level. `full` adds the `workflow` summary to every workflow run; a job run never carries one, whatever this is set to. `includeTraceSpans=true` and `includeFinalOutput=true` each imply `full`, so either one adds `workflow` even when `details=basic` is sent explicitly.",
172172
"schema": {
173173
"default": "basic",
174174
"type": "string",
175175
"enum": ["basic", "full"],
176-
"description": "Response detail level. `full` adds the `workflow` summary to every item. `includeTraceSpans=true` and `includeFinalOutput=true` each imply `full`, so either one adds `workflow` even when `details=basic` is sent explicitly."
176+
"description": "Response detail level. `full` adds the `workflow` summary to every workflow run; a job run never carries one, whatever this is set to. `includeTraceSpans=true` and `includeFinalOutput=true` each imply `full`, so either one adds `workflow` even when `details=basic` is sent explicitly."
177177
}
178178
},
179179
{
@@ -279,10 +279,10 @@
279279
"name": "folderPaths",
280280
"in": "query",
281281
"required": false,
282-
"description": "Comma-separated workflow folder paths to include. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error.",
282+
"description": "Comma-separated workflow folder paths to include. A path covers its whole subtree, so `/prod` also selects runs in `/prod/nested`. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error.",
283283
"schema": {
284284
"type": "string",
285-
"description": "Comma-separated workflow folder paths to include. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
285+
"description": "Comma-separated workflow folder paths to include. A path covers its whole subtree, so `/prod` also selects runs in `/prod/nested`. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
286286
}
287287
}
288288
],
@@ -339,7 +339,7 @@
339339
"get": {
340340
"operationId": "getLog",
341341
"summary": "Get Log",
342-
"description": "Retrieve the diagnostic representation of a run, including its workflow snapshot, trace spans, final output, and cost. Trace spans are pruned on their own retention schedule, so an empty `traceSpans` array does not mean the run recorded none. A workspace folder tree over 10,000 folders is a `413`.",
342+
"description": "Retrieve the diagnostic representation of a run, including its workflow snapshot, trace spans, final output, and cost. Trace spans are pruned on their own retention schedule, so an empty `traceSpans` array does not mean the run recorded none. A workspace folder tree over 10,000 folders is a `413`. Runs are hard-deleted once they pass the payer's log retention window, so an older run is simply absent rather than reported as removed. The window is 30 days from run start on the free plan, unbounded on Pro and Team, and set per organization on Enterprise with an optional per-workspace override.",
343343
"tags": ["Logs"],
344344
"parameters": [
345345
{

apps/docs/openapi-v2-resources.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"openapi": "3.1.0",
33
"info": {
44
"title": "Sim API v2 — Workspace Resources",
5-
"description": "Version 2 of the Sim REST API for workspace metadata, members, MCP servers, skills, custom tools, credentials, and write-only secrets.",
5+
"description": "Version 2 of the Sim REST API for workspace metadata, members, MCP servers, skills, custom tools, credentials, write-only secrets, chat deployments, and the block, tool, connector-type, and enrichment catalogs.",
66
"version": "2.0.0",
77
"contact": {
88
"name": "Sim Support",
@@ -2578,7 +2578,7 @@
25782578
"get": {
25792579
"operationId": "listSecrets",
25802580
"summary": "List Secrets",
2581-
"description": "List workspace and caller-owned personal secret metadata with opaque cursor pagination. Only names, scope, role, and timestamps are returned; secret values are never returned. A workspace API key is rejected with `403`; use a personal API key.",
2581+
"description": "List workspace and caller-owned personal secret metadata with opaque cursor pagination. Only names, scope, description, role, and timestamps are returned; secret values are never returned. A workspace API key is rejected with `403`; use a personal API key.",
25822582
"tags": ["Secrets"],
25832583
"parameters": [
25842584
{

0 commit comments

Comments
 (0)