|
169 | 169 | } |
170 | 170 | } |
171 | 171 | }, |
172 | | - "x-removed-buffered-post": { |
173 | | - "operationId": "uploadFile", |
174 | | - "summary": "Upload File", |
175 | | - "description": "Upload a file to a workspace as `multipart/form-data` with a single `file` field. The workspace — and the optional target `folderId` — are supplied as query parameters (not form fields) so authorization runs before the request body is buffered. Maximum file size is 100MB. A name already taken in the destination folder is **not** an error: the name is auto-suffixed (`data.csv` -> `data (1).csv`), matching the in-app uploader, so a `201` can come back with a `name` different from the one you sent — always read `name` from the response rather than assuming it. `409` is returned only if a unique name cannot be allocated after several attempts. Use `PATCH /api/v2/files/{fileId}` if you need a specific name to be exact-or-fail. Returns `201 Created`.\n\nPresigned upload is not part of the public API: it debits the storage quota only in a separate register step, so a caller that never registers would leave unaccounted bytes in storage. This buffered path debits inside the upload transaction.", |
| 172 | + "post": { |
| 173 | + "operationId": "createFile", |
| 174 | + "summary": "Create File", |
| 175 | + "description": "Create an authored workspace file, either empty or with initial inline content. Use this endpoint for files whose bytes are already available as UTF-8 text or base64 and are at most 50 MiB after decoding. Use the upload-session endpoints for streamed or larger files. A live file with the same name in the same folder is rejected with `409`.", |
176 | 176 | "tags": ["Files"], |
177 | 177 | "x-codeSamples": [ |
178 | 178 | { |
179 | 179 | "id": "curl", |
180 | 180 | "label": "cURL", |
181 | 181 | "lang": "bash", |
182 | | - "source": "curl -X POST \\\n \"https://www.sim.ai/api/v2/files?workspaceId=YOUR_WORKSPACE_ID\" \\\n -H \"X-API-Key: YOUR_API_KEY\" \\\n -F \"file=@/path/to/file.csv\"" |
183 | | - } |
184 | | - ], |
185 | | - "parameters": [ |
186 | | - { |
187 | | - "$ref": "#/components/parameters/WorkspaceIdQuery" |
188 | | - }, |
189 | | - { |
190 | | - "name": "folderId", |
191 | | - "in": "query", |
192 | | - "required": false, |
193 | | - "description": "Target file folder. Omit to upload to the workspace root. Supplied as a query parameter, like `workspaceId`, so authorization runs before the multipart body is buffered.", |
194 | | - "schema": { |
195 | | - "type": "string", |
196 | | - "example": "fold_9Kq2mZ7pR4tLxWc0Ye3Nu" |
197 | | - } |
| 182 | + "source": "curl -X POST \\\n \"https://www.sim.ai/api/v2/files\" \\\n -H \"X-API-Key: YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"workspaceId\": \"YOUR_WORKSPACE_ID\", \"name\": \"notes.md\"}'" |
198 | 183 | } |
199 | 184 | ], |
200 | 185 | "requestBody": { |
201 | 186 | "required": true, |
202 | | - "description": "The file to upload, sent as multipart/form-data.", |
203 | 187 | "content": { |
204 | | - "multipart/form-data": { |
| 188 | + "application/json": { |
205 | 189 | "schema": { |
206 | 190 | "type": "object", |
207 | | - "required": ["file"], |
| 191 | + "additionalProperties": false, |
| 192 | + "required": ["workspaceId", "name"], |
208 | 193 | "properties": { |
209 | | - "file": { |
| 194 | + "workspaceId": { |
| 195 | + "type": "string", |
| 196 | + "minLength": 1, |
| 197 | + "description": "Workspace in which to create the file." |
| 198 | + }, |
| 199 | + "name": { |
| 200 | + "type": "string", |
| 201 | + "minLength": 1, |
| 202 | + "maxLength": 255, |
| 203 | + "description": "File name, including its extension. Path separators and dot segments are rejected." |
| 204 | + }, |
| 205 | + "contentType": { |
| 206 | + "type": "string", |
| 207 | + "minLength": 1, |
| 208 | + "maxLength": 255, |
| 209 | + "description": "MIME type. When omitted, it is inferred from the file extension." |
| 210 | + }, |
| 211 | + "folderId": { |
| 212 | + "type": "string", |
| 213 | + "minLength": 1, |
| 214 | + "maxLength": 128, |
| 215 | + "description": "Destination folder. Omit to create the file at the workspace root." |
| 216 | + }, |
| 217 | + "content": { |
| 218 | + "type": "string", |
| 219 | + "maxLength": 70000000, |
| 220 | + "default": "", |
| 221 | + "description": "Initial file content. Omit or send an empty string to create a zero-byte file." |
| 222 | + }, |
| 223 | + "encoding": { |
210 | 224 | "type": "string", |
211 | | - "format": "binary", |
212 | | - "description": "The file to upload. Maximum size is 100MB." |
| 225 | + "enum": ["utf-8", "base64"], |
| 226 | + "default": "utf-8", |
| 227 | + "description": "Encoding of `content`." |
213 | 228 | } |
214 | 229 | } |
| 230 | + }, |
| 231 | + "example": { |
| 232 | + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", |
| 233 | + "name": "notes.md" |
215 | 234 | } |
216 | 235 | } |
217 | 236 | } |
218 | 237 | }, |
219 | 238 | "responses": { |
220 | 239 | "201": { |
221 | | - "description": "The file was uploaded successfully.", |
| 240 | + "description": "The created file.", |
222 | 241 | "headers": { |
223 | 242 | "X-RateLimit-Limit": { |
224 | 243 | "$ref": "#/components/headers/X-RateLimit-Limit" |
|
238 | 257 | "example": { |
239 | 258 | "data": { |
240 | 259 | "id": "wf_V1StGXR8z5jdHi6BmyT91", |
241 | | - "name": "data.csv", |
242 | | - "size": 1024, |
243 | | - "type": "text/csv", |
244 | | - "key": "workspace/a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64/1709571234-xyz-data.csv", |
245 | | - "folderId": "fold_9Kq2mZ7pR4tLxWc0Ye3Nu", |
246 | | - "folderPath": "Reports/Q1", |
| 260 | + "name": "notes.md", |
| 261 | + "size": 0, |
| 262 | + "type": "text/markdown", |
| 263 | + "key": "workspace/a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64/1709571234-xyz-notes.md", |
| 264 | + "folderId": null, |
| 265 | + "folderPath": null, |
247 | 266 | "uploadedBy": "user_abc123", |
248 | 267 | "uploadedAt": "2026-01-15T10:30:00Z", |
249 | 268 | "updatedAt": "2026-01-15T10:30:00Z" |
|
252 | 271 | } |
253 | 272 | } |
254 | 273 | }, |
255 | | - "400": { |
256 | | - "description": "The request was malformed: an invalid `workspaceId` query parameter, a body that is not valid multipart form data, or a missing `file` form field.", |
257 | | - "content": { |
258 | | - "application/json": { |
259 | | - "schema": { |
260 | | - "$ref": "#/components/schemas/V2Error" |
261 | | - }, |
262 | | - "example": { |
263 | | - "error": { |
264 | | - "code": "BAD_REQUEST", |
265 | | - "message": "file form field is required" |
266 | | - } |
267 | | - } |
268 | | - } |
269 | | - } |
270 | | - }, |
271 | | - "401": { |
272 | | - "$ref": "#/components/responses/Unauthorized" |
273 | | - }, |
274 | | - "403": { |
275 | | - "$ref": "#/components/responses/Forbidden" |
276 | | - }, |
277 | | - "409": { |
278 | | - "description": "A unique filename could not be allocated in the destination folder after several attempts. An ordinary name collision is auto-suffixed instead, not rejected.", |
279 | | - "content": { |
280 | | - "application/json": { |
281 | | - "schema": { |
282 | | - "$ref": "#/components/schemas/V2Error" |
283 | | - }, |
284 | | - "example": { |
285 | | - "error": { |
286 | | - "code": "CONFLICT", |
287 | | - "message": "A file named \"data.csv\" already exists in this workspace" |
288 | | - } |
289 | | - } |
290 | | - } |
291 | | - } |
292 | | - }, |
293 | | - "413": { |
294 | | - "description": "The upload exceeds the 100MB file size limit, or the workspace storage limit would be exceeded.", |
295 | | - "content": { |
296 | | - "application/json": { |
297 | | - "schema": { |
298 | | - "$ref": "#/components/schemas/V2Error" |
299 | | - }, |
300 | | - "example": { |
301 | | - "error": { |
302 | | - "code": "PAYLOAD_TOO_LARGE", |
303 | | - "message": "File size exceeds 100MB limit (142.30MB)" |
304 | | - } |
305 | | - } |
306 | | - } |
307 | | - } |
308 | | - }, |
309 | | - "429": { |
310 | | - "$ref": "#/components/responses/RateLimited" |
311 | | - }, |
312 | | - "500": { |
313 | | - "$ref": "#/components/responses/InternalError" |
314 | | - } |
| 274 | + "400": { "$ref": "#/components/responses/BadRequest" }, |
| 275 | + "401": { "$ref": "#/components/responses/Unauthorized" }, |
| 276 | + "403": { "$ref": "#/components/responses/Forbidden" }, |
| 277 | + "404": { "$ref": "#/components/responses/NotFound" }, |
| 278 | + "409": { "$ref": "#/components/responses/Conflict" }, |
| 279 | + "413": { "$ref": "#/components/responses/PayloadTooLarge" }, |
| 280 | + "429": { "$ref": "#/components/responses/RateLimited" }, |
| 281 | + "500": { "$ref": "#/components/responses/InternalError" } |
315 | 282 | } |
316 | 283 | } |
317 | 284 | }, |
318 | 285 | "/api/v2/files/uploads": { |
319 | 286 | "post": { |
320 | 287 | "operationId": "createFileUpload", |
321 | 288 | "summary": "Create File Upload", |
322 | | - "description": "Create a stateless multipart upload session and signed upload token. Every file uses this flow; a small file is a single part. The maximum file size is 5 GB.", |
| 289 | + "description": "Create an upload session and signed control token. Empty files and files up to and including 50 MiB receive a single signed PUT URL; larger files receive multipart transfer instructions. The maximum file size is 5 GB.", |
323 | 290 | "tags": ["Files"], |
324 | 291 | "requestBody": { |
325 | 292 | "required": true, |
|
405 | 372 | "post": { |
406 | 373 | "operationId": "completeFileUpload", |
407 | 374 | "summary": "Complete File Upload", |
408 | | - "description": "Verify every part, assemble the object, and atomically register the workspace file.", |
| 375 | + "description": "Verify the single PUT or assemble every multipart part, then atomically register the workspace file.", |
409 | 376 | "tags": ["Files"], |
410 | 377 | "parameters": [ |
411 | 378 | { |
|
1681 | 1648 | "name": "upload-token", |
1682 | 1649 | "in": "header", |
1683 | 1650 | "required": true, |
1684 | | - "description": "The signed token returned when the multipart upload was created.", |
| 1651 | + "description": "The signed control token returned when the upload session was created.", |
1685 | 1652 | "schema": { "type": "string", "minLength": 1 } |
1686 | 1653 | }, |
1687 | 1654 | "FileIdPath": { |
|
0 commit comments