@healthcloudai/hc-settings-connector 0.0.5 → 0.0.8

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
@@ -1,24 +1,22 @@
1
1
  # Healthcheck Settings Connector
2
2
 
3
- This library provides a client for accessing **user settings and profile-related data**
4
- from the Healthcheck API.
3
+ This library provides a client for authenticated user settings, profile image,
4
+ identification, insurance, and dashboard-related flows in Healthcheck.
5
5
  It is built on top of the shared Healthcheck HTTP and Login connectors.
6
+
6
7
  ---
7
8
 
8
9
  ## Features
9
- 1. Retrieve patient dashboard data
10
- 2. Generate a pre-signed URL for user selfie upload
11
- 3. Capture user selfie from uploaded file key
12
- 4. Generate a pre-signed URL for driving license / ID upload
13
- 5. Capture driving license / ID data from uploaded file key
14
- 6. Submit driving license / ID data
15
- 7. Generate a pre-signed URL for insurance upload
16
- 8. Capture insurance data from uploaded file key
17
- 9. Submit user insurance
18
- 10. Retrieve patient insurances
19
- 11. Update user profile image URL
20
- 12. Self deactivate user
21
- 13. Built on shared Healthcheck HttpClient and authentication layer
10
+ 1. Retrieve the authenticated patient profile
11
+ 2. Retrieve the authenticated patient dashboard
12
+ 3. Generate canned upload URLs for selfie, ID, and insurance images
13
+ 4. Capture selfie, identification, and insurance documents from uploaded file keys
14
+ 5. Update or submit driving license data through the resolved EHR route
15
+ 6. Submit patient insurance coverage details
16
+ 7. Retrieve patient insurances through the resolved EHR route
17
+ 8. Update the stored user image file reference
18
+ 9. Deactivate the authenticated user
19
+ 10. Built on the shared Healthcheck HttpClient and authentication layer
22
20
 
23
21
  ---
24
22
 
@@ -50,8 +48,8 @@ import { FetchClient } from "@healthcloudai/hc-http";
50
48
  const httpClient = new FetchClient();
51
49
  const authClient = new HCLoginClient(httpClient);
52
50
 
53
- authClient.configure("tenant-id", "dev");
54
- await authClient.login("john.doe@test.com", "password");
51
+ authClient.configure("demo-tenant", "dev");
52
+ await authClient.login("john.doe@example.com", "ExamplePassword123!");
55
53
 
56
54
  const settingsClient = new HCSettingsClient(
57
55
  httpClient,
@@ -67,24 +65,120 @@ const settingsClient = new HCSettingsClient(
67
65
 
68
66
  Public signature: `settingsClient.getUserInfo()`
69
67
 
70
- Returns the current patient profile data.
68
+ Returns the current authenticated patient profile.
71
69
 
72
70
  ```ts
73
71
  const userInfo = await settingsClient.getUserInfo();
74
72
  ```
75
73
 
74
+ #### Full API request
75
+
76
+ This method performs an authenticated request internally and does not send a request body.
77
+
78
+ #### API response
79
+
80
+ Status:
81
+
82
+ ```txt
83
+ 200
84
+ ```
85
+
86
+ ```json
87
+ {
88
+ "Data": {
89
+ "Record": {
90
+ "ID": "record-id-example",
91
+ "TenantID": "demo-tenant",
92
+ "FirstName": "John",
93
+ "LastName": "Doe",
94
+ "Email": "john.doe@example.com",
95
+ "Phone": null,
96
+ "BirthDate": "0001-01-01T00:00:00",
97
+ "HasInsurance": false,
98
+ "HasIDCard": false,
99
+ "HasSelfie": true,
100
+ "Address": {
101
+ "StreetAndNumber": null,
102
+ "Extension": null,
103
+ "City": null,
104
+ "State": null,
105
+ "PostalCode": null,
106
+ "Country": null
107
+ },
108
+ "Attributes": {
109
+ "FHIRPatientID": "patient-id-example",
110
+ "CompositeID": "composite-id-example",
111
+ "PatientImageURL": "https://storage.example.com/selfie_example.jpeg"
112
+ },
113
+ "CompositeID": "composite-id-example",
114
+ "FHIRID": "fhir-id-example"
115
+ },
116
+ "Encounters": null,
117
+ "EHR": "fhir",
118
+ "PendingActions": [
119
+ "ADD_ID",
120
+ "IMPORT_VITALS"
121
+ ]
122
+ },
123
+ "ErrorMessage": null,
124
+ "IsOK": true
125
+ }
126
+ ```
127
+
76
128
  ---
77
129
 
78
130
  ### Get Dashboard
79
131
 
80
132
  Public signature: `settingsClient.getDashboard()`
81
133
 
82
- Returns the current patient dashboard response.
134
+ Returns the current authenticated patient dashboard response.
83
135
 
84
136
  ```ts
85
137
  const dashboard = await settingsClient.getDashboard();
86
138
  ```
87
139
 
140
+ #### Full API request
141
+
142
+ This method performs an authenticated request internally and does not send a request body.
143
+
144
+ #### API response
145
+
146
+ Status:
147
+
148
+ ```txt
149
+ 200
150
+ ```
151
+
152
+ ```json
153
+ {
154
+ "Data": {
155
+ "Record": {
156
+ "ID": "record-id-example",
157
+ "TenantID": "demo-tenant",
158
+ "FirstName": "John",
159
+ "LastName": "Doe",
160
+ "Email": "john.doe@example.com",
161
+ "HasInsurance": false,
162
+ "HasIDCard": false,
163
+ "HasSelfie": true,
164
+ "Attributes": {
165
+ "FHIRPatientID": "patient-id-example",
166
+ "CompositeID": "composite-id-example",
167
+ "PatientImageURL": "https://storage.example.com/selfie_example.jpeg"
168
+ }
169
+ },
170
+ "Encounters": [],
171
+ "EHR": "fhir",
172
+ "PendingActions": [
173
+ "ADD_ID",
174
+ "IMPORT_VITALS"
175
+ ]
176
+ },
177
+ "ErrorMessage": null,
178
+ "IsOK": true
179
+ }
180
+ ```
181
+
88
182
  ---
89
183
 
90
184
  ### Submit Insurance
@@ -92,162 +186,563 @@ const dashboard = await settingsClient.getDashboard();
92
186
  Public signature: `settingsClient.submitInsurance(payload)`
93
187
 
94
188
  Submits patient insurance coverage details.
189
+ The client forwards the provided payload into the backend `Data` wrapper.
95
190
 
96
191
  ```ts
97
192
  await settingsClient.submitInsurance({
98
193
  InsurancePackageId: "693245",
99
- MemberId: "096304628",
194
+ MemberId: "member-id-example",
100
195
  FirstName: "John",
101
- LastName: "Smith",
196
+ LastName: "Doe",
102
197
  Sex: "",
103
- Image: "1765886686136.png"
198
+ Image: "insurancecard_example.jpeg"
104
199
  });
105
200
  ```
106
201
 
202
+ #### Full API request
203
+
204
+ ```json
205
+ {
206
+ "Data": {
207
+ "InsurancePackageId": "693245",
208
+ "MemberId": "member-id-example",
209
+ "FirstName": "John",
210
+ "LastName": "Doe",
211
+ "Sex": "",
212
+ "Image": "insurancecard_example.jpeg"
213
+ }
214
+ }
215
+ ```
216
+
217
+ #### API response
218
+
219
+ Status:
220
+
221
+ ```txt
222
+ 200
223
+ ```
224
+
225
+ ```json
226
+ {
227
+ "Data": {
228
+ "InsuranceId": "insurance-id-example",
229
+ "InsurancePackageId": 693245,
230
+ "InsurancePolicyHolder": "John Doe",
231
+ "InsuranceType": "Insurance",
232
+ "IssueDate": "01/01/2030",
233
+ "MemberId": "member-id-example",
234
+ "Image": "insurancecard_example.jpeg"
235
+ },
236
+ "ErrorMessage": null,
237
+ "IsOK": true
238
+ }
239
+ ```
240
+
241
+ ---
242
+
107
243
  ### Get User Image Canned URL
108
244
 
109
245
  Public signature: `settingsClient.getUserImageCannedUrl(extension)`
110
246
 
111
- Generates a pre-signed upload URL for a user selfie file.
247
+ Generates a canned upload URL for a user selfie file.
248
+ The connector returns the raw backend response object for the generated file.
249
+ The package does not upload the file bytes for you.
250
+ When you upload to the returned S3 URL, you must preserve any signed headers that the URL expects.
251
+ In live verification, uploads succeeded only when the S3 request included `x-amz-acl: public-read`.
112
252
 
113
253
  ```ts
114
- const selfieUpload = await settingsClient.getUserImageCannedUrl("jpg");
254
+ const selfieUpload = await settingsClient.getUserImageCannedUrl("jpeg");
255
+ ```
256
+
257
+ #### Full API request
258
+
259
+ ```json
260
+ {
261
+ "Data": {
262
+ "Extension": "jpeg"
263
+ }
264
+ }
115
265
  ```
116
266
 
267
+ #### API response
268
+
269
+ Status:
270
+
271
+ ```txt
272
+ 200
273
+ ```
274
+
275
+ ```json
276
+ {
277
+ "ImageURL": "https://storage.example.com/selfie_example.jpeg?signature=example",
278
+ "FileName": "selfie_example.jpeg",
279
+ "Extension": "jpeg"
280
+ }
281
+ ```
282
+
283
+ ---
284
+
117
285
  ### Capture User Photo
118
286
 
119
287
  Public signature: `settingsClient.captureUserPhoto(fileKey)`
120
288
 
121
- Captures a user selfie through `POST /patient/capture`.
122
- The client internally sends `Type: "userphoto"` and `FileID: fileKey`.
289
+ Convenience wrapper around the patient capture endpoint.
290
+ The client sends `Type: "userphoto"` and the uploaded file key inside the backend `Data` wrapper.
291
+ This method expects the file to have already been uploaded to the canned URL returned by `getUserImageCannedUrl(...)`.
292
+ If the canned URL requires signed S3 headers, the upload must include them before capture can succeed.
123
293
 
124
294
  ```ts
125
295
  const capturedSelfie = await settingsClient.captureUserPhoto(
126
- "selfie_639064123637965380.jpg"
296
+ "selfie_example.jpeg"
127
297
  );
128
298
  ```
129
299
 
300
+ #### Full API request
301
+
302
+ ```json
303
+ {
304
+ "Data": {
305
+ "Type": "userphoto",
306
+ "FileID": "selfie_example.jpeg"
307
+ }
308
+ }
309
+ ```
310
+
311
+ #### API response
312
+
313
+ Direct success response for a selfie image was not verified in the latest live run.
314
+ The same upload prerequisite applies here as for the ID and insurance flows: the file must exist at the canned URL upload target, and any signed S3 headers such as `x-amz-acl: public-read` must be preserved during upload.
315
+
316
+ ---
317
+
130
318
  ### Get Driving License Canned URL
131
319
 
132
320
  Public signature: `settingsClient.getDrivingLicenseCannedUrl(extension)`
133
321
 
134
- Generates a pre-signed upload URL for a driving license / ID file.
322
+ Generates a canned upload URL for a driving license or identification file.
323
+ The package does not upload the file bytes for you.
324
+ When you upload to the returned S3 URL, you must preserve any signed headers that the URL expects.
325
+ In live verification, uploads succeeded only when the S3 request included `x-amz-acl: public-read`.
135
326
 
136
327
  ```ts
137
- const idUpload = await settingsClient.getDrivingLicenseCannedUrl("jpg");
328
+ const idUpload = await settingsClient.getDrivingLicenseCannedUrl("jpeg");
329
+ ```
330
+
331
+ #### Full API request
332
+
333
+ ```json
334
+ {
335
+ "Data": {
336
+ "Extension": "jpeg"
337
+ }
338
+ }
339
+ ```
340
+
341
+ #### API response
342
+
343
+ Status:
344
+
345
+ ```txt
346
+ 200
347
+ ```
348
+
349
+ ```json
350
+ {
351
+ "ImageURL": "https://storage.example.com/idcard_example.jpeg?signature=example",
352
+ "FileName": "idcard_example.jpeg",
353
+ "Extension": "jpeg"
354
+ }
138
355
  ```
139
356
 
357
+ ---
358
+
140
359
  ### Capture Driving License
141
360
 
142
361
  Public signature: `settingsClient.captureDrivingLicense(fileKey)`
143
362
 
144
- Captures and extracts patient identification data through `POST /patient/capture`.
145
- The client internally sends `Type: "identification"` and `FileID: fileKey`.
363
+ Convenience wrapper around the patient capture endpoint.
364
+ The client sends `Type: "identification"` and the uploaded file key inside the backend `Data` wrapper.
365
+ This method expects the file to have already been uploaded to the canned URL returned by `getDrivingLicenseCannedUrl(...)`.
146
366
 
147
367
  ```ts
148
368
  const capturedLicense = await settingsClient.captureDrivingLicense(
149
- "idcard_639064123637965380.jpg"
369
+ "idcard_example.jpeg"
150
370
  );
151
371
  ```
152
372
 
373
+ #### Full API request
374
+
375
+ ```json
376
+ {
377
+ "Data": {
378
+ "Type": "identification",
379
+ "FileID": "idcard_example.jpeg"
380
+ }
381
+ }
382
+ ```
383
+
384
+ #### API response
385
+
386
+ Status:
387
+
388
+ ```txt
389
+ 200
390
+ ```
391
+
392
+ ```json
393
+ {
394
+ "Data": {
395
+ "CapturedData": {
396
+ "FirstName": "John",
397
+ "LastName": "Doe",
398
+ "StreetAddress": "123 Main St",
399
+ "City": "Springfield",
400
+ "ZipCode": "90210",
401
+ "State": "California",
402
+ "IssuedDate": "01/01/2024",
403
+ "ExpiresDate": "01/01/2028",
404
+ "Dob": "01/01/1990",
405
+ "IDNumber": null
406
+ },
407
+ "IsCaptured": true,
408
+ "InsurancePackages": null
409
+ },
410
+ "ErrorMessage": null,
411
+ "IsOK": true
412
+ }
413
+ ```
414
+
415
+ ---
416
+
153
417
  ### Update Driving License
154
418
 
155
419
  Public signature: `settingsClient.updateDrivingLicense(payload)`
156
420
 
157
- Updates patient driving license data through the wrapper-backed EHR route.
158
- The client resolves the current patient's `EHR` internally from `authClient.getUserInfo()`
159
- and sends the payload inside the backend `Data` wrapper.
160
- `Image` should be the uploaded file key / path, not a raw file.
421
+ Updates patient driving license data through the EHR-backed route.
422
+ The client resolves the current `EHR` internally from `authClient.getUserInfo()` and sends the payload inside the backend `Data` wrapper.
161
423
 
162
424
  ```ts
163
425
  const response = await settingsClient.updateDrivingLicense({
164
- Image: "idcard_639064123637965380.jpg"
426
+ Image: "idcard_example.jpeg"
165
427
  });
166
428
  ```
167
429
 
430
+ #### Full API request
431
+
432
+ ```json
433
+ {
434
+ "Data": {
435
+ "Image": "idcard_example.jpeg"
436
+ }
437
+ }
438
+ ```
439
+
440
+ #### API response
441
+
442
+ Status:
443
+
444
+ ```txt
445
+ 200
446
+ ```
447
+
448
+ ```json
449
+ {
450
+ "Data": "true",
451
+ "ErrorMessage": null,
452
+ "IsOK": true
453
+ }
454
+ ```
455
+
456
+ `Data` was observed as the string `"true"` in the live test environment after a successful upload and capture flow.
457
+
168
458
  `submitDrivingLicense(payload)` is still available as a backward-compatible alias.
169
459
 
460
+ ---
461
+
462
+ ### Submit Driving License
463
+
464
+ Public signature: `settingsClient.submitDrivingLicense(payload)`
465
+
466
+ Backward-compatible alias for `updateDrivingLicense(payload)`.
467
+ It sends the same request payload and currently calls the same implementation internally.
468
+
469
+ ```ts
470
+ const response = await settingsClient.submitDrivingLicense({
471
+ Image: "idcard_example.jpeg"
472
+ });
473
+ ```
474
+
475
+ #### Full API request
476
+
477
+ ```json
478
+ {
479
+ "Data": {
480
+ "Image": "idcard_example.jpeg"
481
+ }
482
+ }
483
+ ```
484
+
485
+ #### API response
486
+
487
+ Status:
488
+
489
+ ```txt
490
+ 200
491
+ ```
492
+
493
+ ```json
494
+ {
495
+ "Data": "true",
496
+ "ErrorMessage": null,
497
+ "IsOK": true
498
+ }
499
+ ```
500
+
501
+ ---
502
+
170
503
  ### Get Insurance Canned URL
171
504
 
172
505
  Public signature: `settingsClient.getInsuranceCannedUrl(extension)`
173
506
 
174
- Generates a pre-signed upload URL for an insurance file.
507
+ Generates a canned upload URL for an insurance file.
508
+ The package does not upload the file bytes for you.
509
+ When you upload to the returned S3 URL, you must preserve any signed headers that the URL expects.
510
+ In live verification, uploads succeeded only when the S3 request included `x-amz-acl: public-read`.
175
511
 
176
512
  ```ts
177
- const insuranceUpload = await settingsClient.getInsuranceCannedUrl("jpg");
513
+ const insuranceUpload = await settingsClient.getInsuranceCannedUrl("jpeg");
178
514
  ```
179
515
 
516
+ #### Full API request
517
+
518
+ ```json
519
+ {
520
+ "Data": {
521
+ "Extension": "jpeg"
522
+ }
523
+ }
524
+ ```
525
+
526
+ #### API response
527
+
528
+ Status:
529
+
530
+ ```txt
531
+ 200
532
+ ```
533
+
534
+ ```json
535
+ {
536
+ "ImageURL": "https://storage.example.com/insurancecard_example.jpeg?signature=example",
537
+ "FileName": "insurancecard_example.jpeg",
538
+ "Extension": "jpeg"
539
+ }
540
+ ```
541
+
542
+ ---
543
+
180
544
  ### Capture Insurance
181
545
 
182
546
  Public signature: `settingsClient.captureInsurance(fileKey)`
183
547
 
184
- Captures and extracts insurance data through `POST /patient/capture`.
185
- The client internally sends `Type: "healthinsurance"` and `FileID: fileKey`.
548
+ Convenience wrapper around the patient capture endpoint.
549
+ The client sends `Type: "healthinsurance"` and the uploaded file key inside the backend `Data` wrapper.
550
+ This method expects the file to have already been uploaded to the canned URL returned by `getInsuranceCannedUrl(...)`.
186
551
 
187
552
  ```ts
188
553
  const capturedInsurance = await settingsClient.captureInsurance(
189
- "insurance_639064123637965380.jpg"
554
+ "insurancecard_example.jpeg"
190
555
  );
191
556
  ```
192
557
 
558
+ #### Full API request
559
+
560
+ ```json
561
+ {
562
+ "Data": {
563
+ "Type": "healthinsurance",
564
+ "FileID": "insurancecard_example.jpeg"
565
+ }
566
+ }
567
+ ```
568
+
569
+ #### API response
570
+
571
+ Status:
572
+
573
+ ```txt
574
+ 200
575
+ ```
576
+
577
+ ```json
578
+ {
579
+ "Data": {
580
+ "CapturedData": {
581
+ "FirstName": "John",
582
+ "LastName": "Doe",
583
+ "MemberId": "member-id-example",
584
+ "GroupNumber": "group-number-example",
585
+ "EffectiveDate": "",
586
+ "RxBIN": "",
587
+ "RxPCN": "",
588
+ "RxGRP": "",
589
+ "Carrier": "Carrier Example"
590
+ },
591
+ "IsCaptured": true,
592
+ "InsurancePackages": null
593
+ },
594
+ "ErrorMessage": null,
595
+ "IsOK": true
596
+ }
597
+ ```
598
+
599
+ ---
600
+
193
601
  ### Get Insurances
194
602
 
195
603
  Public signature: `settingsClient.getInsurances()`
196
604
 
197
- Returns patient insurances through the wrapper-backed EHR route.
198
- The client resolves the current patient's `EHR` internally from `authClient.getUserInfo()`.
605
+ Returns patient insurances through the EHR-backed route.
606
+ The client resolves the current `EHR` internally from `authClient.getUserInfo()`.
199
607
 
200
608
  ```ts
201
609
  const insurances = await settingsClient.getInsurances();
202
610
  ```
203
611
 
612
+ #### Full API request
613
+
614
+ This method performs an authenticated request internally and does not send a request body.
615
+
616
+ #### API response
617
+
618
+ Status:
619
+
620
+ ```txt
621
+ 200
622
+ ```
623
+
624
+ ```json
625
+ {
626
+ "Data": [
627
+ {
628
+ "InsuranceId": "insurance-id-example",
629
+ "InsurancePackageId": 693245,
630
+ "InsurancePolicyHolderFirstName": "John",
631
+ "InsurancePolicyHolderLastName": "Doe",
632
+ "InsurancePolicyHolder": "John Doe",
633
+ "RelationshipToInsured": "Self",
634
+ "EligibilityStatus": "Active",
635
+ "InsurancePlanName": " - ",
636
+ "InsuranceType": "FHIR",
637
+ "MemberId": "member-id-example",
638
+ "Image": "insurancecard_example.jpeg"
639
+ }
640
+ ],
641
+ "ErrorMessage": null,
642
+ "IsOK": true
643
+ }
644
+ ```
645
+
646
+ ---
647
+
204
648
  ### Update User Image URL
205
649
 
206
650
  Public signature: `settingsClient.updateUserImage(fileName)`
207
651
 
208
- Updates the user profile image URL using a file name.
652
+ Updates the stored user image file reference using a file name returned from `getUserImageCannedUrl(...)`.
209
653
 
210
654
  ```ts
211
- await settingsClient.updateUserImage("selfie_639064123637965380.jpg");
655
+ const updated = await settingsClient.updateUserImage(
656
+ "selfie_example.jpeg"
657
+ );
658
+ ```
659
+
660
+ #### Full API request
661
+
662
+ ```json
663
+ {
664
+ "Data": {
665
+ "FileName": "selfie_example.jpeg"
666
+ }
667
+ }
668
+ ```
669
+
670
+ #### API response
671
+
672
+ Status:
673
+
674
+ ```txt
675
+ 200
676
+ ```
677
+
678
+ ```json
679
+ true
212
680
  ```
213
681
 
682
+ ---
683
+
214
684
  ### Deactivate User
215
685
 
216
686
  Public signature: `settingsClient.deactivateUser()`
217
687
 
218
- Deactivates the current user.
688
+ Deactivates the current authenticated user.
219
689
 
220
690
  ```ts
221
691
  await settingsClient.deactivateUser();
222
692
  ```
223
693
 
224
- ---
694
+ #### Full API request
225
695
 
226
- ## How It Works
696
+ ```json
697
+ {
698
+ "Data": {}
699
+ }
700
+ ```
227
701
 
228
- - **HCLoginClient**
229
- - Handles authentication
230
- - Resolves base API URL
231
- - Provides authorization headers
232
- - Resolves the current user's `EHR` for EHR-backed settings methods
702
+ #### API response
233
703
 
234
- - **HttpClient**
235
- - Performs all HTTP requests
704
+ This method was not directly verified in the live environment because it would deactivate the authenticated test user.
705
+ The client returns the raw backend response from the authenticated `PUT` request.
236
706
 
237
- - **HCSettingsClient**
238
- - Exposes user settings and profile-related endpoints
707
+ ---
708
+
709
+ ## How It Works
710
+
711
+ - `HCLoginClient` handles tenant configuration, authentication, and authenticated headers.
712
+ - `HCSettingsClient` uses the authenticated login client to call patient settings and profile-related endpoints.
713
+ - Canned URL methods return a backend-generated upload URL and file name, but the caller is responsible for uploading the file bytes and preserving any signed S3 headers required by that URL.
714
+ - Capture, insurance, and EHR-backed settings methods all use the authenticated patient context from the shared login client.
715
+ - `getInsurances()`, `updateDrivingLicense()`, and `submitDrivingLicense()` resolve the active patient's `EHR` internally before building the final route.
239
716
 
240
717
  ---
241
718
 
242
719
  ## Notes
243
720
 
244
- - `HCLoginClient` must be configured and logged in before calling settings methods
245
- - `getUserImageCannedUrl()` uses `PUT /patient/image/cannedurl`
246
- - `getDrivingLicenseCannedUrl()` uses `PUT /patient/id/cannedurl`
247
- - `getInsuranceCannedUrl()` uses `PUT /patient/insurance/cannedurl`
248
- - `captureUserPhoto()` sends `Type: "userphoto"` and `FileID` to `/patient/capture`
249
- - `captureDrivingLicense()` sends `Type: "identification"` and `FileID` to `/patient/capture`
250
- - `captureInsurance()` sends `Type: "healthinsurance"` and `FileID` to `/patient/capture`
251
- - `updateDrivingLicense()` and `submitDrivingLicense()` send `{ Data: { Image: fileKey } }`
252
- - `getInsurances()`, `updateDrivingLicense()` and `submitDrivingLicense()` internally resolve the current patient's `EHR`
721
+ - `HCLoginClient` must be configured and logged in before calling settings methods.
722
+ - `getUserImageCannedUrl()`, `getDrivingLicenseCannedUrl()`, and `getInsuranceCannedUrl()` return the backend canned URL response and do not upload the file contents.
723
+ - After requesting a canned URL, the file must be uploaded outside this package before capture methods can succeed.
724
+ - Live verification showed that the S3 upload must preserve signed headers from the canned URL; when `x-amz-acl` was signed, uploads succeeded with `x-amz-acl: public-read`.
725
+ - `captureUserPhoto()` sends `Type: "userphoto"` and `FileID` to the patient capture endpoint.
726
+ - `captureDrivingLicense()` sends `Type: "identification"` and `FileID` to the patient capture endpoint.
727
+ - `captureInsurance()` sends `Type: "healthinsurance"` and `FileID` to the patient capture endpoint.
728
+ - `updateDrivingLicense()` and `submitDrivingLicense()` send `{ "Data": { "Image": "..." } }` to the resolved EHR patient route.
729
+ - `submitDrivingLicense()` is a backward-compatible alias of `updateDrivingLicense()`.
730
+ - `getInsurances()`, `updateDrivingLicense()`, and `submitDrivingLicense()` internally resolve the current patient's `EHR`.
731
+
732
+
733
+ ## API Key
734
+
735
+ All outgoing requests from `HCSettingsClient` can include an optional API key header.
736
+
737
+ ```ts
738
+ const apiKey = process.env.HEALTHCLOUD_API_KEY;
739
+
740
+ if (apiKey) {
741
+ settingsClient.setApiKey("x-api-key", apiKey);
742
+ }
743
+ ```
253
744
 
745
+ - Header name should be `x-api-key`.
746
+ - API key is optional unless required by the backend.
747
+ - If not set, behavior remains unchanged and the header is omitted.
748
+ - The API key is also included on the internal patient header lookup used to resolve the active `EHR`.
package/dist/index.cjs CHANGED
@@ -34,16 +34,20 @@ var HCSettingsClient = class {
34
34
  this.http = httpClient;
35
35
  this.auth = authClient;
36
36
  }
37
+ setApiKey(headerName, value) {
38
+ this.apiKeyHeaderName = headerName;
39
+ this.apiKeyValue = value;
40
+ }
37
41
  async getUserInfo() {
38
42
  return this.http.get(
39
- `${this.auth.getBaseUrl()}/patient/header`,
40
- this.auth.getAuthHeader()
43
+ `${this.getBaseUrl()}/patient/header`,
44
+ this.getAuthHeaders()
41
45
  );
42
46
  }
43
47
  async getDashboard() {
44
48
  return this.http.get(
45
- `${this.auth.getBaseUrl()}/patient/dashboard`,
46
- this.auth.getAuthHeader()
49
+ `${this.getBaseUrl()}/patient/dashboard`,
50
+ this.getAuthHeaders()
47
51
  );
48
52
  }
49
53
  async getUserImageCannedUrl(extension) {
@@ -54,12 +58,9 @@ var HCSettingsClient = class {
54
58
  }
55
59
  };
56
60
  const response = await this.http.put(
57
- `${this.auth.getBaseUrl()}/patient/image/cannedurl`,
61
+ `${this.getBaseUrl()}/patient/image/cannedurl`,
58
62
  payload,
59
- {
60
- ...this.auth.getAuthHeader(),
61
- "Content-Type": "application/json"
62
- }
63
+ this.getJsonHeaders()
63
64
  );
64
65
  return (_a = response.Data) != null ? _a : response;
65
66
  }
@@ -71,12 +72,9 @@ var HCSettingsClient = class {
71
72
  }
72
73
  };
73
74
  const response = await this.http.put(
74
- `${this.auth.getBaseUrl()}/patient/id/cannedurl`,
75
+ `${this.getBaseUrl()}/patient/id/cannedurl`,
75
76
  payload,
76
- {
77
- ...this.auth.getAuthHeader(),
78
- "Content-Type": "application/json"
79
- }
77
+ this.getJsonHeaders()
80
78
  );
81
79
  return (_a = response.Data) != null ? _a : response;
82
80
  }
@@ -88,12 +86,9 @@ var HCSettingsClient = class {
88
86
  }
89
87
  };
90
88
  const response = await this.http.put(
91
- `${this.auth.getBaseUrl()}/patient/insurance/cannedurl`,
89
+ `${this.getBaseUrl()}/patient/insurance/cannedurl`,
92
90
  payload,
93
- {
94
- ...this.auth.getAuthHeader(),
95
- "Content-Type": "application/json"
96
- }
91
+ this.getJsonHeaders()
97
92
  );
98
93
  return (_a = response.Data) != null ? _a : response;
99
94
  }
@@ -105,12 +100,9 @@ var HCSettingsClient = class {
105
100
  }
106
101
  };
107
102
  return this.http.post(
108
- `${this.auth.getBaseUrl()}/patient/capture`,
103
+ `${this.getBaseUrl()}/patient/capture`,
109
104
  payload,
110
- {
111
- ...this.auth.getAuthHeader(),
112
- "Content-Type": "application/json"
113
- }
105
+ this.getJsonHeaders()
114
106
  );
115
107
  }
116
108
  async captureDrivingLicense(fileKey) {
@@ -121,12 +113,9 @@ var HCSettingsClient = class {
121
113
  }
122
114
  };
123
115
  return this.http.post(
124
- `${this.auth.getBaseUrl()}/patient/capture`,
116
+ `${this.getBaseUrl()}/patient/capture`,
125
117
  payload,
126
- {
127
- ...this.auth.getAuthHeader(),
128
- "Content-Type": "application/json"
129
- }
118
+ this.getJsonHeaders()
130
119
  );
131
120
  }
132
121
  async captureInsurance(fileKey) {
@@ -137,12 +126,9 @@ var HCSettingsClient = class {
137
126
  }
138
127
  };
139
128
  return this.http.post(
140
- `${this.auth.getBaseUrl()}/patient/capture`,
129
+ `${this.getBaseUrl()}/patient/capture`,
141
130
  payload,
142
- {
143
- ...this.auth.getAuthHeader(),
144
- "Content-Type": "application/json"
145
- }
131
+ this.getJsonHeaders()
146
132
  );
147
133
  }
148
134
  async submitInsurance(payload) {
@@ -150,18 +136,15 @@ var HCSettingsClient = class {
150
136
  Data: payload
151
137
  };
152
138
  return this.http.put(
153
- `${this.auth.getBaseUrl()}/patient/coverage`,
139
+ `${this.getBaseUrl()}/patient/coverage`,
154
140
  requestPayload,
155
- {
156
- ...this.auth.getAuthHeader(),
157
- "Content-Type": "application/json"
158
- }
141
+ this.getJsonHeaders()
159
142
  );
160
143
  }
161
144
  async getInsurances() {
162
145
  return this.http.get(
163
146
  await this.buildEhrPatientUrl("insurances"),
164
- this.auth.getAuthHeader()
147
+ this.getAuthHeaders()
165
148
  );
166
149
  }
167
150
  async updateDrivingLicense(payload) {
@@ -171,10 +154,7 @@ var HCSettingsClient = class {
171
154
  return this.http.put(
172
155
  await this.buildEhrPatientUrl("drivinglicense"),
173
156
  requestPayload,
174
- {
175
- ...this.auth.getAuthHeader(),
176
- "Content-Type": "application/json"
177
- }
157
+ this.getJsonHeaders()
178
158
  );
179
159
  }
180
160
  async submitDrivingLicense(payload) {
@@ -188,12 +168,9 @@ var HCSettingsClient = class {
188
168
  }
189
169
  };
190
170
  const response = await this.http.put(
191
- `${this.auth.getBaseUrl()}/patient/image/url`,
171
+ `${this.getBaseUrl()}/patient/image/url`,
192
172
  payload,
193
- {
194
- ...this.auth.getAuthHeader(),
195
- "Content-Type": "application/json"
196
- }
173
+ this.getJsonHeaders()
197
174
  );
198
175
  return (_a = response.Data) != null ? _a : response;
199
176
  }
@@ -202,31 +179,54 @@ var HCSettingsClient = class {
202
179
  Data: {}
203
180
  };
204
181
  return this.http.put(
205
- `${this.auth.getBaseUrl()}/patient/deactivate`,
182
+ `${this.getBaseUrl()}/patient/deactivate`,
206
183
  payload,
207
- {
208
- ...this.auth.getAuthHeader(),
209
- "Content-Type": "application/json"
210
- }
184
+ this.getJsonHeaders()
211
185
  );
212
186
  }
213
187
  async buildEhrPatientUrl(path) {
214
188
  const ehr = await this.getResolvedEhr();
215
- return `${this.auth.getBaseUrl()}/ehr/${ehr}/patient/${path}`;
189
+ return `${this.getBaseUrl()}/ehr/${ehr}/patient/${path}`;
216
190
  }
217
191
  async getResolvedEhr() {
218
192
  var _a, _b, _c;
219
193
  if (this.resolvedEhr) {
220
194
  return this.resolvedEhr;
221
195
  }
222
- const userInfo = await this.auth.getUserInfo();
196
+ const userInfo = await this.http.get(
197
+ `${this.getBaseUrl()}/patient/header`,
198
+ this.getAuthHeaders()
199
+ );
223
200
  const ehr = ((_b = (_a = userInfo == null ? void 0 : userInfo.Data) == null ? void 0 : _a.EHR) == null ? void 0 : _b.trim()) || ((_c = userInfo == null ? void 0 : userInfo.EHR) == null ? void 0 : _c.trim());
224
201
  if (!ehr) {
225
- throw new Error("Could not resolve EHR from loginClient.getUserInfo()");
202
+ throw new Error("Could not resolve EHR from patient header response.");
226
203
  }
227
204
  this.resolvedEhr = ehr;
228
205
  return ehr;
229
206
  }
207
+ getBaseUrl() {
208
+ return this.auth.getBaseUrl();
209
+ }
210
+ getAuthHeaders() {
211
+ return {
212
+ ...this.auth.getAuthHeader(),
213
+ ...this.getApiKeyHeader()
214
+ };
215
+ }
216
+ getJsonHeaders() {
217
+ return {
218
+ ...this.getAuthHeaders(),
219
+ "Content-Type": "application/json"
220
+ };
221
+ }
222
+ getApiKeyHeader() {
223
+ if (!this.apiKeyHeaderName || !this.apiKeyValue) {
224
+ return {};
225
+ }
226
+ return {
227
+ "x-api-key": this.apiKeyValue
228
+ };
229
+ }
230
230
  };
231
231
 
232
232
  // src/errors.ts
package/dist/index.d.cts CHANGED
@@ -3,9 +3,12 @@ import { HttpClient } from '@healthcloudai/hc-http';
3
3
 
4
4
  type Environment = "dev" | "uat" | "prod";
5
5
  interface UserImage {
6
- imageUrl: string;
7
- fileName: string;
8
- extension: string;
6
+ ImageURL: string;
7
+ FileName: string;
8
+ Extension: string;
9
+ imageUrl?: string;
10
+ fileName?: string;
11
+ extension?: string;
9
12
  }
10
13
  interface UserInfo {
11
14
  ID?: string;
@@ -66,7 +69,10 @@ declare class HCSettingsClient {
66
69
  private http;
67
70
  private auth;
68
71
  private resolvedEhr;
72
+ private apiKeyHeaderName?;
73
+ private apiKeyValue?;
69
74
  constructor(httpClient: HttpClient, authClient: HCLoginClient);
75
+ setApiKey(headerName: string, value: string): void;
70
76
  getUserInfo(): Promise<any>;
71
77
  getDashboard(): Promise<any>;
72
78
  getUserImageCannedUrl(extension: string): Promise<UserImage>;
@@ -79,10 +85,14 @@ declare class HCSettingsClient {
79
85
  getInsurances(): Promise<any>;
80
86
  updateDrivingLicense(payload: DrivingLicenseData): Promise<DrivingLicenseResponse>;
81
87
  submitDrivingLicense(payload: DrivingLicenseData): Promise<DrivingLicenseResponse>;
82
- updateUserImage(fileName: string): Promise<UserImage>;
88
+ updateUserImage(fileName: string): Promise<any>;
83
89
  deactivateUser(): Promise<any>;
84
90
  private buildEhrPatientUrl;
85
91
  private getResolvedEhr;
92
+ private getBaseUrl;
93
+ private getAuthHeaders;
94
+ private getJsonHeaders;
95
+ private getApiKeyHeader;
86
96
  }
87
97
 
88
98
  declare class ConfigError extends Error {
package/dist/index.d.ts CHANGED
@@ -3,9 +3,12 @@ import { HttpClient } from '@healthcloudai/hc-http';
3
3
 
4
4
  type Environment = "dev" | "uat" | "prod";
5
5
  interface UserImage {
6
- imageUrl: string;
7
- fileName: string;
8
- extension: string;
6
+ ImageURL: string;
7
+ FileName: string;
8
+ Extension: string;
9
+ imageUrl?: string;
10
+ fileName?: string;
11
+ extension?: string;
9
12
  }
10
13
  interface UserInfo {
11
14
  ID?: string;
@@ -66,7 +69,10 @@ declare class HCSettingsClient {
66
69
  private http;
67
70
  private auth;
68
71
  private resolvedEhr;
72
+ private apiKeyHeaderName?;
73
+ private apiKeyValue?;
69
74
  constructor(httpClient: HttpClient, authClient: HCLoginClient);
75
+ setApiKey(headerName: string, value: string): void;
70
76
  getUserInfo(): Promise<any>;
71
77
  getDashboard(): Promise<any>;
72
78
  getUserImageCannedUrl(extension: string): Promise<UserImage>;
@@ -79,10 +85,14 @@ declare class HCSettingsClient {
79
85
  getInsurances(): Promise<any>;
80
86
  updateDrivingLicense(payload: DrivingLicenseData): Promise<DrivingLicenseResponse>;
81
87
  submitDrivingLicense(payload: DrivingLicenseData): Promise<DrivingLicenseResponse>;
82
- updateUserImage(fileName: string): Promise<UserImage>;
88
+ updateUserImage(fileName: string): Promise<any>;
83
89
  deactivateUser(): Promise<any>;
84
90
  private buildEhrPatientUrl;
85
91
  private getResolvedEhr;
92
+ private getBaseUrl;
93
+ private getAuthHeaders;
94
+ private getJsonHeaders;
95
+ private getApiKeyHeader;
86
96
  }
87
97
 
88
98
  declare class ConfigError extends Error {
package/dist/index.js CHANGED
@@ -5,16 +5,20 @@ var HCSettingsClient = class {
5
5
  this.http = httpClient;
6
6
  this.auth = authClient;
7
7
  }
8
+ setApiKey(headerName, value) {
9
+ this.apiKeyHeaderName = headerName;
10
+ this.apiKeyValue = value;
11
+ }
8
12
  async getUserInfo() {
9
13
  return this.http.get(
10
- `${this.auth.getBaseUrl()}/patient/header`,
11
- this.auth.getAuthHeader()
14
+ `${this.getBaseUrl()}/patient/header`,
15
+ this.getAuthHeaders()
12
16
  );
13
17
  }
14
18
  async getDashboard() {
15
19
  return this.http.get(
16
- `${this.auth.getBaseUrl()}/patient/dashboard`,
17
- this.auth.getAuthHeader()
20
+ `${this.getBaseUrl()}/patient/dashboard`,
21
+ this.getAuthHeaders()
18
22
  );
19
23
  }
20
24
  async getUserImageCannedUrl(extension) {
@@ -25,12 +29,9 @@ var HCSettingsClient = class {
25
29
  }
26
30
  };
27
31
  const response = await this.http.put(
28
- `${this.auth.getBaseUrl()}/patient/image/cannedurl`,
32
+ `${this.getBaseUrl()}/patient/image/cannedurl`,
29
33
  payload,
30
- {
31
- ...this.auth.getAuthHeader(),
32
- "Content-Type": "application/json"
33
- }
34
+ this.getJsonHeaders()
34
35
  );
35
36
  return (_a = response.Data) != null ? _a : response;
36
37
  }
@@ -42,12 +43,9 @@ var HCSettingsClient = class {
42
43
  }
43
44
  };
44
45
  const response = await this.http.put(
45
- `${this.auth.getBaseUrl()}/patient/id/cannedurl`,
46
+ `${this.getBaseUrl()}/patient/id/cannedurl`,
46
47
  payload,
47
- {
48
- ...this.auth.getAuthHeader(),
49
- "Content-Type": "application/json"
50
- }
48
+ this.getJsonHeaders()
51
49
  );
52
50
  return (_a = response.Data) != null ? _a : response;
53
51
  }
@@ -59,12 +57,9 @@ var HCSettingsClient = class {
59
57
  }
60
58
  };
61
59
  const response = await this.http.put(
62
- `${this.auth.getBaseUrl()}/patient/insurance/cannedurl`,
60
+ `${this.getBaseUrl()}/patient/insurance/cannedurl`,
63
61
  payload,
64
- {
65
- ...this.auth.getAuthHeader(),
66
- "Content-Type": "application/json"
67
- }
62
+ this.getJsonHeaders()
68
63
  );
69
64
  return (_a = response.Data) != null ? _a : response;
70
65
  }
@@ -76,12 +71,9 @@ var HCSettingsClient = class {
76
71
  }
77
72
  };
78
73
  return this.http.post(
79
- `${this.auth.getBaseUrl()}/patient/capture`,
74
+ `${this.getBaseUrl()}/patient/capture`,
80
75
  payload,
81
- {
82
- ...this.auth.getAuthHeader(),
83
- "Content-Type": "application/json"
84
- }
76
+ this.getJsonHeaders()
85
77
  );
86
78
  }
87
79
  async captureDrivingLicense(fileKey) {
@@ -92,12 +84,9 @@ var HCSettingsClient = class {
92
84
  }
93
85
  };
94
86
  return this.http.post(
95
- `${this.auth.getBaseUrl()}/patient/capture`,
87
+ `${this.getBaseUrl()}/patient/capture`,
96
88
  payload,
97
- {
98
- ...this.auth.getAuthHeader(),
99
- "Content-Type": "application/json"
100
- }
89
+ this.getJsonHeaders()
101
90
  );
102
91
  }
103
92
  async captureInsurance(fileKey) {
@@ -108,12 +97,9 @@ var HCSettingsClient = class {
108
97
  }
109
98
  };
110
99
  return this.http.post(
111
- `${this.auth.getBaseUrl()}/patient/capture`,
100
+ `${this.getBaseUrl()}/patient/capture`,
112
101
  payload,
113
- {
114
- ...this.auth.getAuthHeader(),
115
- "Content-Type": "application/json"
116
- }
102
+ this.getJsonHeaders()
117
103
  );
118
104
  }
119
105
  async submitInsurance(payload) {
@@ -121,18 +107,15 @@ var HCSettingsClient = class {
121
107
  Data: payload
122
108
  };
123
109
  return this.http.put(
124
- `${this.auth.getBaseUrl()}/patient/coverage`,
110
+ `${this.getBaseUrl()}/patient/coverage`,
125
111
  requestPayload,
126
- {
127
- ...this.auth.getAuthHeader(),
128
- "Content-Type": "application/json"
129
- }
112
+ this.getJsonHeaders()
130
113
  );
131
114
  }
132
115
  async getInsurances() {
133
116
  return this.http.get(
134
117
  await this.buildEhrPatientUrl("insurances"),
135
- this.auth.getAuthHeader()
118
+ this.getAuthHeaders()
136
119
  );
137
120
  }
138
121
  async updateDrivingLicense(payload) {
@@ -142,10 +125,7 @@ var HCSettingsClient = class {
142
125
  return this.http.put(
143
126
  await this.buildEhrPatientUrl("drivinglicense"),
144
127
  requestPayload,
145
- {
146
- ...this.auth.getAuthHeader(),
147
- "Content-Type": "application/json"
148
- }
128
+ this.getJsonHeaders()
149
129
  );
150
130
  }
151
131
  async submitDrivingLicense(payload) {
@@ -159,12 +139,9 @@ var HCSettingsClient = class {
159
139
  }
160
140
  };
161
141
  const response = await this.http.put(
162
- `${this.auth.getBaseUrl()}/patient/image/url`,
142
+ `${this.getBaseUrl()}/patient/image/url`,
163
143
  payload,
164
- {
165
- ...this.auth.getAuthHeader(),
166
- "Content-Type": "application/json"
167
- }
144
+ this.getJsonHeaders()
168
145
  );
169
146
  return (_a = response.Data) != null ? _a : response;
170
147
  }
@@ -173,31 +150,54 @@ var HCSettingsClient = class {
173
150
  Data: {}
174
151
  };
175
152
  return this.http.put(
176
- `${this.auth.getBaseUrl()}/patient/deactivate`,
153
+ `${this.getBaseUrl()}/patient/deactivate`,
177
154
  payload,
178
- {
179
- ...this.auth.getAuthHeader(),
180
- "Content-Type": "application/json"
181
- }
155
+ this.getJsonHeaders()
182
156
  );
183
157
  }
184
158
  async buildEhrPatientUrl(path) {
185
159
  const ehr = await this.getResolvedEhr();
186
- return `${this.auth.getBaseUrl()}/ehr/${ehr}/patient/${path}`;
160
+ return `${this.getBaseUrl()}/ehr/${ehr}/patient/${path}`;
187
161
  }
188
162
  async getResolvedEhr() {
189
163
  var _a, _b, _c;
190
164
  if (this.resolvedEhr) {
191
165
  return this.resolvedEhr;
192
166
  }
193
- const userInfo = await this.auth.getUserInfo();
167
+ const userInfo = await this.http.get(
168
+ `${this.getBaseUrl()}/patient/header`,
169
+ this.getAuthHeaders()
170
+ );
194
171
  const ehr = ((_b = (_a = userInfo == null ? void 0 : userInfo.Data) == null ? void 0 : _a.EHR) == null ? void 0 : _b.trim()) || ((_c = userInfo == null ? void 0 : userInfo.EHR) == null ? void 0 : _c.trim());
195
172
  if (!ehr) {
196
- throw new Error("Could not resolve EHR from loginClient.getUserInfo()");
173
+ throw new Error("Could not resolve EHR from patient header response.");
197
174
  }
198
175
  this.resolvedEhr = ehr;
199
176
  return ehr;
200
177
  }
178
+ getBaseUrl() {
179
+ return this.auth.getBaseUrl();
180
+ }
181
+ getAuthHeaders() {
182
+ return {
183
+ ...this.auth.getAuthHeader(),
184
+ ...this.getApiKeyHeader()
185
+ };
186
+ }
187
+ getJsonHeaders() {
188
+ return {
189
+ ...this.getAuthHeaders(),
190
+ "Content-Type": "application/json"
191
+ };
192
+ }
193
+ getApiKeyHeader() {
194
+ if (!this.apiKeyHeaderName || !this.apiKeyValue) {
195
+ return {};
196
+ }
197
+ return {
198
+ "x-api-key": this.apiKeyValue
199
+ };
200
+ }
201
201
  };
202
202
 
203
203
  // src/errors.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@healthcloudai/hc-settings-connector",
3
- "version": "0.0.5",
3
+ "version": "0.0.8",
4
4
  "description": "Healthcheck Settings SDK with TypeScript",
5
5
  "author": "Healthcheck Systems Inc",
6
6
  "license": "MIT",