@rbaileysr/zephyr-managed-api 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -331,6 +331,25 @@ The Managed API is organized into the following groups:
331
331
  - `createJUnitExecutions(request)` - Upload JUnit XML results
332
332
  - `retrieveBDDTestCases(options)` - Retrieve BDD feature files
333
333
 
334
+ ### Private API ⚠️
335
+ > **⚠️ WARNING: Private API Methods**
336
+ >
337
+ > The following methods use Zephyr's private/unofficial API endpoints that are:
338
+ > - **Not officially supported** by SmartBear
339
+ > - **Not part of the public API documentation**
340
+ > - **Subject to change at any time** without notice
341
+ > - **Not covered by Standard Support**
342
+ >
343
+ > Use these methods at your own risk. They may break with future Zephyr updates.
344
+
345
+ - `getContextJwt(userEmail, apiToken, jiraInstanceUrl)` - Get Jira Context JWT token (required for private API calls)
346
+ - `createCustomField(userEmail, apiToken, jiraInstanceUrl, category, request)` - Create custom fields for test cases, test plans, test runs, or test steps
347
+ - `createTestCaseVersion(userEmail, apiToken, jiraInstanceUrl, request)` - Create a new test case version
348
+ - `createTestCaseComment(userEmail, apiToken, jiraInstanceUrl, request)` - Create a comment on a test case
349
+ - `getTestCaseAttachments(userEmail, apiToken, jiraInstanceUrl, request)` - Get all attachments for a test case
350
+ - `downloadAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Download an attachment file into memory
351
+ - `createAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Upload an attachment to a test case
352
+
334
353
  ## Authentication
335
354
 
336
355
  ### Using ScriptRunner Connect API Connection (Recommended)
@@ -370,6 +389,253 @@ const apiEU = Zephyr.createZephyrApi(
370
389
  );
371
390
  ```
372
391
 
392
+ ## Private API ⚠️
393
+
394
+ > **⚠️ WARNING: Private API Usage**
395
+ >
396
+ > The Private API methods use Zephyr's private/unofficial endpoints that are not officially supported by SmartBear. These endpoints may change or be removed at any time without notice and are not covered by Standard Support. Use these methods at your own risk.
397
+
398
+ The Private API group provides access to functionality not available in the public Zephyr API, such as creating custom fields and test case versions. These methods require Jira user credentials (email and API token) rather than OAuth tokens.
399
+
400
+ ### Authentication
401
+
402
+ Private API methods use Jira Basic Authentication (email + API token) to retrieve a Context JWT token, which is then used to authenticate with Zephyr's private endpoints.
403
+
404
+ ### Get Context JWT
405
+
406
+ The Context JWT is a short-lived token (15 minutes) required for all private API calls:
407
+
408
+ ```typescript
409
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
410
+ import ZephyrApiConnection from '../api/zephyr';
411
+
412
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
413
+
414
+ // Get Context JWT token
415
+ const contextJwt = await api.Private.getContextJwt(
416
+ 'user@example.com',
417
+ 'jira-api-token',
418
+ 'https://your-instance.atlassian.net'
419
+ );
420
+ ```
421
+
422
+ ### Create Custom Fields
423
+
424
+ Create custom fields for test cases, test plans, test runs, or test steps:
425
+
426
+ ```typescript
427
+ // Create a basic custom field for test cases
428
+ const customField = await api.Private.createCustomField(
429
+ 'user@example.com',
430
+ 'jira-api-token',
431
+ 'https://your-instance.atlassian.net',
432
+ 'TEST_CASE', // Category: TEST_CASE, TEST_PLAN, TEST_RUN, or TEST_STEP
433
+ {
434
+ projectId: 10017,
435
+ name: 'Build Number',
436
+ type: 'SINGLE_LINE_TEXT', // CHECKBOX, NUMBER, DECIMAL, SINGLE_LINE_TEXT, MULTI_LINE_TEXT, SINGLE_CHOICE_SELECT_LIST, MULTI_CHOICE_SELECT_LIST, USER_LIST, DATE
437
+ required: false,
438
+ index: 4,
439
+ category: 'TEST_CASE',
440
+ options: [], // Only for SINGLE_CHOICE_SELECT_LIST or MULTI_CHOICE_SELECT_LIST
441
+ archived: false
442
+ }
443
+ );
444
+
445
+ // Create a custom field with options (select list)
446
+ const selectField = await api.Private.createCustomField(
447
+ 'user@example.com',
448
+ 'jira-api-token',
449
+ 'https://your-instance.atlassian.net',
450
+ 'TEST_CASE',
451
+ {
452
+ projectId: 10017,
453
+ name: 'Test Category',
454
+ type: 'MULTI_CHOICE_SELECT_LIST',
455
+ required: false,
456
+ index: 5,
457
+ category: 'TEST_CASE',
458
+ options: [
459
+ { index: 1, name: 'Smoke', archived: false },
460
+ { index: 2, name: 'Regression', archived: false },
461
+ { index: 3, name: 'Performance', archived: false }
462
+ ],
463
+ archived: false
464
+ }
465
+ );
466
+ ```
467
+
468
+ **Available Custom Field Types:**
469
+ - `CHECKBOX` - Checkbox
470
+ - `NUMBER` - Number
471
+ - `DECIMAL` - Decimal number
472
+ - `SINGLE_LINE_TEXT` - Single-line text
473
+ - `MULTI_LINE_TEXT` - Multi-line text
474
+ - `SINGLE_CHOICE_SELECT_LIST` - Single-choice select list
475
+ - `MULTI_CHOICE_SELECT_LIST` - Multi-choice select list
476
+ - `USER_LIST` - User picker
477
+ - `DATE` - Date picker
478
+
479
+ **Available Categories:**
480
+ - `TEST_CASE` - Custom field for test cases
481
+ - `TEST_PLAN` - Custom field for test plans
482
+ - `TEST_RUN` - Custom field for test cycles (test runs)
483
+ - `TEST_STEP` - Custom field for test steps
484
+
485
+ ### Create Test Case Version
486
+
487
+ Create a new version of an existing test case. **Note:** When a new version is created, the `testCaseId` changes for that test case.
488
+
489
+ ```typescript
490
+ // Create a new version (test case ID is looked up automatically from key)
491
+ const newVersion = await api.Private.createTestCaseVersion(
492
+ 'user@example.com',
493
+ 'jira-api-token',
494
+ 'https://your-instance.atlassian.net',
495
+ {
496
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
497
+ projectId: 10017 // Numeric project ID
498
+ }
499
+ );
500
+ // Returns: { id: 286693656, key: "ZEP-T18" }
501
+ ```
502
+
503
+ **Important Notes:**
504
+ - The method accepts `testCaseKey` and automatically looks up the numeric ID
505
+ - The `projectId` must be numeric, not the project key
506
+ - If a new version already exists, the API will return a 409 Conflict error
507
+ - The test case ID changes after creating a new version
508
+
509
+ ### Create Test Case Comment
510
+
511
+ Add a comment to an existing test case.
512
+
513
+ ```typescript
514
+ const comment = await api.Private.createTestCaseComment(
515
+ 'user@example.com',
516
+ 'jira-api-token',
517
+ 'https://your-instance.atlassian.net',
518
+ {
519
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
520
+ projectId: 10233, // Numeric project ID
521
+ body: 'This is a test comment', // Comment text
522
+ createdBy: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
523
+ }
524
+ );
525
+ ```
526
+
527
+ ### Get Test Case Attachments
528
+
529
+ Retrieve all attachment details for a test case, including signed S3 URLs for downloading.
530
+
531
+ ```typescript
532
+ const attachments = await api.Private.getTestCaseAttachments(
533
+ 'user@example.com',
534
+ 'jira-api-token',
535
+ 'https://your-instance.atlassian.net',
536
+ {
537
+ testCaseKey: 'PROJ-T1',
538
+ projectId: 10233
539
+ }
540
+ );
541
+
542
+ console.log(`Found ${attachments.attachments.length} attachments`);
543
+ attachments.attachments.forEach(att => {
544
+ console.log(`- ${att.name} (${att.fileSize} bytes, ${att.mimeType})`);
545
+ console.log(` ID: ${att.id}`);
546
+ console.log(` URL: ${att.url}`);
547
+ });
548
+ ```
549
+
550
+ **Response Structure:**
551
+ Each attachment includes:
552
+ - `id` - Attachment UUID
553
+ - `name` - File name
554
+ - `mimeType` - MIME type (e.g., 'image/jpeg', 'application/pdf')
555
+ - `fileSize` - File size in bytes
556
+ - `url` - Signed S3 URL for downloading (expires after ~90 minutes)
557
+ - `createdOn` - Creation timestamp
558
+ - `userKey` - Atlassian account ID of the uploader
559
+ - `s3Key` - S3 storage key
560
+
561
+ ### Download Attachment
562
+
563
+ Download an attachment file into memory. This method automatically gets a fresh signed URL and downloads the file.
564
+
565
+ ```typescript
566
+ const fileBlob = await api.Private.downloadAttachment(
567
+ 'user@example.com',
568
+ 'jira-api-token',
569
+ 'https://your-instance.atlassian.net',
570
+ {
571
+ testCaseKey: 'PROJ-T1',
572
+ projectId: 10233,
573
+ attachmentId: 'c3f14125-638f-47f9-9211-12a9777c09e7' // Attachment UUID
574
+ }
575
+ );
576
+
577
+ // Use the blob (e.g., save to Record Storage, upload elsewhere, etc.)
578
+ console.log(`Downloaded file: ${fileBlob.size} bytes, type: ${fileBlob.type}`);
579
+
580
+ // Example: Convert to ArrayBuffer if needed
581
+ const arrayBuffer = await fileBlob.arrayBuffer();
582
+ ```
583
+
584
+ **Important Notes:**
585
+ - The method automatically gets a fresh signed URL to ensure it hasn't expired
586
+ - Returns a `Blob` object that can be used directly or converted to `ArrayBuffer`
587
+ - The signed URLs from `getTestCaseAttachments` expire after ~90 minutes, but `downloadAttachment` always gets a fresh URL
588
+
589
+ ### Upload Attachment
590
+
591
+ Upload a file attachment to a test case.
592
+
593
+ ```typescript
594
+ const file = new Blob(['file content'], { type: 'text/plain' });
595
+
596
+ const attachment = await api.Private.createAttachment(
597
+ 'user@example.com',
598
+ 'jira-api-token',
599
+ 'https://your-instance.atlassian.net',
600
+ {
601
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
602
+ projectId: 10233, // Numeric project ID
603
+ file: file, // Blob or ArrayBuffer
604
+ fileName: 'test-file.txt',
605
+ userAccountId: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
606
+ }
607
+ );
608
+ ```
609
+
610
+ **Important Notes:**
611
+ - The method handles the complete upload flow: getting S3 credentials, uploading to S3, and saving metadata
612
+ - Supports both `Blob` and `ArrayBuffer` file types
613
+ - MIME type is automatically detected from file name extension
614
+
615
+ ### Error Handling for Private API
616
+
617
+ Private API methods use the same error types as the public API:
618
+
619
+ ```typescript
620
+ try {
621
+ await api.Private.createCustomField(...);
622
+ } catch (error) {
623
+ if (error instanceof Zephyr.BadRequestError) {
624
+ console.log('Invalid request parameters');
625
+ } else if (error instanceof Zephyr.UnauthorizedError) {
626
+ console.log('Authentication failed - check your credentials');
627
+ } else if (error instanceof Zephyr.ForbiddenError) {
628
+ console.log('Insufficient permissions');
629
+ } else if (error instanceof Zephyr.NotFoundError) {
630
+ console.log('Resource not found');
631
+ } else if (error instanceof Zephyr.ServerError) {
632
+ if (error.status === 409) {
633
+ console.log('Conflict - version already exists');
634
+ }
635
+ }
636
+ }
637
+ ```
638
+
373
639
  ## Custom Fields
374
640
 
375
641
  Custom fields are supported as flexible key-value pairs:
@@ -677,6 +943,20 @@ For issues, questions, or contributions, please refer to the project repository
677
943
 
678
944
  ## Changelog
679
945
 
946
+ ### 1.1.0
947
+
948
+ - **Added**: Private API group with support for unofficial Zephyr endpoints
949
+ - `getContextJwt()` - Retrieve Jira Context JWT token for private API authentication
950
+ - `createCustomField()` - Create custom fields for test cases, test plans, test runs, and test steps
951
+ - `createTestCaseVersion()` - Create new test case versions (now accepts testCaseKey and looks up ID automatically)
952
+ - `createTestCaseComment()` - Create comments on test cases
953
+ - `getTestCaseAttachments()` - Get all attachment details for a test case
954
+ - `downloadAttachment()` - Download attachment files into memory with automatic fresh URL retrieval
955
+ - `createAttachment()` - Upload file attachments to test cases
956
+ - **Added**: Type definitions for private API requests and responses
957
+ - **Changed**: `createTestCaseVersion()` now uses interface structure and automatically looks up test case ID from key
958
+ - **Warning**: Private API methods are not officially supported and may change without notice
959
+
680
960
  ### 1.0.1
681
961
 
682
962
  - **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation
package/dist/README.md CHANGED
@@ -331,6 +331,25 @@ The Managed API is organized into the following groups:
331
331
  - `createJUnitExecutions(request)` - Upload JUnit XML results
332
332
  - `retrieveBDDTestCases(options)` - Retrieve BDD feature files
333
333
 
334
+ ### Private API ⚠️
335
+ > **⚠️ WARNING: Private API Methods**
336
+ >
337
+ > The following methods use Zephyr's private/unofficial API endpoints that are:
338
+ > - **Not officially supported** by SmartBear
339
+ > - **Not part of the public API documentation**
340
+ > - **Subject to change at any time** without notice
341
+ > - **Not covered by Standard Support**
342
+ >
343
+ > Use these methods at your own risk. They may break with future Zephyr updates.
344
+
345
+ - `getContextJwt(userEmail, apiToken, jiraInstanceUrl)` - Get Jira Context JWT token (required for private API calls)
346
+ - `createCustomField(userEmail, apiToken, jiraInstanceUrl, category, request)` - Create custom fields for test cases, test plans, test runs, or test steps
347
+ - `createTestCaseVersion(userEmail, apiToken, jiraInstanceUrl, request)` - Create a new test case version
348
+ - `createTestCaseComment(userEmail, apiToken, jiraInstanceUrl, request)` - Create a comment on a test case
349
+ - `getTestCaseAttachments(userEmail, apiToken, jiraInstanceUrl, request)` - Get all attachments for a test case
350
+ - `downloadAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Download an attachment file into memory
351
+ - `createAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Upload an attachment to a test case
352
+
334
353
  ## Authentication
335
354
 
336
355
  ### Using ScriptRunner Connect API Connection (Recommended)
@@ -370,6 +389,253 @@ const apiEU = Zephyr.createZephyrApi(
370
389
  );
371
390
  ```
372
391
 
392
+ ## Private API ⚠️
393
+
394
+ > **⚠️ WARNING: Private API Usage**
395
+ >
396
+ > The Private API methods use Zephyr's private/unofficial endpoints that are not officially supported by SmartBear. These endpoints may change or be removed at any time without notice and are not covered by Standard Support. Use these methods at your own risk.
397
+
398
+ The Private API group provides access to functionality not available in the public Zephyr API, such as creating custom fields and test case versions. These methods require Jira user credentials (email and API token) rather than OAuth tokens.
399
+
400
+ ### Authentication
401
+
402
+ Private API methods use Jira Basic Authentication (email + API token) to retrieve a Context JWT token, which is then used to authenticate with Zephyr's private endpoints.
403
+
404
+ ### Get Context JWT
405
+
406
+ The Context JWT is a short-lived token (15 minutes) required for all private API calls:
407
+
408
+ ```typescript
409
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
410
+ import ZephyrApiConnection from '../api/zephyr';
411
+
412
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
413
+
414
+ // Get Context JWT token
415
+ const contextJwt = await api.Private.getContextJwt(
416
+ 'user@example.com',
417
+ 'jira-api-token',
418
+ 'https://your-instance.atlassian.net'
419
+ );
420
+ ```
421
+
422
+ ### Create Custom Fields
423
+
424
+ Create custom fields for test cases, test plans, test runs, or test steps:
425
+
426
+ ```typescript
427
+ // Create a basic custom field for test cases
428
+ const customField = await api.Private.createCustomField(
429
+ 'user@example.com',
430
+ 'jira-api-token',
431
+ 'https://your-instance.atlassian.net',
432
+ 'TEST_CASE', // Category: TEST_CASE, TEST_PLAN, TEST_RUN, or TEST_STEP
433
+ {
434
+ projectId: 10017,
435
+ name: 'Build Number',
436
+ type: 'SINGLE_LINE_TEXT', // CHECKBOX, NUMBER, DECIMAL, SINGLE_LINE_TEXT, MULTI_LINE_TEXT, SINGLE_CHOICE_SELECT_LIST, MULTI_CHOICE_SELECT_LIST, USER_LIST, DATE
437
+ required: false,
438
+ index: 4,
439
+ category: 'TEST_CASE',
440
+ options: [], // Only for SINGLE_CHOICE_SELECT_LIST or MULTI_CHOICE_SELECT_LIST
441
+ archived: false
442
+ }
443
+ );
444
+
445
+ // Create a custom field with options (select list)
446
+ const selectField = await api.Private.createCustomField(
447
+ 'user@example.com',
448
+ 'jira-api-token',
449
+ 'https://your-instance.atlassian.net',
450
+ 'TEST_CASE',
451
+ {
452
+ projectId: 10017,
453
+ name: 'Test Category',
454
+ type: 'MULTI_CHOICE_SELECT_LIST',
455
+ required: false,
456
+ index: 5,
457
+ category: 'TEST_CASE',
458
+ options: [
459
+ { index: 1, name: 'Smoke', archived: false },
460
+ { index: 2, name: 'Regression', archived: false },
461
+ { index: 3, name: 'Performance', archived: false }
462
+ ],
463
+ archived: false
464
+ }
465
+ );
466
+ ```
467
+
468
+ **Available Custom Field Types:**
469
+ - `CHECKBOX` - Checkbox
470
+ - `NUMBER` - Number
471
+ - `DECIMAL` - Decimal number
472
+ - `SINGLE_LINE_TEXT` - Single-line text
473
+ - `MULTI_LINE_TEXT` - Multi-line text
474
+ - `SINGLE_CHOICE_SELECT_LIST` - Single-choice select list
475
+ - `MULTI_CHOICE_SELECT_LIST` - Multi-choice select list
476
+ - `USER_LIST` - User picker
477
+ - `DATE` - Date picker
478
+
479
+ **Available Categories:**
480
+ - `TEST_CASE` - Custom field for test cases
481
+ - `TEST_PLAN` - Custom field for test plans
482
+ - `TEST_RUN` - Custom field for test cycles (test runs)
483
+ - `TEST_STEP` - Custom field for test steps
484
+
485
+ ### Create Test Case Version
486
+
487
+ Create a new version of an existing test case. **Note:** When a new version is created, the `testCaseId` changes for that test case.
488
+
489
+ ```typescript
490
+ // Create a new version (test case ID is looked up automatically from key)
491
+ const newVersion = await api.Private.createTestCaseVersion(
492
+ 'user@example.com',
493
+ 'jira-api-token',
494
+ 'https://your-instance.atlassian.net',
495
+ {
496
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
497
+ projectId: 10017 // Numeric project ID
498
+ }
499
+ );
500
+ // Returns: { id: 286693656, key: "ZEP-T18" }
501
+ ```
502
+
503
+ **Important Notes:**
504
+ - The method accepts `testCaseKey` and automatically looks up the numeric ID
505
+ - The `projectId` must be numeric, not the project key
506
+ - If a new version already exists, the API will return a 409 Conflict error
507
+ - The test case ID changes after creating a new version
508
+
509
+ ### Create Test Case Comment
510
+
511
+ Add a comment to an existing test case.
512
+
513
+ ```typescript
514
+ const comment = await api.Private.createTestCaseComment(
515
+ 'user@example.com',
516
+ 'jira-api-token',
517
+ 'https://your-instance.atlassian.net',
518
+ {
519
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
520
+ projectId: 10233, // Numeric project ID
521
+ body: 'This is a test comment', // Comment text
522
+ createdBy: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
523
+ }
524
+ );
525
+ ```
526
+
527
+ ### Get Test Case Attachments
528
+
529
+ Retrieve all attachment details for a test case, including signed S3 URLs for downloading.
530
+
531
+ ```typescript
532
+ const attachments = await api.Private.getTestCaseAttachments(
533
+ 'user@example.com',
534
+ 'jira-api-token',
535
+ 'https://your-instance.atlassian.net',
536
+ {
537
+ testCaseKey: 'PROJ-T1',
538
+ projectId: 10233
539
+ }
540
+ );
541
+
542
+ console.log(`Found ${attachments.attachments.length} attachments`);
543
+ attachments.attachments.forEach(att => {
544
+ console.log(`- ${att.name} (${att.fileSize} bytes, ${att.mimeType})`);
545
+ console.log(` ID: ${att.id}`);
546
+ console.log(` URL: ${att.url}`);
547
+ });
548
+ ```
549
+
550
+ **Response Structure:**
551
+ Each attachment includes:
552
+ - `id` - Attachment UUID
553
+ - `name` - File name
554
+ - `mimeType` - MIME type (e.g., 'image/jpeg', 'application/pdf')
555
+ - `fileSize` - File size in bytes
556
+ - `url` - Signed S3 URL for downloading (expires after ~90 minutes)
557
+ - `createdOn` - Creation timestamp
558
+ - `userKey` - Atlassian account ID of the uploader
559
+ - `s3Key` - S3 storage key
560
+
561
+ ### Download Attachment
562
+
563
+ Download an attachment file into memory. This method automatically gets a fresh signed URL and downloads the file.
564
+
565
+ ```typescript
566
+ const fileBlob = await api.Private.downloadAttachment(
567
+ 'user@example.com',
568
+ 'jira-api-token',
569
+ 'https://your-instance.atlassian.net',
570
+ {
571
+ testCaseKey: 'PROJ-T1',
572
+ projectId: 10233,
573
+ attachmentId: 'c3f14125-638f-47f9-9211-12a9777c09e7' // Attachment UUID
574
+ }
575
+ );
576
+
577
+ // Use the blob (e.g., save to Record Storage, upload elsewhere, etc.)
578
+ console.log(`Downloaded file: ${fileBlob.size} bytes, type: ${fileBlob.type}`);
579
+
580
+ // Example: Convert to ArrayBuffer if needed
581
+ const arrayBuffer = await fileBlob.arrayBuffer();
582
+ ```
583
+
584
+ **Important Notes:**
585
+ - The method automatically gets a fresh signed URL to ensure it hasn't expired
586
+ - Returns a `Blob` object that can be used directly or converted to `ArrayBuffer`
587
+ - The signed URLs from `getTestCaseAttachments` expire after ~90 minutes, but `downloadAttachment` always gets a fresh URL
588
+
589
+ ### Upload Attachment
590
+
591
+ Upload a file attachment to a test case.
592
+
593
+ ```typescript
594
+ const file = new Blob(['file content'], { type: 'text/plain' });
595
+
596
+ const attachment = await api.Private.createAttachment(
597
+ 'user@example.com',
598
+ 'jira-api-token',
599
+ 'https://your-instance.atlassian.net',
600
+ {
601
+ testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
602
+ projectId: 10233, // Numeric project ID
603
+ file: file, // Blob or ArrayBuffer
604
+ fileName: 'test-file.txt',
605
+ userAccountId: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
606
+ }
607
+ );
608
+ ```
609
+
610
+ **Important Notes:**
611
+ - The method handles the complete upload flow: getting S3 credentials, uploading to S3, and saving metadata
612
+ - Supports both `Blob` and `ArrayBuffer` file types
613
+ - MIME type is automatically detected from file name extension
614
+
615
+ ### Error Handling for Private API
616
+
617
+ Private API methods use the same error types as the public API:
618
+
619
+ ```typescript
620
+ try {
621
+ await api.Private.createCustomField(...);
622
+ } catch (error) {
623
+ if (error instanceof Zephyr.BadRequestError) {
624
+ console.log('Invalid request parameters');
625
+ } else if (error instanceof Zephyr.UnauthorizedError) {
626
+ console.log('Authentication failed - check your credentials');
627
+ } else if (error instanceof Zephyr.ForbiddenError) {
628
+ console.log('Insufficient permissions');
629
+ } else if (error instanceof Zephyr.NotFoundError) {
630
+ console.log('Resource not found');
631
+ } else if (error instanceof Zephyr.ServerError) {
632
+ if (error.status === 409) {
633
+ console.log('Conflict - version already exists');
634
+ }
635
+ }
636
+ }
637
+ ```
638
+
373
639
  ## Custom Fields
374
640
 
375
641
  Custom fields are supported as flexible key-value pairs:
@@ -677,6 +943,20 @@ For issues, questions, or contributions, please refer to the project repository
677
943
 
678
944
  ## Changelog
679
945
 
946
+ ### 1.1.0
947
+
948
+ - **Added**: Private API group with support for unofficial Zephyr endpoints
949
+ - `getContextJwt()` - Retrieve Jira Context JWT token for private API authentication
950
+ - `createCustomField()` - Create custom fields for test cases, test plans, test runs, and test steps
951
+ - `createTestCaseVersion()` - Create new test case versions (now accepts testCaseKey and looks up ID automatically)
952
+ - `createTestCaseComment()` - Create comments on test cases
953
+ - `getTestCaseAttachments()` - Get all attachment details for a test case
954
+ - `downloadAttachment()` - Download attachment files into memory with automatic fresh URL retrieval
955
+ - `createAttachment()` - Upload file attachments to test cases
956
+ - **Added**: Type definitions for private API requests and responses
957
+ - **Changed**: `createTestCaseVersion()` now uses interface structure and automatically looks up test case ID from key
958
+ - **Warning**: Private API methods are not officially supported and may change without notice
959
+
680
960
  ### 1.0.1
681
961
 
682
962
  - **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation