@healthcloudai/hc-safe-cdx 0.2.0 → 0.2.2
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 +695 -409
- package/dist/index.cjs +127 -202
- package/dist/index.d.cts +385 -165
- package/dist/index.d.ts +385 -165
- package/dist/index.js +127 -202
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
# Healthcheck Safe CDX Connector
|
|
2
2
|
|
|
3
|
-
Safe CDX
|
|
3
|
+
Safe CDX supports the diagnostic test workflow performed by an authenticated patient. It provides the SDK methods used to retrieve available test profiles, resolve a selected test by GTIN, prepare and upload test images, process test results, and complete the test flow.
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
`HCSafeCDXClient` uses the authenticated patient context provided by `HCLoginClient`. The client derives its own Safe CDX service URL from the configured environment, sends authenticated requests to Safe CDX routes, and wraps request payloads internally where the API expects the standard `Data` envelope.
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- `HCLoginClient` provides the authenticated request headers.
|
|
9
|
-
- `HCSafeCDXClient` builds Safe CDX URLs, wraps request payloads, and exposes one method per Safe CDX route.
|
|
10
|
-
|
|
11
|
-
Safe CDX has its own API host. The connector uses `HCLoginClient` for authentication only; it does not use `loginClient.getBaseUrl()` for Safe CDX routes.
|
|
12
|
-
Like `HCHealthRecordClient`, `HCSafeCDXClient` reads the configured environment from `HCLoginClient` and derives its own service base URL internally.
|
|
13
|
-
|
|
14
|
-
Image upload is handled separately because the upload target is a pre-signed S3 URL, not a Safe CDX API route.
|
|
7
|
+
Image upload is handled separately because the upload target is a pre-signed storage URL rather than a Safe CDX API route.
|
|
15
8
|
|
|
16
9
|
## Installation
|
|
17
10
|
|
|
@@ -27,358 +20,323 @@ import { HCLoginClient } from "@healthcloudai/hc-login-connector";
|
|
|
27
20
|
import { HCSafeCDXClient } from "@healthcloudai/hc-safe-cdx";
|
|
28
21
|
```
|
|
29
22
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
const http = new FetchClient();
|
|
34
|
-
|
|
35
|
-
const loginClient = new HCLoginClient(http);
|
|
36
|
-
|
|
37
|
-
loginClient.configure("healthcheck", "dev");
|
|
38
|
-
await loginClient.login(email, password);
|
|
39
|
-
|
|
40
|
-
const safeCdx = new HCSafeCDXClient(http, loginClient);
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The connector does not perform login. The consuming application should authenticate through the Health Cloud login connector first. Safe CDX then reuses the authenticated headers from `loginClient.getAuthHeader()`.
|
|
44
|
-
|
|
45
|
-
There is no `setAccessToken()` step in this version of the client.
|
|
46
|
-
|
|
47
|
-
## Dependency Notes
|
|
48
|
-
|
|
49
|
-
Because `HCSafeCDXClient` accepts `HCLoginClient` in the constructor, `@healthcloudai/hc-login-connector` should be included as a package dependency.
|
|
50
|
-
|
|
51
|
-
Example package configuration:
|
|
52
|
-
|
|
53
|
-
```json
|
|
54
|
-
{
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"@healthcloudai/hc-http": "^0.x.x",
|
|
57
|
-
"@healthcloudai/hc-login-connector": "^0.x.x"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
In a workspace setup, use the same dependency versioning strategy already used by the other connector packages.
|
|
23
|
+
## Setup
|
|
63
24
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
```json
|
|
67
|
-
{
|
|
68
|
-
"dependencies": {
|
|
69
|
-
"@healthcloudai/hc-http": "workspace:*",
|
|
70
|
-
"@healthcloudai/hc-login-connector": "workspace:*"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## How the Client Works
|
|
76
|
-
|
|
77
|
-
The client receives both the HTTP client and the login client:
|
|
25
|
+
Create the shared HTTP client, authenticate the patient through `HCLoginClient`, and then create the Safe CDX client with the authenticated login instance.
|
|
78
26
|
|
|
79
27
|
```ts
|
|
80
|
-
const
|
|
81
|
-
const loginClient = new HCLoginClient(
|
|
28
|
+
const httpClient = new FetchClient();
|
|
29
|
+
const loginClient = new HCLoginClient(httpClient);
|
|
82
30
|
|
|
83
31
|
loginClient.configure("healthcheck", "dev");
|
|
84
32
|
await loginClient.login(email, password);
|
|
85
33
|
|
|
86
|
-
const safeCdx = new HCSafeCDXClient(
|
|
34
|
+
const safeCdx = new HCSafeCDXClient(httpClient, loginClient);
|
|
87
35
|
```
|
|
88
36
|
|
|
89
|
-
The
|
|
37
|
+
The Safe CDX connector does not perform login and does not require a separate `setAccessToken(...)` step. Authenticated headers are read from the existing `HCLoginClient` instance.
|
|
90
38
|
|
|
91
|
-
|
|
39
|
+
## Client Configuration
|
|
92
40
|
|
|
93
|
-
|
|
41
|
+
### Service URL
|
|
94
42
|
|
|
95
|
-
|
|
96
|
-
- building Safe CDX URLs
|
|
97
|
-
- adding auth headers from `HCLoginClient`
|
|
98
|
-
- adding optional API key headers when configured
|
|
99
|
-
- wrapping POST request payloads into `{ Data: payload }`
|
|
100
|
-
- validating `ApiResponse` results where the backend returns `{ IsOK, Data, ErrorMessage }`
|
|
101
|
-
- exposing one SDK method per Safe CDX route
|
|
43
|
+
Safe CDX uses its own service base URL and does not reuse `loginClient.getBaseUrl()`. The client reads the configured environment through `loginClient.getEnvironment()` and resolves the Safe CDX host internally.
|
|
102
44
|
|
|
103
|
-
The Safe CDX client does not create its own internal `fetch` helpers for standard Safe CDX API routes.
|
|
104
45
|
|
|
105
|
-
|
|
46
|
+
### Optional API Key
|
|
106
47
|
|
|
107
|
-
|
|
48
|
+
When an environment requires an API key header, configure it on the Safe CDX client:
|
|
108
49
|
|
|
109
50
|
```ts
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const safeCdx = new HCSafeCDXClient(http, loginClient);
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
The Safe CDX client reads the environment from:
|
|
116
|
-
|
|
117
|
-
```ts
|
|
118
|
-
loginClient.getEnvironment()
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Safe CDX still uses its own service base URL. It does not reuse `loginClient.getBaseUrl()`.
|
|
122
|
-
|
|
123
|
-
Environment mapping is handled internally by the connector:
|
|
124
|
-
|
|
125
|
-
```txt
|
|
126
|
-
dev -> https://dev-api-hcs.healthcloud-services.com/api/console/hcservice/safecdx
|
|
127
|
-
uat -> https://uat-api-hcs.healthcloud-services.com/api/console/hcservice/safecdx
|
|
128
|
-
prod -> https://api-hcs.healthcloud-services.com/api/console/hcservice/safecdx
|
|
51
|
+
safeCdx.setApiKey("x-api-key", apiKeyValue);
|
|
129
52
|
```
|
|
130
53
|
|
|
131
|
-
|
|
54
|
+
The configured API key header is added to Safe CDX API route requests together with the patient authentication headers.
|
|
132
55
|
|
|
133
|
-
##
|
|
56
|
+
## Request Contract
|
|
134
57
|
|
|
135
|
-
|
|
58
|
+
SDK methods receive only the values needed by the consuming application. The consumer does not manually provide the backend `Data` wrapper, tenant context, patient identity values, or authentication headers.
|
|
136
59
|
|
|
137
|
-
|
|
60
|
+
For POST requests, `HCSafeCDXClient` constructs the API request envelope internally:
|
|
138
61
|
|
|
139
62
|
```ts
|
|
140
|
-
|
|
63
|
+
interface APIRequest<T> {
|
|
64
|
+
Data: T;
|
|
65
|
+
}
|
|
141
66
|
```
|
|
142
67
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
Example flow:
|
|
68
|
+
For example:
|
|
146
69
|
|
|
147
70
|
```ts
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
71
|
+
await safeCdx.submitAnswers({
|
|
72
|
+
UserTestResultId: userTestResultId,
|
|
73
|
+
Result: [
|
|
74
|
+
{
|
|
75
|
+
Analyte: "Purchase",
|
|
76
|
+
ReportedValue: "drug store",
|
|
77
|
+
StoredValue: "drug store",
|
|
78
|
+
Score: "0"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
});
|
|
156
82
|
```
|
|
157
83
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
## Optional API Key Header
|
|
84
|
+
The client sends:
|
|
161
85
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"Data": {
|
|
89
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>",
|
|
90
|
+
"Result": [
|
|
91
|
+
{
|
|
92
|
+
"Analyte": "Purchase",
|
|
93
|
+
"ReportedValue": "drug store",
|
|
94
|
+
"StoredValue": "drug store",
|
|
95
|
+
"Score": "0"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
166
100
|
```
|
|
167
101
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## Request Payload Wrapping
|
|
102
|
+
## Response Contract
|
|
171
103
|
|
|
172
|
-
|
|
104
|
+
Safe CDX methods return the response shape produced by their backend endpoint without unwrapping or transforming it.
|
|
173
105
|
|
|
174
|
-
|
|
106
|
+
Most documented methods return the standard Health Cloud response envelope:
|
|
175
107
|
|
|
176
108
|
```ts
|
|
177
|
-
{
|
|
178
|
-
|
|
109
|
+
interface APIResponse<T> {
|
|
110
|
+
Data: T | null;
|
|
111
|
+
IsOK: boolean;
|
|
112
|
+
ErrorMessage: string | null;
|
|
179
113
|
}
|
|
180
114
|
```
|
|
181
115
|
|
|
182
|
-
|
|
116
|
+
Several Safe CDX operations return a service response inside `APIResponse.Data`, or return that service response directly:
|
|
183
117
|
|
|
184
118
|
```ts
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
StoredValue: "drug store",
|
|
192
|
-
Score: "0",
|
|
193
|
-
},
|
|
194
|
-
],
|
|
195
|
-
});
|
|
119
|
+
interface SafeAPIResponse<T> {
|
|
120
|
+
success: boolean;
|
|
121
|
+
data: T | null;
|
|
122
|
+
message: string | null;
|
|
123
|
+
code: number;
|
|
124
|
+
}
|
|
196
125
|
```
|
|
197
126
|
|
|
198
|
-
|
|
127
|
+
The following methods return `SafeAPIResponse<T>` directly, without the outer `APIResponse<T>` wrapper:
|
|
199
128
|
|
|
200
129
|
```ts
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
},
|
|
206
|
-
});
|
|
130
|
+
safeCdx.updateCvmlStatus(...)
|
|
131
|
+
safeCdx.getCvmlResults(...)
|
|
132
|
+
safeCdx.getResultDetails(...)
|
|
133
|
+
safeCdx.getImageCaptureUrl(...)
|
|
207
134
|
```
|
|
208
135
|
|
|
209
|
-
|
|
136
|
+
`HCSafeCDXClient` does not replace an API-defined response with a different return value. Local errors may still be thrown before or outside a Safe CDX API response, such as invalid API key configuration or a failed direct image upload. Transport-level handling for unsuccessful HTTP responses is determined by the supplied `HttpClient`.
|
|
210
137
|
|
|
211
|
-
##
|
|
138
|
+
## Parameter Design
|
|
212
139
|
|
|
213
|
-
|
|
140
|
+
Public methods follow the documented patient workflow request shapes.
|
|
214
141
|
|
|
215
142
|
```ts
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
143
|
+
safeCdx.getTestProfileByGTIN(gtin)
|
|
144
|
+
safeCdx.getTestProfilesByAccount(includeRegisterTestDetails?)
|
|
145
|
+
safeCdx.createUploadUrl(userTestResultId, gtin, imageType?)
|
|
146
|
+
safeCdx.updateCvmlStatus(imageOfCaptureId, cvmlStatus)
|
|
147
|
+
safeCdx.getCvmlResults(imageOfCaptureId)
|
|
148
|
+
safeCdx.getPendingResults(excludeStatus?)
|
|
149
|
+
safeCdx.getLastResults(excludeStatus?)
|
|
150
|
+
safeCdx.getTestHistory(excludeStatus?)
|
|
151
|
+
safeCdx.getResultDetails(userTestResultId)
|
|
152
|
+
safeCdx.getResultPdf(userTestResultId)
|
|
153
|
+
safeCdx.getImageCaptureUrl(userTestResultId)
|
|
154
|
+
safeCdx.resumeFlow(userTestResultId, resumed?)
|
|
155
|
+
safeCdx.finalizeTest(userTestResultId)
|
|
221
156
|
```
|
|
222
157
|
|
|
223
|
-
For these endpoints, the client validates `IsOK`.
|
|
224
158
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
This validation exists because an HTTP `200` response does not always mean the backend operation succeeded. The HTTP client validates the transport layer, while the Safe CDX client validates the API response envelope.
|
|
228
|
-
|
|
229
|
-
For the following methods, the client returns the received response directly without applying `ApiResponse` validation:
|
|
159
|
+
## Typical Patient Workflow
|
|
230
160
|
|
|
231
161
|
```ts
|
|
232
|
-
|
|
233
|
-
getCvmlResults(...)
|
|
234
|
-
getResultDetails(...)
|
|
235
|
-
getImageCaptureUrl(...)
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
## Image Upload Handling
|
|
162
|
+
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
239
163
|
|
|
240
|
-
|
|
164
|
+
const profile = await safeCdx.getTestProfileByGTIN("850024942325");
|
|
241
165
|
|
|
242
|
-
|
|
166
|
+
if (!profile.IsOK || !profile.Data) {
|
|
167
|
+
throw new Error(profile.ErrorMessage ?? "Unable to resolve the test profile.");
|
|
168
|
+
}
|
|
243
169
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
```
|
|
170
|
+
const userTestResultId = profile.Data.ID;
|
|
171
|
+
const gtin = profile.Data.DiagnosticProfile?.TestInfo.gtin;
|
|
247
172
|
|
|
248
|
-
|
|
173
|
+
if (!userTestResultId || !gtin) {
|
|
174
|
+
throw new Error("The selected test profile does not include the required workflow identifiers.");
|
|
175
|
+
}
|
|
249
176
|
|
|
250
|
-
|
|
177
|
+
const upload = await safeCdx.createUploadUrl(userTestResultId, gtin);
|
|
251
178
|
|
|
252
|
-
|
|
179
|
+
if (!upload.IsOK || !upload.Data?.preSignedURL || !upload.Data.Metadata?.UploadId) {
|
|
180
|
+
throw new Error(upload.ErrorMessage ?? "Unable to prepare image upload.");
|
|
181
|
+
}
|
|
253
182
|
|
|
254
|
-
|
|
183
|
+
const preSignedURL = upload.Data.preSignedURL;
|
|
184
|
+
const imageOfCaptureId = upload.Data.Metadata.UploadId;
|
|
255
185
|
|
|
256
|
-
|
|
186
|
+
await safeCdx.uploadImage(preSignedURL, imageBody, "image/jpeg");
|
|
187
|
+
await safeCdx.updateCvmlStatus(imageOfCaptureId, "ImageProcessing");
|
|
257
188
|
|
|
258
|
-
|
|
259
|
-
const http = new FetchClient();
|
|
189
|
+
const cvmlResults = await safeCdx.getCvmlResults(imageOfCaptureId);
|
|
260
190
|
|
|
261
|
-
|
|
191
|
+
await safeCdx.submitAnswers({
|
|
192
|
+
UserTestResultId: userTestResultId,
|
|
193
|
+
Result: [
|
|
194
|
+
{
|
|
195
|
+
Analyte: "Purchase",
|
|
196
|
+
ReportedValue: "drug store",
|
|
197
|
+
StoredValue: "drug store",
|
|
198
|
+
Score: "0"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
});
|
|
262
202
|
|
|
263
|
-
|
|
264
|
-
await loginClient.login(email, password);
|
|
203
|
+
await safeCdx.finalizeTest(userTestResultId);
|
|
265
204
|
|
|
266
|
-
const
|
|
205
|
+
const details = await safeCdx.getResultDetails(userTestResultId);
|
|
206
|
+
const pdf = await safeCdx.getResultPdf(userTestResultId);
|
|
207
|
+
const imageCaptureUrl = await safeCdx.getImageCaptureUrl(userTestResultId);
|
|
267
208
|
```
|
|
268
209
|
|
|
269
|
-
|
|
210
|
+
The application is responsible for preserving workflow values returned between steps, including `userTestResultId`, `gtin`, `preSignedURL`, and `imageOfCaptureId`.
|
|
270
211
|
|
|
271
|
-
|
|
272
|
-
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### 2. Resolve test profile by GTIN
|
|
212
|
+
## Public Methods
|
|
276
213
|
|
|
277
|
-
|
|
278
|
-
const profile = await safeCdx.getTestProfileByGTIN("850024942325");
|
|
214
|
+
### `getTestProfilesByAccount(...)`
|
|
279
215
|
|
|
280
|
-
|
|
281
|
-
const gtin = profile.Data.DiagnosticProfile.TestInfo.gtin;
|
|
282
|
-
```
|
|
216
|
+
Lists test profiles available to the authenticated patient account. The backend resolves the tenant from the authenticated patient context.
|
|
283
217
|
|
|
284
|
-
|
|
218
|
+
#### Signature
|
|
285
219
|
|
|
286
220
|
```ts
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const imageOfCaptureId = upload.Data.Metadata.UploadId;
|
|
221
|
+
safeCdx.getTestProfilesByAccount(
|
|
222
|
+
includeRegisterTestDetails?: boolean
|
|
223
|
+
): Promise<APIResponse<GetTestProfilesByAccountData>>
|
|
291
224
|
```
|
|
292
225
|
|
|
293
|
-
|
|
226
|
+
`GetTestProfilesByAccountData` is:
|
|
294
227
|
|
|
295
228
|
```ts
|
|
296
|
-
|
|
229
|
+
type GetTestProfilesByAccountData =
|
|
230
|
+
SafeAPIResponse<TestProfileByAccountItem[]>;
|
|
297
231
|
```
|
|
298
232
|
|
|
299
|
-
|
|
233
|
+
#### Parameters
|
|
300
234
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
235
|
+
| Parameter | Type | Required | Description |
|
|
236
|
+
|---|---|---:|---|
|
|
237
|
+
| `includeRegisterTestDetails` | `boolean` | No | Includes registration-specific test details when `true`. Defaults to `true`. |
|
|
304
238
|
|
|
305
|
-
|
|
239
|
+
#### Usage
|
|
306
240
|
|
|
307
241
|
```ts
|
|
308
|
-
const
|
|
242
|
+
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
309
243
|
```
|
|
310
244
|
|
|
311
|
-
### 7. Submit answers
|
|
312
|
-
|
|
313
245
|
```ts
|
|
314
|
-
await safeCdx.
|
|
315
|
-
UserTestResultId: userTestResultId,
|
|
316
|
-
Result: [
|
|
317
|
-
{
|
|
318
|
-
Analyte: "Purchase",
|
|
319
|
-
ReportedValue: "drug store",
|
|
320
|
-
StoredValue: "drug store",
|
|
321
|
-
Score: "0",
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
});
|
|
246
|
+
const profiles = await safeCdx.getTestProfilesByAccount(true);
|
|
325
247
|
```
|
|
326
248
|
|
|
327
|
-
|
|
249
|
+
#### API request sent internally
|
|
328
250
|
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"Data": {
|
|
254
|
+
"IncludeRegisterTestDetails": true
|
|
255
|
+
}
|
|
256
|
+
}
|
|
333
257
|
```
|
|
334
258
|
|
|
335
|
-
|
|
259
|
+
#### API response example
|
|
336
260
|
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"Data": {
|
|
264
|
+
"success": true,
|
|
265
|
+
"data": [
|
|
266
|
+
{
|
|
267
|
+
"gtin": "810172700093",
|
|
268
|
+
"productName": "Speedy Swab COVID-19 + Flu Self-Test",
|
|
269
|
+
"description": "",
|
|
270
|
+
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/4307c803740644ab8c4594f69783c1d8-638694157517533356.png",
|
|
271
|
+
"language": "en",
|
|
272
|
+
"registerTestDetail": {
|
|
273
|
+
"title": "Scan the barcode",
|
|
274
|
+
"description": "<p><span style=\"font-size: 12pt; font-family: Avenir, -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;\">Hold your phone over the barcode on the box.</span></p>",
|
|
275
|
+
"buttonTitle": "Scan Code",
|
|
276
|
+
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/1ccc293f924a4c5bb2c5fc76f474c625-638769599179275771.png"
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"gtin": "860002060439",
|
|
281
|
+
"productName": "Winx UTI Test + Treat",
|
|
282
|
+
"description": "",
|
|
283
|
+
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/36649cb6377c435a9e4f83af0f2fea46-639058689126409862.png",
|
|
284
|
+
"language": "en",
|
|
285
|
+
"registerTestDetail": {
|
|
286
|
+
"title": "",
|
|
287
|
+
"description": "<p></p>",
|
|
288
|
+
"buttonTitle": "Scan Barcode on the Box",
|
|
289
|
+
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/ad72c9b8c3324c1cb7aa9dbf29e46d64-638905990491115782.png"
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"gtin": "850024942325",
|
|
294
|
+
"productName": "Vaginal Health pH Test + Treat",
|
|
295
|
+
"description": "",
|
|
296
|
+
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/3cebedbb69cb4455af33da5ab524ec93-639058688331122684.png",
|
|
297
|
+
"language": "en",
|
|
298
|
+
"registerTestDetail": {
|
|
299
|
+
"title": "",
|
|
300
|
+
"description": "<p></p>",
|
|
301
|
+
"buttonTitle": "Scan Barcode on the Box",
|
|
302
|
+
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/1475ae0004084d749ee2dfc9123af952-638905989776168388.png"
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
"message": "Success",
|
|
307
|
+
"code": 0
|
|
308
|
+
},
|
|
309
|
+
"ErrorMessage": null,
|
|
310
|
+
"IsOK": true
|
|
311
|
+
}
|
|
345
312
|
```
|
|
346
313
|
|
|
347
|
-
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### `getTestProfileByGTIN(...)`
|
|
348
317
|
|
|
349
|
-
|
|
318
|
+
Resolves the Safe CDX test profile associated with a GTIN barcode.
|
|
350
319
|
|
|
351
|
-
|
|
320
|
+
#### Signature
|
|
352
321
|
|
|
353
322
|
```ts
|
|
354
|
-
|
|
355
|
-
gtin: undefined,
|
|
356
|
-
userTestResultId: undefined,
|
|
357
|
-
preSignedURL: undefined,
|
|
358
|
-
imageOfCaptureId: undefined,
|
|
359
|
-
};
|
|
323
|
+
safeCdx.getTestProfileByGTIN(gtin: string): Promise<APIResponse<GetTestProfileByGTINData>>
|
|
360
324
|
```
|
|
361
325
|
|
|
362
|
-
|
|
326
|
+
#### Parameters
|
|
363
327
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
- `imageOfCaptureId`: upload identifier returned after creating the upload URL
|
|
328
|
+
| Parameter | Type | Required | Description |
|
|
329
|
+
|---|---|---:|---|
|
|
330
|
+
| `gtin` | `string` | Yes | GTIN barcode value used to resolve the test profile. |
|
|
368
331
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
## Public Methods
|
|
372
|
-
|
|
373
|
-
### getTestProfileByGTIN
|
|
332
|
+
#### Usage
|
|
374
333
|
|
|
375
334
|
```ts
|
|
376
|
-
const profile = await safeCdx.getTestProfileByGTIN(
|
|
335
|
+
const profile = await safeCdx.getTestProfileByGTIN("850024942325");
|
|
377
336
|
```
|
|
378
337
|
|
|
379
|
-
Resolves a test profile by GTIN barcode.
|
|
380
338
|
|
|
381
|
-
#### API
|
|
339
|
+
#### API response example
|
|
382
340
|
|
|
383
341
|
```json
|
|
384
342
|
{
|
|
@@ -568,92 +526,55 @@ Resolves a test profile by GTIN barcode.
|
|
|
568
526
|
}
|
|
569
527
|
```
|
|
570
528
|
|
|
571
|
-
|
|
529
|
+
---
|
|
572
530
|
|
|
573
|
-
|
|
574
|
-
const profiles = await safeCdx.getTestProfilesByAccount();
|
|
575
|
-
```
|
|
531
|
+
### `createUploadUrl(...)`
|
|
576
532
|
|
|
577
|
-
|
|
533
|
+
Creates a pre-signed URL for uploading a test image.
|
|
578
534
|
|
|
579
|
-
|
|
535
|
+
#### Signature
|
|
580
536
|
|
|
581
537
|
```ts
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
538
|
+
safeCdx.createUploadUrl(
|
|
539
|
+
userTestResultId: string,
|
|
540
|
+
gtin: string,
|
|
541
|
+
imageType?: string
|
|
542
|
+
): Promise<APIResponse<CreateUploadUrlData>>
|
|
585
543
|
```
|
|
586
544
|
|
|
587
|
-
####
|
|
545
|
+
#### Parameters
|
|
588
546
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
{
|
|
595
|
-
"gtin": "810172700093",
|
|
596
|
-
"productName": "Speedy Swab COVID-19 + Flu Self-Test",
|
|
597
|
-
"description": "",
|
|
598
|
-
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/4307c803740644ab8c4594f69783c1d8-638694157517533356.png",
|
|
599
|
-
"language": "en",
|
|
600
|
-
"registerTestDetail": {
|
|
601
|
-
"title": "Scan the barcode",
|
|
602
|
-
"description": "<p><span style=\"font-size: 12pt; font-family: Avenir, -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;\">Hold your phone over the barcode on the box.</span></p>",
|
|
603
|
-
"buttonTitle": "Scan Code",
|
|
604
|
-
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/1ccc293f924a4c5bb2c5fc76f474c625-638769599179275771.png"
|
|
605
|
-
}
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
"gtin": "860002060439",
|
|
609
|
-
"productName": "Winx UTI Test + Treat",
|
|
610
|
-
"description": "",
|
|
611
|
-
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/36649cb6377c435a9e4f83af0f2fea46-639058689126409862.png",
|
|
612
|
-
"language": "en",
|
|
613
|
-
"registerTestDetail": {
|
|
614
|
-
"title": "",
|
|
615
|
-
"description": "<p></p>",
|
|
616
|
-
"buttonTitle": "Scan Barcode on the Box",
|
|
617
|
-
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/ad72c9b8c3324c1cb7aa9dbf29e46d64-638905990491115782.png"
|
|
618
|
-
}
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
"gtin": "850024942325",
|
|
622
|
-
"productName": "Vaginal Health pH Test + Treat",
|
|
623
|
-
"description": "",
|
|
624
|
-
"testKitImageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/3cebedbb69cb4455af33da5ab524ec93-639058688331122684.png",
|
|
625
|
-
"language": "en",
|
|
626
|
-
"registerTestDetail": {
|
|
627
|
-
"title": "",
|
|
628
|
-
"description": "<p></p>",
|
|
629
|
-
"buttonTitle": "Scan Barcode on the Box",
|
|
630
|
-
"imageURL": "https://safe-content-cache-us-west-2-quality-speed.s3-us-west-2.amazonaws.com/LabTestOrderable/RegisterTest/Image/1475ae0004084d749ee2dfc9123af952-638905989776168388.png"
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
],
|
|
634
|
-
"message": "Success",
|
|
635
|
-
"code": 0
|
|
636
|
-
},
|
|
637
|
-
"ErrorMessage": null,
|
|
638
|
-
"IsOK": true
|
|
639
|
-
}
|
|
640
|
-
```
|
|
547
|
+
| Parameter | Type | Required | Description |
|
|
548
|
+
|---|---|---:|---|
|
|
549
|
+
| `userTestResultId` | `string` | Yes | Test result identifier reused through the workflow. |
|
|
550
|
+
| `gtin` | `string` | Yes | GTIN associated with the selected test. |
|
|
551
|
+
| `imageType` | `string` | No | Image type used in upload metadata. Defaults to `"jpg"`. |
|
|
641
552
|
|
|
642
|
-
|
|
553
|
+
#### Usage
|
|
643
554
|
|
|
644
555
|
```ts
|
|
645
556
|
const upload = await safeCdx.createUploadUrl(
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
557
|
+
userTestResultId,
|
|
558
|
+
gtin,
|
|
559
|
+
"jpg"
|
|
649
560
|
);
|
|
650
561
|
```
|
|
651
562
|
|
|
652
|
-
|
|
563
|
+
#### API request sent internally
|
|
653
564
|
|
|
654
|
-
|
|
565
|
+
```json
|
|
566
|
+
{
|
|
567
|
+
"Data": {
|
|
568
|
+
"Gtin": "<GTIN>",
|
|
569
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>",
|
|
570
|
+
"Metadata": {
|
|
571
|
+
"ImageType": "jpg"
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
655
576
|
|
|
656
|
-
#### API
|
|
577
|
+
#### API response example
|
|
657
578
|
|
|
658
579
|
```json
|
|
659
580
|
{
|
|
@@ -670,30 +591,92 @@ Creates a pre-signed image upload URL.
|
|
|
670
591
|
}
|
|
671
592
|
```
|
|
672
593
|
|
|
673
|
-
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
### `uploadImage(...)`
|
|
597
|
+
|
|
598
|
+
Uploads an image directly to the pre-signed URL returned by `createUploadUrl(...)`. This method does not call a Safe CDX API route and does not send Health Cloud authentication headers.
|
|
599
|
+
|
|
600
|
+
#### Signature
|
|
674
601
|
|
|
675
602
|
```ts
|
|
676
|
-
|
|
603
|
+
safeCdx.uploadImage(
|
|
604
|
+
preSignedURL: string,
|
|
605
|
+
image: BodyInit,
|
|
606
|
+
contentType?: string
|
|
607
|
+
): Promise<void>
|
|
677
608
|
```
|
|
678
609
|
|
|
679
|
-
|
|
610
|
+
#### Parameters
|
|
680
611
|
|
|
681
|
-
|
|
612
|
+
| Parameter | Type | Required | Description |
|
|
613
|
+
|---|---|---:|---|
|
|
614
|
+
| `preSignedURL` | `string` | Yes | Temporary storage upload URL returned by `createUploadUrl(...)`. |
|
|
615
|
+
| `image` | `BodyInit` | Yes | Raw image body, such as a `File`, `Blob` or compatible upload body. |
|
|
616
|
+
| `contentType` | `string` | No | MIME type of the uploaded file. Defaults to `"image/jpeg"`. |
|
|
682
617
|
|
|
683
|
-
|
|
618
|
+
#### Usage
|
|
684
619
|
|
|
685
620
|
```ts
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
621
|
+
await safeCdx.uploadImage(
|
|
622
|
+
preSignedURL,
|
|
623
|
+
imageBody,
|
|
624
|
+
"image/jpeg"
|
|
689
625
|
);
|
|
690
626
|
```
|
|
691
627
|
|
|
692
|
-
|
|
628
|
+
A failed direct upload throws `SafeCDXError`.
|
|
629
|
+
|
|
630
|
+
---
|
|
693
631
|
|
|
694
|
-
|
|
632
|
+
### `updateCvmlStatus(...)`
|
|
695
633
|
|
|
696
|
-
|
|
634
|
+
Updates the CVML processing status for a captured image. This endpoint returns `SafeAPIResponse<T>` directly.
|
|
635
|
+
|
|
636
|
+
#### Signature
|
|
637
|
+
|
|
638
|
+
```ts
|
|
639
|
+
safeCdx.updateCvmlStatus(
|
|
640
|
+
imageOfCaptureId: string,
|
|
641
|
+
cvmlStatus: string
|
|
642
|
+
): Promise<UpdateCvmlStatusResponse>
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
`UpdateCvmlStatusResponse` is:
|
|
646
|
+
|
|
647
|
+
```ts
|
|
648
|
+
type UpdateCvmlStatusResponse =
|
|
649
|
+
SafeAPIResponse<EntityReferenceData>;
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
#### Parameters
|
|
653
|
+
|
|
654
|
+
| Parameter | Type | Required | Description |
|
|
655
|
+
|---|---|---:|---|
|
|
656
|
+
| `imageOfCaptureId` | `string` | Yes | Identifier returned in the image upload metadata. |
|
|
657
|
+
| `cvmlStatus` | `string` | Yes | CVML processing status to apply, such as `"ImageProcessing"`. |
|
|
658
|
+
|
|
659
|
+
#### Usage
|
|
660
|
+
|
|
661
|
+
```ts
|
|
662
|
+
const response = await safeCdx.updateCvmlStatus(
|
|
663
|
+
imageOfCaptureId,
|
|
664
|
+
"ImageProcessing"
|
|
665
|
+
);
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
#### API request sent internally
|
|
669
|
+
|
|
670
|
+
```json
|
|
671
|
+
{
|
|
672
|
+
"Data": {
|
|
673
|
+
"ImageOfCaptureId": "<IMAGE_OF_CAPTURE_ID>",
|
|
674
|
+
"CvmlStatus": "ImageProcessing"
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
#### API response example
|
|
697
680
|
|
|
698
681
|
```json
|
|
699
682
|
{
|
|
@@ -706,17 +689,40 @@ The client returns the received response directly without applying `ApiResponse`
|
|
|
706
689
|
}
|
|
707
690
|
```
|
|
708
691
|
|
|
709
|
-
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
### `getCvmlResults(...)`
|
|
695
|
+
|
|
696
|
+
Polls CVML results for a captured image. This endpoint returns `SafeAPIResponse<T>` directly.
|
|
697
|
+
|
|
698
|
+
#### Signature
|
|
699
|
+
|
|
700
|
+
```ts
|
|
701
|
+
safeCdx.getCvmlResults(
|
|
702
|
+
imageOfCaptureId: string
|
|
703
|
+
): Promise<GetCvmlResultsResponse>
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
`GetCvmlResultsResponse` is:
|
|
710
707
|
|
|
711
708
|
```ts
|
|
712
|
-
|
|
709
|
+
type GetCvmlResultsResponse =
|
|
710
|
+
SafeAPIResponse<CvmlResultsData>;
|
|
713
711
|
```
|
|
714
712
|
|
|
715
|
-
|
|
713
|
+
#### Parameters
|
|
716
714
|
|
|
717
|
-
|
|
715
|
+
| Parameter | Type | Required | Description |
|
|
716
|
+
|---|---|---:|---|
|
|
717
|
+
| `imageOfCaptureId` | `string` | Yes | Identifier of the captured image being processed. |
|
|
718
718
|
|
|
719
|
-
####
|
|
719
|
+
#### Usage
|
|
720
|
+
|
|
721
|
+
```ts
|
|
722
|
+
const response = await safeCdx.getCvmlResults(imageOfCaptureId);
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
#### API response example
|
|
720
726
|
|
|
721
727
|
```json
|
|
722
728
|
{
|
|
@@ -760,33 +766,56 @@ The client returns the received response directly without applying `ApiResponse`
|
|
|
760
766
|
}
|
|
761
767
|
```
|
|
762
768
|
|
|
763
|
-
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
### `getPendingResults(...)`
|
|
772
|
+
|
|
773
|
+
Returns pending or incomplete test results for the authenticated patient.
|
|
774
|
+
|
|
775
|
+
#### Signature
|
|
764
776
|
|
|
765
777
|
```ts
|
|
766
|
-
|
|
778
|
+
safeCdx.getPendingResults(
|
|
779
|
+
excludeStatus?: string
|
|
780
|
+
): Promise<APIResponse<GetPendingResultsData>>
|
|
767
781
|
```
|
|
768
782
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
When called without an argument, the SDK sends:
|
|
783
|
+
`GetPendingResultsData` is:
|
|
772
784
|
|
|
773
785
|
```ts
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
ExcludeStatus: "Invalid,Canceled",
|
|
777
|
-
},
|
|
778
|
-
}
|
|
786
|
+
type GetPendingResultsData =
|
|
787
|
+
SafeAPIResponse<TestResultSummary[]>;
|
|
779
788
|
```
|
|
780
789
|
|
|
781
|
-
|
|
790
|
+
#### Parameters
|
|
791
|
+
|
|
792
|
+
| Parameter | Type | Required | Description |
|
|
793
|
+
|---|---|---:|---|
|
|
794
|
+
| `excludeStatus` | `string` | No | Comma-separated statuses excluded from the returned results. Defaults to `"Invalid,Canceled"`. |
|
|
795
|
+
|
|
796
|
+
#### Usage
|
|
782
797
|
|
|
783
798
|
```ts
|
|
784
|
-
const pending = await safeCdx.getPendingResults(
|
|
785
|
-
ExcludeStatus: "Invalid,Canceled",
|
|
786
|
-
});
|
|
799
|
+
const pending = await safeCdx.getPendingResults();
|
|
787
800
|
```
|
|
788
801
|
|
|
789
|
-
|
|
802
|
+
```ts
|
|
803
|
+
const pending = await safeCdx.getPendingResults(
|
|
804
|
+
"Invalid,Canceled"
|
|
805
|
+
);
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
#### API request sent internally
|
|
809
|
+
|
|
810
|
+
```json
|
|
811
|
+
{
|
|
812
|
+
"Data": {
|
|
813
|
+
"ExcludeStatus": "Invalid,Canceled"
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
#### API response example
|
|
790
819
|
|
|
791
820
|
```json
|
|
792
821
|
{
|
|
@@ -866,25 +895,54 @@ const pending = await safeCdx.getPendingResults({
|
|
|
866
895
|
}
|
|
867
896
|
```
|
|
868
897
|
|
|
869
|
-
|
|
898
|
+
---
|
|
899
|
+
|
|
900
|
+
### `getLastResults(...)`
|
|
901
|
+
|
|
902
|
+
Returns the most recent test result for the authenticated patient.
|
|
903
|
+
|
|
904
|
+
#### Signature
|
|
905
|
+
|
|
906
|
+
```ts
|
|
907
|
+
safeCdx.getLastResults(
|
|
908
|
+
excludeStatus?: string
|
|
909
|
+
): Promise<APIResponse<GetLastResultsData>>
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
`GetLastResultsData` is:
|
|
870
913
|
|
|
871
914
|
```ts
|
|
872
|
-
|
|
915
|
+
type GetLastResultsData =
|
|
916
|
+
SafeAPIResponse<TestResultDetails>;
|
|
873
917
|
```
|
|
874
918
|
|
|
875
|
-
|
|
919
|
+
#### Parameters
|
|
920
|
+
|
|
921
|
+
| Parameter | Type | Required | Description |
|
|
922
|
+
|---|---|---:|---|
|
|
923
|
+
| `excludeStatus` | `string` | No | Status excluded from the returned result. Defaults to `"Invalid"`. |
|
|
876
924
|
|
|
877
|
-
|
|
925
|
+
#### Usage
|
|
878
926
|
|
|
879
927
|
```ts
|
|
928
|
+
const lastResult = await safeCdx.getLastResults();
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
```ts
|
|
932
|
+
const lastResult = await safeCdx.getLastResults("Invalid");
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
#### API request sent internally
|
|
936
|
+
|
|
937
|
+
```json
|
|
880
938
|
{
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
939
|
+
"Data": {
|
|
940
|
+
"ExcludeStatus": "Invalid"
|
|
941
|
+
}
|
|
884
942
|
}
|
|
885
943
|
```
|
|
886
944
|
|
|
887
|
-
#### API
|
|
945
|
+
#### API response example
|
|
888
946
|
|
|
889
947
|
```json
|
|
890
948
|
{
|
|
@@ -1028,25 +1086,54 @@ When called without an argument, the SDK sends:
|
|
|
1028
1086
|
}
|
|
1029
1087
|
```
|
|
1030
1088
|
|
|
1031
|
-
|
|
1089
|
+
---
|
|
1090
|
+
|
|
1091
|
+
### `getTestHistory(...)`
|
|
1092
|
+
|
|
1093
|
+
Returns test result history for the authenticated patient.
|
|
1094
|
+
|
|
1095
|
+
#### Signature
|
|
1032
1096
|
|
|
1033
1097
|
```ts
|
|
1034
|
-
|
|
1098
|
+
safeCdx.getTestHistory(
|
|
1099
|
+
excludeStatus?: string
|
|
1100
|
+
): Promise<APIResponse<GetTestHistoryData>>
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
`GetTestHistoryData` is:
|
|
1104
|
+
|
|
1105
|
+
```ts
|
|
1106
|
+
type GetTestHistoryData =
|
|
1107
|
+
SafeAPIResponse<TestResultSummary[]>;
|
|
1035
1108
|
```
|
|
1036
1109
|
|
|
1037
|
-
|
|
1110
|
+
#### Parameters
|
|
1111
|
+
|
|
1112
|
+
| Parameter | Type | Required | Description |
|
|
1113
|
+
|---|---|---:|---|
|
|
1114
|
+
| `excludeStatus` | `string` | No | Status excluded from the returned history. Defaults to `"Invalid"`. |
|
|
1038
1115
|
|
|
1039
|
-
|
|
1116
|
+
#### Usage
|
|
1040
1117
|
|
|
1041
1118
|
```ts
|
|
1119
|
+
const history = await safeCdx.getTestHistory();
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
```ts
|
|
1123
|
+
const history = await safeCdx.getTestHistory("Invalid");
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
#### API request sent internally
|
|
1127
|
+
|
|
1128
|
+
```json
|
|
1042
1129
|
{
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1130
|
+
"Data": {
|
|
1131
|
+
"ExcludeStatus": "Invalid"
|
|
1132
|
+
}
|
|
1046
1133
|
}
|
|
1047
1134
|
```
|
|
1048
1135
|
|
|
1049
|
-
#### API
|
|
1136
|
+
#### API response example
|
|
1050
1137
|
|
|
1051
1138
|
```json
|
|
1052
1139
|
{
|
|
@@ -1087,17 +1174,50 @@ When called without an argument, the SDK sends:
|
|
|
1087
1174
|
}
|
|
1088
1175
|
```
|
|
1089
1176
|
|
|
1090
|
-
|
|
1177
|
+
---
|
|
1178
|
+
|
|
1179
|
+
### `getResultDetails(...)`
|
|
1180
|
+
|
|
1181
|
+
Returns detailed data for a specific test attempt. This endpoint returns `SafeAPIResponse<T>` directly.
|
|
1182
|
+
|
|
1183
|
+
#### Signature
|
|
1184
|
+
|
|
1185
|
+
```ts
|
|
1186
|
+
safeCdx.getResultDetails(
|
|
1187
|
+
userTestResultId: string
|
|
1188
|
+
): Promise<GetResultDetailsResponse>
|
|
1189
|
+
```
|
|
1190
|
+
|
|
1191
|
+
`GetResultDetailsResponse` is:
|
|
1192
|
+
|
|
1193
|
+
```ts
|
|
1194
|
+
type GetResultDetailsResponse =
|
|
1195
|
+
SafeAPIResponse<TestResultDetails>;
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
#### Parameters
|
|
1199
|
+
|
|
1200
|
+
| Parameter | Type | Required | Description |
|
|
1201
|
+
|---|---|---:|---|
|
|
1202
|
+
| `userTestResultId` | `string` | Yes | Identifier of the test attempt. |
|
|
1203
|
+
|
|
1204
|
+
#### Usage
|
|
1091
1205
|
|
|
1092
1206
|
```ts
|
|
1093
1207
|
const details = await safeCdx.getResultDetails(userTestResultId);
|
|
1094
1208
|
```
|
|
1095
1209
|
|
|
1096
|
-
|
|
1210
|
+
#### API request sent internally
|
|
1097
1211
|
|
|
1098
|
-
|
|
1212
|
+
```json
|
|
1213
|
+
{
|
|
1214
|
+
"Data": {
|
|
1215
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>"
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
```
|
|
1099
1219
|
|
|
1100
|
-
#### API
|
|
1220
|
+
#### API response example
|
|
1101
1221
|
|
|
1102
1222
|
```json
|
|
1103
1223
|
{
|
|
@@ -1231,17 +1351,47 @@ The client returns the received response directly without applying `ApiResponse`
|
|
|
1231
1351
|
}
|
|
1232
1352
|
```
|
|
1233
1353
|
|
|
1234
|
-
|
|
1354
|
+
---
|
|
1355
|
+
|
|
1356
|
+
### `getResultPdf(...)`
|
|
1357
|
+
|
|
1358
|
+
Requests the PDF result for a specific test attempt.
|
|
1359
|
+
|
|
1360
|
+
#### Signature
|
|
1235
1361
|
|
|
1236
1362
|
```ts
|
|
1237
|
-
|
|
1238
|
-
UserTestResultId: userTestResultId,
|
|
1239
|
-
});
|
|
1363
|
+
safeCdx.getResultPdf(userTestResultId: string): Promise<APIResponse<GetResultPdfData>>
|
|
1240
1364
|
```
|
|
1241
1365
|
|
|
1242
|
-
|
|
1366
|
+
`GetResultPdfData` is:
|
|
1367
|
+
|
|
1368
|
+
```ts
|
|
1369
|
+
type GetResultPdfData = SafeAPIResponse<string>;
|
|
1370
|
+
```
|
|
1243
1371
|
|
|
1244
|
-
####
|
|
1372
|
+
#### Parameters
|
|
1373
|
+
|
|
1374
|
+
| Parameter | Type | Required | Description |
|
|
1375
|
+
|---|---|---:|---|
|
|
1376
|
+
| `userTestResultId` | `string` | Yes | Identifier of the test attempt. |
|
|
1377
|
+
|
|
1378
|
+
#### Usage
|
|
1379
|
+
|
|
1380
|
+
```ts
|
|
1381
|
+
const pdf = await safeCdx.getResultPdf(userTestResultId);
|
|
1382
|
+
```
|
|
1383
|
+
|
|
1384
|
+
#### API request sent internally
|
|
1385
|
+
|
|
1386
|
+
```json
|
|
1387
|
+
{
|
|
1388
|
+
"Data": {
|
|
1389
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>"
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
```
|
|
1393
|
+
|
|
1394
|
+
#### API response example
|
|
1245
1395
|
|
|
1246
1396
|
```json
|
|
1247
1397
|
{
|
|
@@ -1256,17 +1406,50 @@ Requests the PDF result for a specific test result.
|
|
|
1256
1406
|
}
|
|
1257
1407
|
```
|
|
1258
1408
|
|
|
1259
|
-
|
|
1409
|
+
---
|
|
1410
|
+
|
|
1411
|
+
### `getImageCaptureUrl(...)`
|
|
1412
|
+
|
|
1413
|
+
Requests image capture data for a specific test attempt. This endpoint returns `SafeAPIResponse<T>` directly.
|
|
1414
|
+
|
|
1415
|
+
#### Signature
|
|
1416
|
+
|
|
1417
|
+
```ts
|
|
1418
|
+
safeCdx.getImageCaptureUrl(
|
|
1419
|
+
userTestResultId: string
|
|
1420
|
+
): Promise<GetImageCaptureUrlResponse>
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
`GetImageCaptureUrlResponse` is:
|
|
1424
|
+
|
|
1425
|
+
```ts
|
|
1426
|
+
type GetImageCaptureUrlResponse =
|
|
1427
|
+
SafeAPIResponse<string>;
|
|
1428
|
+
```
|
|
1429
|
+
|
|
1430
|
+
#### Parameters
|
|
1431
|
+
|
|
1432
|
+
| Parameter | Type | Required | Description |
|
|
1433
|
+
|---|---|---:|---|
|
|
1434
|
+
| `userTestResultId` | `string` | Yes | Identifier of the test attempt. |
|
|
1435
|
+
|
|
1436
|
+
#### Usage
|
|
1260
1437
|
|
|
1261
1438
|
```ts
|
|
1262
1439
|
const imageUrl = await safeCdx.getImageCaptureUrl(userTestResultId);
|
|
1263
1440
|
```
|
|
1264
1441
|
|
|
1265
|
-
|
|
1442
|
+
#### API request sent internally
|
|
1266
1443
|
|
|
1267
|
-
|
|
1444
|
+
```json
|
|
1445
|
+
{
|
|
1446
|
+
"Data": {
|
|
1447
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>"
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
```
|
|
1268
1451
|
|
|
1269
|
-
#### API
|
|
1452
|
+
#### API response example
|
|
1270
1453
|
|
|
1271
1454
|
```json
|
|
1272
1455
|
{
|
|
@@ -1277,21 +1460,60 @@ The client returns the received response directly without applying `ApiResponse`
|
|
|
1277
1460
|
}
|
|
1278
1461
|
```
|
|
1279
1462
|
|
|
1280
|
-
|
|
1463
|
+
---
|
|
1464
|
+
|
|
1465
|
+
### `resumeFlow(...)`
|
|
1466
|
+
|
|
1467
|
+
Marks a test attempt as resumed or not resumed.
|
|
1468
|
+
|
|
1469
|
+
#### Signature
|
|
1281
1470
|
|
|
1282
1471
|
```ts
|
|
1283
|
-
|
|
1472
|
+
safeCdx.resumeFlow(
|
|
1473
|
+
userTestResultId: string,
|
|
1474
|
+
resumed?: boolean
|
|
1475
|
+
): Promise<APIResponse<ResumeFlowData>>
|
|
1284
1476
|
```
|
|
1285
1477
|
|
|
1286
|
-
|
|
1478
|
+
`ResumeFlowData` is:
|
|
1479
|
+
|
|
1480
|
+
```ts
|
|
1481
|
+
type ResumeFlowData =
|
|
1482
|
+
SafeAPIResponse<ResumeFlowResult>;
|
|
1483
|
+
```
|
|
1287
1484
|
|
|
1288
|
-
|
|
1485
|
+
#### Parameters
|
|
1486
|
+
|
|
1487
|
+
| Parameter | Type | Required | Description |
|
|
1488
|
+
|---|---|---:|---|
|
|
1489
|
+
| `userTestResultId` | `string` | Yes | Identifier of the test attempt. |
|
|
1490
|
+
| `resumed` | `boolean` | No | Resume state sent to the API. Defaults to `true`. |
|
|
1491
|
+
|
|
1492
|
+
#### Usage
|
|
1289
1493
|
|
|
1290
1494
|
```ts
|
|
1291
|
-
const
|
|
1495
|
+
const response = await safeCdx.resumeFlow(userTestResultId);
|
|
1292
1496
|
```
|
|
1293
1497
|
|
|
1294
|
-
|
|
1498
|
+
```ts
|
|
1499
|
+
const response = await safeCdx.resumeFlow(
|
|
1500
|
+
userTestResultId,
|
|
1501
|
+
true
|
|
1502
|
+
);
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
#### API request sent internally
|
|
1506
|
+
|
|
1507
|
+
```json
|
|
1508
|
+
{
|
|
1509
|
+
"Data": {
|
|
1510
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>",
|
|
1511
|
+
"Resumed": true
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
```
|
|
1515
|
+
|
|
1516
|
+
#### API response example
|
|
1295
1517
|
|
|
1296
1518
|
```json
|
|
1297
1519
|
{
|
|
@@ -1313,17 +1535,69 @@ const resumed = await safeCdx.resumeFlow(userTestResultId, true);
|
|
|
1313
1535
|
}
|
|
1314
1536
|
```
|
|
1315
1537
|
|
|
1316
|
-
|
|
1538
|
+
---
|
|
1539
|
+
|
|
1540
|
+
### `submitAnswers(...)`
|
|
1541
|
+
|
|
1542
|
+
Submits analyte answers for a test attempt. This method accepts a structured object because the request contains a collection of answer entries.
|
|
1543
|
+
|
|
1544
|
+
#### Signature
|
|
1545
|
+
|
|
1546
|
+
```ts
|
|
1547
|
+
safeCdx.submitAnswers(
|
|
1548
|
+
submission: SubmitAnswersRequest
|
|
1549
|
+
): Promise<APIResponse<SubmitAnswersData>>
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
`SubmitAnswersData` is:
|
|
1553
|
+
|
|
1554
|
+
```ts
|
|
1555
|
+
type SubmitAnswersData =
|
|
1556
|
+
SafeAPIResponse<EntityReferenceData>;
|
|
1557
|
+
```
|
|
1558
|
+
|
|
1559
|
+
#### Parameters
|
|
1560
|
+
|
|
1561
|
+
| Parameter | Type | Required | Description |
|
|
1562
|
+
|---|---|---:|---|
|
|
1563
|
+
| `submission.UserTestResultId` | `string` | Yes | Identifier of the test attempt. |
|
|
1564
|
+
| `submission.Result` | `AnswerResult[]` | Yes | Answer entries submitted for the test attempt. |
|
|
1565
|
+
|
|
1566
|
+
#### Usage
|
|
1317
1567
|
|
|
1318
1568
|
```ts
|
|
1319
|
-
const
|
|
1569
|
+
const response = await safeCdx.submitAnswers({
|
|
1570
|
+
UserTestResultId: userTestResultId,
|
|
1571
|
+
Result: [
|
|
1572
|
+
{
|
|
1573
|
+
Analyte: "Purchase",
|
|
1574
|
+
ReportedValue: "drug store",
|
|
1575
|
+
StoredValue: "drug store",
|
|
1576
|
+
Score: "0"
|
|
1577
|
+
}
|
|
1578
|
+
]
|
|
1579
|
+
});
|
|
1320
1580
|
```
|
|
1321
1581
|
|
|
1322
|
-
|
|
1582
|
+
#### API request sent internally
|
|
1323
1583
|
|
|
1324
|
-
|
|
1584
|
+
```json
|
|
1585
|
+
{
|
|
1586
|
+
"Data": {
|
|
1587
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>",
|
|
1588
|
+
"Result": [
|
|
1589
|
+
{
|
|
1590
|
+
"Analyte": "Purchase",
|
|
1591
|
+
"ReportedValue": "drug store",
|
|
1592
|
+
"StoredValue": "drug store",
|
|
1593
|
+
"Score": "0"
|
|
1594
|
+
}
|
|
1595
|
+
]
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
```
|
|
1325
1599
|
|
|
1326
|
-
#### API
|
|
1600
|
+
#### API response example
|
|
1327
1601
|
|
|
1328
1602
|
```json
|
|
1329
1603
|
{
|
|
@@ -1340,36 +1614,48 @@ Submits analyte answers for a test attempt.
|
|
|
1340
1614
|
}
|
|
1341
1615
|
```
|
|
1342
1616
|
|
|
1343
|
-
|
|
1617
|
+
---
|
|
1618
|
+
|
|
1619
|
+
### `finalizeTest(...)`
|
|
1620
|
+
|
|
1621
|
+
Finalizes the test attempt identified by `userTestResultId`.
|
|
1622
|
+
|
|
1623
|
+
#### Signature
|
|
1344
1624
|
|
|
1345
1625
|
```ts
|
|
1346
|
-
|
|
1347
|
-
UserTestResultId: userTestResultId,
|
|
1348
|
-
});
|
|
1626
|
+
safeCdx.finalizeTest(userTestResultId: string): Promise<APIResponse<FinalizeTestData>>
|
|
1349
1627
|
```
|
|
1350
1628
|
|
|
1351
|
-
|
|
1629
|
+
#### Parameters
|
|
1630
|
+
|
|
1631
|
+
| Parameter | Type | Required | Description |
|
|
1632
|
+
|---|---|---:|---|
|
|
1633
|
+
| `userTestResultId` | `string` | Yes | Identifier of the test attempt to finalize. |
|
|
1352
1634
|
|
|
1353
|
-
|
|
1635
|
+
#### Usage
|
|
1354
1636
|
|
|
1355
1637
|
```ts
|
|
1638
|
+
const response = await safeCdx.finalizeTest(userTestResultId);
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
#### API request sent internally
|
|
1642
|
+
|
|
1643
|
+
```json
|
|
1356
1644
|
{
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1645
|
+
"Data": {
|
|
1646
|
+
"UserTestResultId": "<USER_TEST_RESULT_ID>"
|
|
1647
|
+
}
|
|
1360
1648
|
}
|
|
1361
1649
|
```
|
|
1362
1650
|
|
|
1363
1651
|
|
|
1364
1652
|
## Notes
|
|
1365
1653
|
|
|
1366
|
-
-
|
|
1367
|
-
- The connector uses `HCLoginClient` for authenticated
|
|
1654
|
+
- `HCSafeCDXClient` documents the authenticated patient workflow supported by the current client.
|
|
1655
|
+
- The connector does not perform login; it uses `HCLoginClient` for authenticated patient headers.
|
|
1656
|
+
- Safe CDX uses its own service URL derived from `loginClient.getEnvironment()`.
|
|
1368
1657
|
- The connector does not use `loginClient.getBaseUrl()` for Safe CDX API routes.
|
|
1369
|
-
- Safe CDX derives its service base URL from `loginClient.getEnvironment()`.
|
|
1370
|
-
- Standard Safe CDX API methods use the shared `HttpClient`.
|
|
1371
1658
|
- POST payloads are wrapped internally as `{ Data: payload }`.
|
|
1372
|
-
-
|
|
1373
|
-
-
|
|
1374
|
-
-
|
|
1375
|
-
- Pre-signed URLs are time-bound and should not be logged in production.
|
|
1659
|
+
- Patient tenant and identity context are supplied by the backend from the authenticated request.
|
|
1660
|
+
- API responses are returned in their endpoint-defined shape without being unwrapped or transformed by `HCSafeCDXClient`.
|
|
1661
|
+
- Direct image upload uses the pre-signed URL and sends the raw file body without Health Cloud authorization headers.
|