Skip to content

Commit 9f581ab

Browse files
feat: add delete API
1 parent c3ca8d7 commit 9f581ab

File tree

7 files changed

+330
-27
lines changed

7 files changed

+330
-27
lines changed

readme.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,52 @@ For more information, see the [Server API documentation](https://dev.fingerprint
404404
}
405405
```
406406

407+
---
408+
409+
### `deleteVisitorData(visitorId: string): Promise<void>`
410+
411+
Request deleting all data associated with the specified visitor ID. This
412+
API is useful for compliance with privacy regulations.
413+
414+
All delete requests are queued:
415+
416+
417+
* Recent data (10 days or newer) belonging to the specified visitor will
418+
be deleted within 24 hours.
419+
420+
* Data from older (11 days or more) identification events will be
421+
deleted after 90 days.
422+
423+
424+
If you are interested in using this API, please [contact our support
425+
team](https://fingerprint.com/support/) to activate it for you.
426+
Otherwise, you will receive a 403.
427+
428+
#### Usage
429+
430+
```js
431+
client
432+
.deleteVisitorData('<visitorId>')
433+
.then(() => {
434+
// Data deletion request was successfully queued
435+
})
436+
.catch((error) => {
437+
if (error.status === 403 || error.status === 404) {
438+
console.log(error.error);
439+
}
440+
});
441+
```
442+
443+
#### Returns
444+
445+
- `Promise<void>` - promise that resolves when the deletion request is successfully queued
446+
447+
#### Params
448+
449+
- `visitorId: string` - identifier of the visitor to delete
450+
451+
---
452+
407453
## Sealed results API Reference
408454

409455
### `unsealEventsResponse(sealedData: Buffer, decryptionKeys: DecryptionKey[]): Promise<EventResponse>`

src/generatedApiTypes.ts

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
export interface paths {
77
'/events/{request_id}': {
88
/**
9-
* Get event by requestId
10-
* @description This endpoint allows you to get a detailed analysis of an individual request.
9+
* Get event by request ID
10+
* @description Get a detailed analysis of an individual identification event, including Smart Signals.
1111
* **Only for Enterprise customers:** Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
1212
* It is highly recommended that you **ignore** the mobile signals for such requests.
1313
*
@@ -17,15 +17,26 @@ export interface paths {
1717
}
1818
'/visitors/{visitor_id}': {
1919
/**
20-
* Get visits by visitorId
21-
* @description This endpoint allows you to get a history of visits for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
20+
* Get visits by visitor ID
21+
* @description Get a history of visits (identification events) for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
2222
* Only information from the _Identification_ product is returned.
2323
*
2424
* #### Headers
2525
*
2626
* * `Retry-After` — Present in case of `429 Too many requests`. Indicates how long you should wait before making a follow-up request. The value is non-negative decimal integer indicating the seconds to delay after the response is received.
2727
*/
2828
get: operations['getVisits']
29+
/**
30+
* Delete data by visitor ID
31+
* @description Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations.
32+
* All delete requests are queued:
33+
*
34+
* * Recent data (10 days or newer) belonging to the specified visitor will be deleted within 24 hours.
35+
* * Data from older (11 days or more) identification events will be deleted after 90 days.
36+
*
37+
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to activate it for you. Otherwise, you will receive a 403.
38+
*/
39+
delete: operations['deleteVisitorData']
2940
}
3041
'/webhook': {
3142
/** @description Fake path to describe webhook format. More information about webhooks can be found in the [documentation](https://dev.fingerprint.com/docs/webhooks) */
@@ -133,20 +144,21 @@ export interface components {
133144
*/
134145
paginationKey?: string
135146
}
136-
ErrorEvent403Response: {
137-
/** ErrorEvent403ResponseError */
147+
ErrorCommon403Response: {
148+
/** Common403ErrorResponse */
138149
error?: {
139150
/**
140151
* @description Error code:
141152
* * `TokenRequired` - `Auth-API-Key` header is missing or empty
142-
* * `TokenNotFound` - subscription not found for specified secret key
143-
* * `SubscriptionNotActive` - subscription is not active
144-
* * `WrongRegion` - server and subscription region differ
153+
* * `TokenNotFound` - No Fingerprint application found for specified secret key
154+
* * `SubscriptionNotActive` - Fingerprint application is not active
155+
* * `WrongRegion` - server and application region differ
156+
* * `FeatureNotEnabled` - this feature (for example, Delete API) is not enabled for your application
145157
*
146158
* @example TokenRequired
147159
* @enum {string}
148160
*/
149-
code: 'TokenRequired' | 'TokenNotFound' | 'SubscriptionNotActive' | 'WrongRegion'
161+
code: 'TokenRequired' | 'TokenNotFound' | 'SubscriptionNotActive' | 'WrongRegion' | 'FeatureNotEnabled'
150162
/** @example secret key is required */
151163
message: string
152164
}
@@ -156,7 +168,7 @@ export interface components {
156168
error?: {
157169
/**
158170
* @description Error code:
159-
* * `RequestNotFound` - request not found for specified id
171+
* * `RequestNotFound` - The specified request ID was not found. It never existed, expired, or it has been deleted.
160172
*
161173
* @example RequestNotFound
162174
* @enum {string}
@@ -180,6 +192,20 @@ export interface components {
180192
*/
181193
error: string
182194
}
195+
ErrorVisitsDelete404Response: {
196+
/** ErrorVisitsDelete404ResponseError */
197+
error?: {
198+
/**
199+
* @description Error code: * `VisitorNotFound` - The specified visitor ID was not found. It never existed or it may have already been deleted.
200+
*
201+
* @example VisitorNotFound
202+
* @enum {string}
203+
*/
204+
code: 'VisitorNotFound'
205+
/** @example visitor not found */
206+
message: string
207+
}
208+
}
183209
WebhookVisit: {
184210
/** @example 3HNey93AkBW6CRbxV6xP */
185211
visitorId: string
@@ -762,7 +788,7 @@ export interface components {
762788
originCountry?: string
763789
methods: {
764790
/**
765-
* @description User's browser timezone doesn't match the timezone from which the request was originally made.
791+
* @description The browser timezone doesn't match the timezone inferred from the request IP address.
766792
* @example false
767793
*/
768794
timezoneMismatch: boolean
@@ -962,8 +988,8 @@ export type external = Record<string, never>
962988

963989
export interface operations {
964990
/**
965-
* Get event by requestId
966-
* @description This endpoint allows you to get a detailed analysis of an individual request.
991+
* Get event by request ID
992+
* @description Get a detailed analysis of an individual identification event, including Smart Signals.
967993
* **Only for Enterprise customers:** Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
968994
* It is highly recommended that you **ignore** the mobile signals for such requests.
969995
*
@@ -972,7 +998,7 @@ export interface operations {
972998
getEvent: {
973999
parameters: {
9741000
path: {
975-
/** @description The unique [identifier](https://dev.fingerprint.com/docs/js-agent#requestid) of each analysis request. */
1001+
/** @description The unique [identifier](https://dev.fingerprint.com/docs/js-agent#requestid) of each identification request. */
9761002
request_id: string
9771003
}
9781004
}
@@ -986,7 +1012,7 @@ export interface operations {
9861012
/** @description Forbidden */
9871013
403: {
9881014
content: {
989-
'application/json': components['schemas']['ErrorEvent403Response']
1015+
'application/json': components['schemas']['ErrorCommon403Response']
9901016
}
9911017
}
9921018
/** @description Not found */
@@ -998,8 +1024,8 @@ export interface operations {
9981024
}
9991025
}
10001026
/**
1001-
* Get visits by visitorId
1002-
* @description This endpoint allows you to get a history of visits for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
1027+
* Get visits by visitor ID
1028+
* @description Get a history of visits (identification events) for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
10031029
* Only information from the _Identification_ product is returned.
10041030
*
10051031
* #### Headers
@@ -1044,7 +1070,7 @@ export interface operations {
10441070
}
10451071
path: {
10461072
/**
1047-
* @description Unique identifier of the visitor issued by Fingerprint Pro.
1073+
* @description Unique [visitor identifier](https://dev.fingerprint.com/docs/js-agent#visitorid) issued by Fingerprint Pro.
10481074
* @example uYIm7Ksp5rf00SllPhFp
10491075
*/
10501076
visitor_id: string
@@ -1075,4 +1101,40 @@ export interface operations {
10751101
}
10761102
}
10771103
}
1104+
/**
1105+
* Delete data by visitor ID
1106+
* @description Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations.
1107+
* All delete requests are queued:
1108+
*
1109+
* * Recent data (10 days or newer) belonging to the specified visitor will be deleted within 24 hours.
1110+
* * Data from older (11 days or more) identification events will be deleted after 90 days.
1111+
*
1112+
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to activate it for you. Otherwise, you will receive a 403.
1113+
*/
1114+
deleteVisitorData: {
1115+
parameters: {
1116+
path: {
1117+
/** @description The [visitor ID](https://dev.fingerprint.com/docs/js-agent#visitorid) you want to delete. */
1118+
visitor_id: string
1119+
}
1120+
}
1121+
responses: {
1122+
/** @description OK. The visitor ID is scheduled for deletion. */
1123+
200: {
1124+
content: never
1125+
}
1126+
/** @description Forbidden. Access to this API is denied. */
1127+
403: {
1128+
content: {
1129+
'application/json': components['schemas']['ErrorCommon403Response']
1130+
}
1131+
}
1132+
/** @description Not found. The visitor ID cannot be found in this application's data. */
1133+
404: {
1134+
content: {
1135+
'application/json': components['schemas']['ErrorVisitsDelete404Response']
1136+
}
1137+
}
1138+
}
1139+
}
10781140
}

src/serverApiClient.ts

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { getEventUrl, getVisitorsUrl } from './urlUtils'
1+
import { getDeleteVisitorDataUrl, getEventUrl, getVisitorsUrl } from './urlUtils'
22
import {
3-
VisitorHistoryFilter,
4-
VisitorsResponse,
5-
Region,
6-
Options,
73
AuthenticationMode,
8-
EventResponse,
4+
DeleteVisitorError,
95
EventError,
6+
EventResponse,
7+
isDeleteVisitorError,
108
isEventError,
11-
VisitorsError,
129
isVisitorsError,
10+
Options,
11+
Region,
12+
VisitorHistoryFilter,
13+
VisitorsError,
1314
VisitorsError429,
15+
VisitorsResponse,
1416
} from './types'
1517

1618
export class FingerprintJsServerApiClient {
@@ -77,6 +79,51 @@ export class FingerprintJsServerApiClient {
7779
})
7880
}
7981

82+
/**
83+
* Delete data by visitor ID
84+
* Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. All delete requests are queued:
85+
* Recent data (10 days or newer) belonging to the specified visitor will be deleted within 24 hours. * Data from older (11 days or more) identification events will be deleted after 90 days.
86+
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to activate it for you. Otherwise, you will receive a 403.
87+
*
88+
* @param visitorId The [visitor ID](https://dev.fingerprint.com/docs/js-agent#visitorid) you want to delete.*
89+
*/
90+
public async deleteVisitorData(visitorId: string) {
91+
if (!visitorId) {
92+
throw TypeError('VisitorId is not set')
93+
}
94+
95+
const url =
96+
this.authenticationMode === AuthenticationMode.QueryParameter
97+
? getDeleteVisitorDataUrl(this.region, visitorId, this.apiKey)
98+
: getDeleteVisitorDataUrl(this.region, visitorId)
99+
100+
const headers = this.getHeaders()
101+
102+
await this.fetch(url, {
103+
method: 'DELETE',
104+
headers,
105+
})
106+
.then(async (response) => {
107+
if (response.status === 200) {
108+
return
109+
}
110+
111+
const jsonResponse = await response.json()
112+
113+
throw { ...(jsonResponse as DeleteVisitorError), status: response.status } as DeleteVisitorError
114+
})
115+
.catch((err) => {
116+
if (isDeleteVisitorError(err)) {
117+
throw err
118+
}
119+
120+
throw {
121+
status: 0,
122+
error: err,
123+
}
124+
})
125+
}
126+
80127
/**
81128
* Gets history for the given visitor
82129
* @param {string} visitorId - Identifier of the visitor

src/types.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,20 @@ export type VisitorsError429 =
5454
retryAfter: number
5555
}
5656

57+
export type DeleteVisitError404 =
58+
paths['/visitors/{visitor_id}']['delete']['responses']['404']['content']['application/json'] & {
59+
status: 404
60+
}
61+
62+
export type DeleteVisitError403 =
63+
paths['/visitors/{visitor_id}']['delete']['responses']['403']['content']['application/json'] & {
64+
status: 403
65+
}
66+
5767
export type VisitorsError = VisitorsError403 | VisitorsError429
5868

69+
export type DeleteVisitorError = DeleteVisitError404 | DeleteVisitError403
70+
5971
export function isVisitorsError(response: any): response is EventError {
6072
return (
6173
(response?.hasOwnProperty('status') &&
@@ -66,6 +78,18 @@ export function isVisitorsError(response: any): response is EventError {
6678
)
6779
}
6880

81+
export function isDeleteVisitorError(response: any): response is DeleteVisitorError {
82+
return (
83+
(response?.hasOwnProperty('status') &&
84+
(response.status === 403 || response.status === 404) &&
85+
response.error?.hasOwnProperty('message') &&
86+
typeof response.error.message === 'string' &&
87+
response.error?.hasOwnProperty('code') &&
88+
typeof response.error.code === 'string') ||
89+
false
90+
)
91+
}
92+
6993
export type EventResponse = paths['/events/{request_id}']['get']['responses']['200']['content']['application/json']
7094
export type EventError403 = paths['/events/{request_id}']['get']['responses']['403']['content']['application/json']
7195
export type EventError404 = paths['/events/{request_id}']['get']['responses']['404']['content']['application/json']

src/urlUtils.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ export function getEventUrl(requestId: string, region: Region, apiKey?: string)
2626
return `${getServerApiUrl(region)}events/${requestId}?${serializeQueryStringParams(params)}`
2727
}
2828

29+
export function getDeleteVisitorDataUrl(region: Region, visitorId: string, apiKey?: string): string {
30+
const queryStringParameters: QueryStringParameters = {
31+
ii: getIntegrationInfo(),
32+
}
33+
34+
if (apiKey) {
35+
queryStringParameters.api_key = apiKey
36+
}
37+
38+
const serverApiPath = getVisitorsPath(region, visitorId)
39+
const queryString = serializeQueryStringParams(queryStringParameters)
40+
41+
return `${serverApiPath}?${queryString}`
42+
}
43+
2944
export function getVisitorsUrl(
3045
region: Region,
3146
visitorId: string,

0 commit comments

Comments
 (0)