From 3996de3d6881c8e47569c8efe4509773237854b7 Mon Sep 17 00:00:00 2001 From: Viljami Kuosmanen Date: Fri, 15 May 2026 14:36:57 +0300 Subject: [PATCH 1/2] chore(file-client): update spec with async ZIP job endpoints Regenerates @epilot/file-client OpenAPI bundle + types against the file-api spec that adds POST /v1/files:zipJob and GET /v1/files:zipJob/{job_id}, plus the CreateZipJobPayload variant that accepts either file_entity_ids or entity_query. Co-authored-by: Claude --- .changeset/file-client-async-zip-job.md | 8 + clients/file-client/src/openapi-runtime.json | 24 + clients/file-client/src/openapi.d.ts | 2353 +++++++++++++++++- clients/file-client/src/openapi.json | 266 +- 4 files changed, 2629 insertions(+), 22 deletions(-) create mode 100644 .changeset/file-client-async-zip-job.md diff --git a/.changeset/file-client-async-zip-job.md b/.changeset/file-client-async-zip-job.md new file mode 100644 index 00000000..b9102f3d --- /dev/null +++ b/.changeset/file-client-async-zip-job.md @@ -0,0 +1,8 @@ +--- +"@epilot/file-client": minor +--- + +Add async bulk ZIP download endpoints + +- `createZipJob` (`POST /v1/files:zipJob`) — start an async job that bundles files into a ZIP and emails the requester when ready. Accepts either an explicit `file_entity_ids` list (≤1000) or an `entity_query` resolved server-side (≤10,000 files). +- `getZipJob` (`GET /v1/files:zipJob/{job_id}`) — poll status and pick up the signed download URL once the job completes. diff --git a/clients/file-client/src/openapi-runtime.json b/clients/file-client/src/openapi-runtime.json index a262e53b..c6a56dcc 100644 --- a/clients/file-client/src/openapi-runtime.json +++ b/clients/file-client/src/openapi-runtime.json @@ -192,6 +192,30 @@ "responses": {} } }, + "/v1/files:zipJob": { + "post": { + "operationId": "createZipJob", + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": {} + } + }, + "/v1/files:zipJob/{job_id}": { + "get": { + "operationId": "getZipJob", + "parameters": [ + { + "name": "job_id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, "/v1/files/{id}/preview": { "get": { "operationId": "previewFile", diff --git a/clients/file-client/src/openapi.d.ts b/clients/file-client/src/openapi.d.ts index de0d0ae5..f5e418c1 100644 --- a/clients/file-client/src/openapi.d.ts +++ b/clients/file-client/src/openapi.d.ts @@ -1,5 +1,3 @@ -/* eslint-disable */ - import type { OpenAPIClient, Parameters, @@ -237,6 +235,2095 @@ declare namespace Components { */ relations?: FileRelationItem[]; } + /** + * Request payload to create a ZIP job for bulk file download. + * Provide either an explicit list of `file_entity_ids` (up to 1000) or an + * `entity_query` that resolves to file entities (up to 10000). + * + */ + export type CreateZipJobPayload = /** + * Request payload to create a ZIP job for bulk file download. + * Provide either an explicit list of `file_entity_ids` (up to 1000) or an + * `entity_query` that resolves to file entities (up to 10000). + * + */ + { + /** + * List of file entity IDs to include in the ZIP + * example: + * [ + * "ef7d985c-2385-44f4-9c71-ae06a52264f8", + * "3fa85f64-5717-4562-b3fc-2c963f66afa6" + * ] + */ + file_entity_ids: [ + string, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string? + ]; + /** + * Entity search query used to resolve files to include in the ZIP + */ + entity_query?: { + /** + * Lucene-style search query (same syntax as entity search) + * example: + * _schema:file AND _tags:invoice + */ + q: string; + /** + * Sort expression forwarded to the entity search + * example: + * _created_at:desc + */ + sort?: string; + }; + /** + * Name of the generated ZIP file + * example: + * Documents.zip + */ + zip_filename?: string; + /** + * Send email notification when ZIP is ready + */ + notify_email?: boolean; + } | { + /** + * List of file entity IDs to include in the ZIP + * example: + * [ + * "ef7d985c-2385-44f4-9c71-ae06a52264f8", + * "3fa85f64-5717-4562-b3fc-2c963f66afa6" + * ] + */ + file_entity_ids?: [ + string, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string?, + string? + ]; + /** + * Entity search query used to resolve files to include in the ZIP + */ + entity_query: { + /** + * Lucene-style search query (same syntax as entity search) + * example: + * _schema:file AND _tags:invoice + */ + q: string; + /** + * Sort expression forwarded to the entity search + * example: + * _created_at:desc + */ + sort?: string; + }; + /** + * Name of the generated ZIP file + * example: + * Documents.zip + */ + zip_filename?: string; + /** + * Send email notification when ZIP is ready + */ + notify_email?: boolean; + }; /** * Custom external download url used for the file * example: @@ -941,6 +3028,105 @@ declare namespace Components { */ custom_download_url: string; } + /** + * ZIP job status and result + */ + export interface ZipJob { + /** + * Unique identifier for the ZIP job + * example: + * 3fa85f64-5717-4562-b3fc-2c963f66afa6 + */ + job_id?: string; // uuid + /** + * Current status of the ZIP job + * example: + * completed + */ + status?: "queued" | "downloading" | "zipping" | "uploading" | "sending_notification" | "completed" | "failed"; + /** + * Progress information for the job + */ + progress?: { + /** + * Total number of files to process + * example: + * 100 + */ + total_files?: number; + /** + * Number of files successfully downloaded + * example: + * 75 + */ + downloaded_files?: number; + /** + * Number of files that failed to download + * example: + * 2 + */ + failed_files?: number; + }; + /** + * Result of the completed ZIP job + */ + result?: { + /** + * File entity ID of the generated ZIP + * example: + * ef7d985c-2385-44f4-9c71-ae06a52264f8 + */ + file_entity_id?: string; // uuid + /** + * Presigned download URL (expires in 24 hours) + * example: + * https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/files.zip?X-Amz-... + */ + download_url?: string; // uri + /** + * When the download URL expires + * example: + * 2024-01-02T12:00:00Z + */ + expires_at?: string; // date-time + /** + * Size of the generated ZIP file in bytes + * example: + * 104857600 + */ + zip_size_bytes?: number; + }; + /** + * Error message if job failed + * example: + * Failed to download file: access denied + */ + error?: string; + /** + * When the job was created + * example: + * 2024-01-01T12:00:00Z + */ + created_at?: string; // date-time + /** + * User ID who created the job + * example: + * 10234 + */ + created_by?: string; + /** + * Organization ID + * example: + * 123 + */ + org_id?: string; + /** + * When the job was last updated + * example: + * 2024-01-01T12:05:00Z + */ + updated_at?: string; // date-time + } } } declare namespace Paths { @@ -1011,6 +3197,45 @@ declare namespace Paths { Components.Responses.InternalServerError; } } + namespace CreateZipJob { + export type RequestBody = /** + * Request payload to create a ZIP job for bulk file download. + * Provide either an explicit list of `file_entity_ids` (up to 1000) or an + * `entity_query` that resolves to file entities (up to 10000). + * + */ + Components.Schemas.CreateZipJobPayload; + namespace Responses { + export type $202 = /* ZIP job status and result */ Components.Schemas.ZipJob; + export type $400 = /** + * A generic error returned by the API + * example: + * { + * "status": 400, + * "error": "Bad Request: filename is required" + * } + */ + Components.Responses.BadRequestError; + export type $401 = /** + * A generic error returned by the API + * example: + * { + * "status": 401, + * "error": "Unauthorized: Invalid or expired token" + * } + */ + Components.Responses.UnauthorizedError; + export type $500 = /** + * A generic error returned by the API + * example: + * { + * "status": 500, + * "error": "Internal Server Error" + * } + */ + Components.Responses.InternalServerError; + } + } namespace DeleteFile { namespace Parameters { export type ActivityId = /** @@ -1517,6 +3742,44 @@ declare namespace Paths { Components.Responses.InternalServerError; } } + namespace GetZipJob { + namespace Parameters { + export type JobId = string; // uuid + } + export interface PathParameters { + job_id: Parameters.JobId /* uuid */; + } + namespace Responses { + export type $200 = /* ZIP job status and result */ Components.Schemas.ZipJob; + export type $401 = /** + * A generic error returned by the API + * example: + * { + * "status": 401, + * "error": "Unauthorized: Invalid or expired token" + * } + */ + Components.Responses.UnauthorizedError; + export type $404 = /** + * A generic error returned by the API + * example: + * { + * "status": 404, + * "error": "Not Found: File entity not found" + * } + */ + Components.Responses.NotFoundError; + export type $500 = /** + * A generic error returned by the API + * example: + * { + * "status": 500, + * "error": "Internal Server Error" + * } + */ + Components.Responses.InternalServerError; + } + } namespace ListPublicLinksForFile { namespace Parameters { export type Id = string; @@ -2243,6 +4506,36 @@ export interface OperationMethods { data?: Paths.DownloadFiles.RequestBody, config?: AxiosRequestConfig ): OperationResponse + /** + * createZipJob - createZipJob + * + * Create a background job to ZIP multiple files and send a download link via email. + * + * For bulk downloads of more than 50 files, use this async endpoint instead of client-side zipping. + * The job will: + * 1. Download all requested files from S3 + * 2. Create a ZIP archive + * 3. Upload the ZIP to temporary storage + * 4. Send an email notification with the download link + * + * The ZIP file will be available for 7 days. + * + */ + 'createZipJob'( + parameters?: Parameters | null, + data?: Paths.CreateZipJob.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getZipJob - getZipJob + * + * Get the status of a ZIP job + */ + 'getZipJob'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse /** * previewFile - previewFile * @@ -2333,10 +4626,7 @@ export interface OperationMethods { /** * listPublicLinksForFile - listPublicLinksForFile * - * **Not yet implemented.** - * - * This endpoint will fetch all public links previously generated for a file. - * + * Fetches all public links previously generated for a file */ 'listPublicLinksForFile'( parameters?: Parameters | null, @@ -2380,10 +4670,7 @@ export interface OperationMethods { /** * revokePublicLink - revokePublicLink * - * **Not yet implemented.** - * - * This endpoint will revoke a public link, making the file inaccessible via that link. - * + * Revokes a given public link by ID */ 'revokePublicLink'( parameters?: Parameters | null, @@ -2666,6 +4953,40 @@ export interface PathsDictionary { config?: AxiosRequestConfig ): OperationResponse } + ['/v1/files:zipJob']: { + /** + * createZipJob - createZipJob + * + * Create a background job to ZIP multiple files and send a download link via email. + * + * For bulk downloads of more than 50 files, use this async endpoint instead of client-side zipping. + * The job will: + * 1. Download all requested files from S3 + * 2. Create a ZIP archive + * 3. Upload the ZIP to temporary storage + * 4. Send an email notification with the download link + * + * The ZIP file will be available for 7 days. + * + */ + 'post'( + parameters?: Parameters | null, + data?: Paths.CreateZipJob.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/v1/files:zipJob/{job_id}']: { + /** + * getZipJob - getZipJob + * + * Get the status of a ZIP job + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } ['/v1/files/{id}/preview']: { /** * previewFile - previewFile @@ -2784,10 +5105,7 @@ export interface PathsDictionary { /** * listPublicLinksForFile - listPublicLinksForFile * - * **Not yet implemented.** - * - * This endpoint will fetch all public links previously generated for a file. - * + * Fetches all public links previously generated for a file */ 'get'( parameters?: Parameters | null, @@ -2816,10 +5134,7 @@ export interface PathsDictionary { /** * revokePublicLink - revokePublicLink * - * **Not yet implemented.** - * - * This endpoint will revoke a public link, making the file inaccessible via that link. - * + * Revokes a given public link by ID */ 'delete'( parameters?: Parameters | null, @@ -2965,6 +5280,7 @@ export type BaseEntityAcl = Components.Schemas.BaseEntityAcl; export type BaseEntityOwner = Components.Schemas.BaseEntityOwner; export type BatchSaveFileVersionPayload = Components.Schemas.BatchSaveFileVersionPayload; export type CommonSaveFilePayload = Components.Schemas.CommonSaveFilePayload; +export type CreateZipJobPayload = Components.Schemas.CreateZipJobPayload; export type CustomDownloadUrl = Components.Schemas.CustomDownloadUrl; export type DownloadFilesPayload = Components.Schemas.DownloadFilesPayload; export type EntityId = Components.Schemas.EntityId; @@ -2991,3 +5307,4 @@ export type SaveFilePayloadV2 = Components.Schemas.SaveFilePayloadV2; export type SaveS3FilePayload = Components.Schemas.SaveS3FilePayload; export type UploadFilePayload = Components.Schemas.UploadFilePayload; export type VerifyCustomDownloadUrlPayload = Components.Schemas.VerifyCustomDownloadUrlPayload; +export type ZipJob = Components.Schemas.ZipJob; diff --git a/clients/file-client/src/openapi.json b/clients/file-client/src/openapi.json index 1d7461ae..d78d50e1 100644 --- a/clients/file-client/src/openapi.json +++ b/clients/file-client/src/openapi.json @@ -780,6 +780,101 @@ } } }, + "/v1/files:zipJob": { + "post": { + "operationId": "createZipJob", + "summary": "createZipJob", + "description": "Create a background job to ZIP multiple files and send a download link via email.\n\nFor bulk downloads of more than 50 files, use this async endpoint instead of client-side zipping.\nThe job will:\n1. Download all requested files from S3\n2. Create a ZIP archive\n3. Upload the ZIP to temporary storage\n4. Send an email notification with the download link\n\nThe ZIP file will be available for 7 days.\n", + "tags": [ + "File" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateZipJobPayload" + }, + "examples": { + "Zip multiple files": { + "value": { + "file_entity_ids": [ + "ef7d985c-2385-44f4-9c71-ae06a52264f8", + "3fa85f64-5717-4562-b3fc-2c963f66afa6" + ], + "zip_filename": "Documents.zip", + "notify_email": true + } + } + } + } + } + }, + "responses": { + "202": { + "description": "Job created, processing in background", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ZipJob" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "500": { + "$ref": "#/components/responses/InternalServerError" + } + } + } + }, + "/v1/files:zipJob/{job_id}": { + "get": { + "operationId": "getZipJob", + "summary": "getZipJob", + "description": "Get the status of a ZIP job", + "tags": [ + "File" + ], + "parameters": [ + { + "name": "job_id", + "in": "path", + "required": true, + "description": "The UUID of the ZIP job", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "ZIP job status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ZipJob" + } + } + } + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "404": { + "$ref": "#/components/responses/NotFoundError" + }, + "500": { + "$ref": "#/components/responses/InternalServerError" + } + } + } + }, "/v1/files/{id}/preview": { "get": { "operationId": "previewFile", @@ -1199,8 +1294,7 @@ "get": { "operationId": "listPublicLinksForFile", "summary": "listPublicLinksForFile", - "description": "**Not yet implemented.**\n\nThis endpoint will fetch all public links previously generated for a file.\n", - "x-not-implemented": true, + "description": "Fetches all public links previously generated for a file", "parameters": [ { "name": "id", @@ -1340,8 +1434,7 @@ "delete": { "operationId": "revokePublicLink", "summary": "revokePublicLink", - "description": "**Not yet implemented.**\n\nThis endpoint will revoke a public link, making the file inaccessible via that link.\n", - "x-not-implemented": true, + "description": "Revokes a given public link by ID", "parameters": [ { "name": "id", @@ -2378,6 +2471,171 @@ ] } }, + "CreateZipJobPayload": { + "type": "object", + "description": "Request payload to create a ZIP job for bulk file download.\nProvide either an explicit list of `file_entity_ids` (up to 1000) or an\n`entity_query` that resolves to file entities (up to 10000).\n", + "properties": { + "file_entity_ids": { + "type": "array", + "description": "List of file entity IDs to include in the ZIP", + "items": { + "type": "string", + "format": "uuid" + }, + "minItems": 1, + "maxItems": 1000, + "example": [ + "ef7d985c-2385-44f4-9c71-ae06a52264f8", + "3fa85f64-5717-4562-b3fc-2c963f66afa6" + ] + }, + "entity_query": { + "type": "object", + "description": "Entity search query used to resolve files to include in the ZIP", + "properties": { + "q": { + "type": "string", + "description": "Lucene-style search query (same syntax as entity search)", + "example": "_schema:file AND _tags:invoice" + }, + "sort": { + "type": "string", + "description": "Sort expression forwarded to the entity search", + "example": "_created_at:desc" + } + }, + "required": [ + "q" + ] + }, + "zip_filename": { + "type": "string", + "description": "Name of the generated ZIP file", + "default": "Files.zip", + "example": "Documents.zip" + }, + "notify_email": { + "type": "boolean", + "description": "Send email notification when ZIP is ready", + "default": true + } + }, + "oneOf": [ + { + "required": [ + "file_entity_ids" + ] + }, + { + "required": [ + "entity_query" + ] + } + ] + }, + "ZipJob": { + "type": "object", + "description": "ZIP job status and result", + "properties": { + "job_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the ZIP job", + "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6" + }, + "status": { + "type": "string", + "description": "Current status of the ZIP job", + "enum": [ + "queued", + "downloading", + "zipping", + "uploading", + "sending_notification", + "completed", + "failed" + ], + "example": "completed" + }, + "progress": { + "type": "object", + "description": "Progress information for the job", + "properties": { + "total_files": { + "type": "integer", + "description": "Total number of files to process", + "example": 100 + }, + "downloaded_files": { + "type": "integer", + "description": "Number of files successfully downloaded", + "example": 75 + }, + "failed_files": { + "type": "integer", + "description": "Number of files that failed to download", + "example": 2 + } + } + }, + "result": { + "type": "object", + "description": "Result of the completed ZIP job", + "properties": { + "file_entity_id": { + "type": "string", + "format": "uuid", + "description": "File entity ID of the generated ZIP", + "example": "ef7d985c-2385-44f4-9c71-ae06a52264f8" + }, + "download_url": { + "type": "string", + "format": "uri", + "description": "Presigned download URL (expires in 24 hours)", + "example": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/files.zip?X-Amz-..." + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "When the download URL expires", + "example": "2024-01-02T12:00:00Z" + }, + "zip_size_bytes": { + "type": "integer", + "description": "Size of the generated ZIP file in bytes", + "example": 104857600 + } + } + }, + "error": { + "type": "string", + "description": "Error message if job failed", + "example": "Failed to download file: access denied" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the job was created", + "example": "2024-01-01T12:00:00Z" + }, + "created_by": { + "type": "string", + "description": "User ID who created the job", + "example": "10234" + }, + "org_id": { + "type": "string", + "description": "Organization ID", + "example": "123" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "When the job was last updated", + "example": "2024-01-01T12:05:00Z" + } + } + }, "VerifyCustomDownloadUrlPayload": { "type": "object", "properties": { From 389ffa75eef826e5214fbae0d77a390ec17190cb Mon Sep 17 00:00:00 2001 From: Viljami Kuosmanen Date: Fri, 15 May 2026 14:40:48 +0300 Subject: [PATCH 2/2] @epilot/file-client@1.24.0 Co-authored-by: Claude --- clients/file-client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/file-client/package.json b/clients/file-client/package.json index d4f11d51..afb66846 100644 --- a/clients/file-client/package.json +++ b/clients/file-client/package.json @@ -1,6 +1,6 @@ { "name": "@epilot/file-client", - "version": "1.23.0", + "version": "1.24.0", "description": "Client library for the epilot File API", "main": "dist/index.js", "types": "dist/index.d.ts",