Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fingerprintjs/fingerprintjs-pro-server-api

Package Overview
Dependencies
Maintainers
3
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fingerprintjs/fingerprintjs-pro-server-api - npm Package Compare versions

Comparing version 4.0.1 to 4.1.0-test.1

src/webhook.ts

8

package.json
{
"name": "@fingerprintjs/fingerprintjs-pro-server-api",
"version": "4.0.1",
"version": "4.1.0-test.1",
"description": "Node.js wrapper for FingerprintJS Sever API",

@@ -31,3 +31,4 @@ "main": "dist/index.cjs",

"test:dts": "tsc --noEmit --isolatedModules dist/index.d.ts",
"generateTypes": "pnpm openapi-typescript resources/fingerprint-server-api.yaml --output ./src/generatedApiTypes.ts -c .prettierrc"
"generateTypes": "pnpm openapi-typescript resources/fingerprint-server-api.yaml --output ./src/generatedApiTypes.ts -c .prettierrc",
"docs": "typedoc src/index.ts --out docs"
},

@@ -50,3 +51,3 @@ "keywords": [],

"@fingerprintjs/eslint-config-dx-team": "^0.1.0",
"@fingerprintjs/prettier-config-dx-team": "^0.1.0",
"@fingerprintjs/prettier-config-dx-team": "^0.2.0",
"@fingerprintjs/tsconfig-dx-team": "^0.0.2",

@@ -71,4 +72,5 @@ "@rollup/plugin-json": "^6.1.0",

"tslib": "^2.6.2",
"typedoc": "^0.25.13",
"typescript": "^5.4.0"
}
}

@@ -46,3 +46,3 @@ <p align="center">

fetch: fetch.bind(globalThis),
});
})
```

@@ -56,3 +56,3 @@

* NPM:
- NPM:

@@ -62,7 +62,8 @@ ```sh

```
* Yarn:
- Yarn:
```sh
yarn add @fingerprintjs/fingerprintjs-pro-server-api
```
* pnpm:
- pnpm:
```sh

@@ -77,3 +78,6 @@ pnpm i @fingerprintjs/fingerprintjs-pro-server-api

```ts
import { FingerprintJsServerApiClient, Region } from '@fingerprintjs/fingerprintjs-pro-server-api';
import {
FingerprintJsServerApiClient,
Region,
} from '@fingerprintjs/fingerprintjs-pro-server-api'

@@ -83,187 +87,61 @@ const client = new FingerprintJsServerApiClient({

region: Region.Global,
});
})
// Get visit history of a specific visitor
client.getVisitorHistory('<visitorId>').then((visitorHistory) => {
console.log(visitorHistory);
});
console.log(visitorHistory)
})
// Get a specific identification event
client.getEvent('<requestId>').then((event) => {
console.log(event);
});
console.log(event)
})
```
### Using with TypeScript
See the [Examples](./example) folder for more detailed examples.
#### Webhook types
### Error handling
When handling [Webhooks](https://dev.fingerprint.com/docs/webhooks) coming from Fingerprint, you can cast the payload as the built-in `VisitWebhook` type:
```ts
const visit = visitWebhookBody as unknown as VisitWebhook;
```
#### Narrowing error types
The `getEvent` and `getVisitorHistory` methods can throw `EventError` and `VisitorsError`.
The Server API methods like `getEvent` and `getVisitorHistory` can throw `EventError` and `VisitorsError`.
You can use the provided `isVisitorsError` and `isEventError` type guards to narrow down error types:
```typescript
import { isVisitorsError, isEventError } from '@fingerprintjs/fingerprintjs-pro-server-api';
import {
isVisitorsError,
isEventError,
FingerprintJsServerApiClient,
} from '@fingerprintjs/fingerprintjs-pro-server-api'
client
.getVisitorHistory('<visitorId>', filter)
.then((result) => console.log(result))
.catch((err) => {
if (isVisitorsError(err)) {
if (err.code === 429) {
// VisitorsError429 type
retryLater(err.retryAfter); // this function needs to be implemented on your side
} else {
console.log('error: ', err.error);
}
} else {
console.log('unknown error: ', err);
}
});
const client = new FingerprintJsServerApiClient({
apiKey: '<SECRET_API_KEY>',
region: Region.Global,
})
client
.getEvent('<requestId>')
.then((result) => console.log(result))
.catch((err) => {
if (isEventError(err)) {
console.log(`error ${err.code}: `, err.error.message);
} else {
console.log('unknown error: ', err);
}
});
```
// Handling getEvent errors
try {
const event = await client.getEvent(requestId)
console.log(JSON.stringify(event, null, 2))
} catch (error) {
if (isEventError(error)) {
console.log(error.response) // You can also access the raw response
console.log(`error ${error.status}: `, error.error?.message)
} else {
console.log('unknown error: ', error)
}
}
## Sealed results
This SDK provides utility methods for decoding sealed results.
To learn more, refer to example located in [example/sealedResults.js](./example/sealedResults.js).
## API Reference
### `constructor({region: Region, apiKey: string})`
Creates an instance of the client.
#### Usage
```js
const client = new FingerprintJsServerApiClient({ region: Region.EU, apiKey: '<api_key>' });
```
#### Params
- `region: Region` - a region of the server, possible values: `Region.EU`, `Region.AP`, or `Region.Global`
- `apiKey: string` - secret API key from the [FingerprintJS dashboard](https://dashboard.fingerprint.com/)
- `fetch?: typeof fetch` - optional implementation of `fetch` function (defaults to `node-fetch`)
---
### `getEvent(requestId: string): Promise<EventResponse>`
Retrieves a specific identification event with the information from each activated product — Identification and all active [Smart signals](https://dev.fingerprint.com/docs/smart-signals-overview).
#### Usage
```typescript
client
.getEvent('<requestId>')
.then((eventInfo) => {
console.log(eventInfo);
// Handling getVisitorHistory errors
try {
const visitorHistory = await client.getVisitorHistory(visitorId, {
limit: 10,
})
.catch((error) => {
if (error.status === 403 || error.status === 404) {
console.log(error.code, error.message);
console.log(JSON.stringify(visitorHistory, null, 2))
} catch (error) {
if (isVisitorsError(error)) {
console.log(error.status, error.error)
if (error.status === 429) {
retryLater(error.retryAfter) // Needs to be implemented on your side
}
});
```
#### Params
- `requestId: string` - identifier of the event
#### Returns
- `Promise<EventResponse>` - promise with event response
##### `EventResponse`
For more information, see the [Server API documentation](https://dev.fingerprint.com/reference/getevent).
```json
{
"products": {
"identification": {
"data": {
"visitorId": "Ibk1527CUFmcnjLwIs4A9",
"requestId": "0KSh65EnVoB85JBmloQK",
"incognito": true,
"linkedId": "somelinkedId",
"time": "2019-05-21T16:40:13Z",
"timestamp": 1582299576512,
"url": "https://www.example.com/login",
"ip": "61.127.217.15",
"ipLocation": {
"accuracyRadius": 10,
"latitude": 49.982,
"longitude": 36.2566,
"postalCode": "61202",
"timezone": "Europe/Dusseldorf",
"city": {
"name": "Dusseldorf"
},
"continent": {
"code": "EU",
"name": "Europe"
},
"country": {
"code": "DE",
"name": "Germany"
},
"subdivisions": [
{
"isoCode": "63",
"name": "North Rhine-Westphalia"
}
]
},
"browserDetails": {
"browserName": "Chrome",
"browserMajorVersion": "74",
"browserFullVersion": "74.0.3729",
"os": "Windows",
"osVersion": "7",
"device": "Other",
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ...."
},
"confidence": {
"score": 0.97
},
"visitorFound": true,
"firstSeenAt": {
"global": "2022-03-16T11:26:45.362Z",
"subscription": "2022-03-16T11:31:01.101Z"
},
"lastSeenAt": {
"global": "2022-03-16T11:28:34.023Z",
"subscription": null
}
}
},
"botd": {
"data": {
"bot": {
"result": "notDetected"
},
"url": "https://example.com/login",
"ip": "61.127.217.15",
"time": "2019-05-21T16:40:13Z"
}
}
} else {
console.error('unknown error: ', error)
}

@@ -273,187 +151,38 @@ }

---
### Webhooks
### `getVisitorHistory(visitorId: string, filter?: VisitorHistoryFilter): Promise<VisitorsResponse>`
#### Webhook types
Retrieves event history for the specific visitor using the given filter, returns a promise with visitor history response.
When handling [Webhooks](https://dev.fingerprint.com/docs/webhooks) coming from Fingerprint, you can cast the payload as the built-in `VisitWebhook` type:
#### Usage
```ts
import { VisitWebhook } from '@fingerprintjs/fingerprintjs-pro-server-api'
```js
client
.getVisitorHistory('<visitorId>', filter)
.then((visitorHistory) => {
console.log(visitorHistory);
})
.catch((error) => {
if (error.status === 403) {
console.log(error.error);
} else if (error.status === 429) {
retryLater(error.retryAfter); // this function needs to be implemented on your side
}
});
const visit = visitWebhookBody as unknown as VisitWebhook
```
#### Params
#### Webhook signature validation
- `visitorId: string` - identifier of the visitor
- `filter?: VisitorHistoryFilter` - visitor history filter (details below)
Customers on the Enterprise plan can enable [Webhook signatures](https://dev.fingerprint.com/docs/webhooks-security) to cryptographically verify the authenticity of incoming webhooks.
This SDK provides a utility method for verifying the HMAC signature of the incoming webhook request.
##### `VisitorHistoryFilter`
To learn more, see [example/validateWebhookSignature.mjs](example/validateWebhookSignature.mjs) or read the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/functions/isValidWebhookSignature.html).
Filter for querying the [visitors Server API endpoint](https://dev.fingerprint.com/reference/getvisits).
### Sealed results
Usage:
Customers on the Enterprise plan can enable [Sealed results](https://dev.fingerprint.com/docs/sealed-results) to receive the full device intelligence result on the client and unseal it on the server. This SDK provides utility methods for decoding sealed results.
```js
const filter = {
request_id: '<request_id>',
linked_id: '<linked_id>',
limit: 5,
paginationKey: '<paginationKey>',
};
```
To learn more, see [example/unsealResult.mjs](./example/unsealResult.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/functions/unsealEventsResponse.html).
Properties:
### Deleting visitor data
- `request_id: string` - filter visits by `requestId`.
Customers on the Enterprise plan can [Delete all data associated with a specific visitor](https://dev.fingerprint.com/reference/deletevisitordata) to comply with privacy regulations. See [example/deleteVisitorData.mjs](./example/deleteVisitorData.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/docs/classes/FingerprintJsServerApiClient.html#deleteVisitorData).
Every identification request has a unique identifier associated with it called `requestId`. This identifier is returned to the client in the identification [result](https://dev.fingerprint.com/docs/js-agent#requestid). When you filter visits by `requestId`, only one visit will be returned.
## API Reference
- `linked_id: string` - filter visits by your custom identifier.
See the full [API reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/).
You can use [`linkedId`](https://dev.fingerprint.com/docs/js-agent#linkedid) to associate identification requests with your own identifier, for example: session ID, purchase ID, or transaction ID. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier.
- `limit: number` - limit scanned results.
For performance reasons, the API first scans some number of events before filtering them. Use `limit` to specify how many events are scanned before they are filtered by `requestId` or `linkedId`. Results are always returned sorted by the timestamp (most recent first). By default, the most recent 100 visits are scanned, the maximum is 500.
- `paginationKey: string` - use `paginationKey` to get the next page of results.
When more results are available (e.g., you requested 200 results using `limit` parameter, but a total of 600 results are available), the `paginationKey` top-level attribute is added to the response. The key corresponds to the `requestId` of the last returned event. In the following request, use that value in the `paginationKey` parameter to get the next page of results:
1. First request, returning most recent 200 events: `GET api-base-url/visitors/:visitorId?limit=200`
2. Use `response.paginationKey` to get the next page of results: `GET api-base-url/visitors/:visitorId?limit=200&paginationKey=1683900801733.Ogvu1j`
Pagination happens during scanning and before filtering, so you can get less visits than the `limit` you specified with more available on the next page. When there are no more results available for scanning, the `paginationKey` attribute is not returned.
#### Returns
- `Promise<VisitorsResponse>` - promise with the visitor history response
##### `VisitorsResponse`
For more information, see the [Server API documentation](https://dev.fingerprint.com/reference/getvisits).
```json
{
"visitorId": "Ibk1527CUFmcnjLwIs4A9",
"visits": [
{
"requestId": "0KSh65EnVoB85JBmloQK",
"incognito": true,
"linkedId": "somelinkedId",
"time": "2019-05-21T16:40:13Z",
// timestamp of the event with millisecond precision
"timestamp": 1582299576512,
"url": "https://www.example.com/login",
"ip": "61.127.217.15",
"ipLocation": {
"accuracyRadius": 10,
"latitude": 49.982,
"longitude": 36.2566,
"postalCode": "61202",
"timezone": "Europe/Dusseldorf",
"city": {
"name": "Dusseldorf"
},
"continent": {
"code": "EU",
"name": "Europe"
},
"country": {
"code": "DE",
"name": "Germany"
},
"subdivisions": [
{
"isoCode": "63",
"name": "North Rhine-Westphalia"
}
]
},
"browserDetails": {
"browserName": "Chrome",
"browserMajorVersion": "74",
"browserFullVersion": "74.0.3729",
"os": "Windows",
"osVersion": "7",
"device": "Other",
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ...."
},
"confidence": {
"score": 0.97
},
"visitorFound": true,
"firstSeenAt": {
"global": "2022-03-16T11:26:45.362Z",
"subscription": "2022-03-16T11:31:01.101Z"
},
"lastSeenAt": {
"global": "2022-03-16T11:28:34.023Z",
"subscription": null
}
}
],
// optional, if more results are available for pagination.
"lastTimestamp": 1582299576512
}
```
## Sealed results API Reference
### `unsealEventsResponse(sealedData: Buffer, decryptionKeys: DecryptionKey[]): Promise<EventResponse>`
Decrypts the sealed events response with provided keys.
#### Usage
```js
import { unsealEventsResponse, DecryptionAlgorithm } from '@fingerprintjs/fingerprintjs-pro-server-api';
unsealEventsResponse(sealedData, [
{
key: Buffer.from('p2PA7MGy5tx56cnyJaFZMr96BCFwZeHjZV2EqMvTq53=', 'base64'),
algorithm: DecryptionAlgorithm.Aes256Gcm,
},
]).then(result => {
console.log(result);
});
```
#### Params
- `sealedData: Buffer` - sealed data to decrypt
- `decryptionKeys: DecryptionKey[]` - array of decryption keys. The SDK will try to decrypt the result with each key until it succeeds.
##### `DecryptionKey`
```js
const decryptionKey = {
key: Buffer.from('aW52YWxpZA==', 'base64'),
algorithm: DecryptionAlgorithm.Aes256Gcm,
}
```
Properties:
- `key: Buffer` - key generated in dashboard that will be used to decrypt sealed result
- `algorithm: DecryptionAlgorithm` - algorithm to use for decryption. Currently only `Aes256Gcm` value is supported.
#### Returns
- `Promise<EventResponse>` - promise with the decrypted event response
## Support and feedback
To report problems, ask questions or provide feedback, please use [Issues](https://github.com/fingerprintjs/fingerprintjs-pro-server-api-node-sdk/issues). If you need private support, you can email us at [oss-support@fingerprint.com](mailto:oss-support@fingerprint.com).
To report problems, ask questions, or provide feedback, please use [Issues](https://github.com/fingerprintjs/fingerprintjs-pro-server-api-node-sdk/issues). If you need private support, you can email us at [oss-support@fingerprint.com](mailto:oss-support@fingerprint.com).

@@ -460,0 +189,0 @@ ## License

@@ -9,4 +9,4 @@ /**

/**
* Get event by requestId
* @description This endpoint allows you to get a detailed analysis of an individual request.
* Get event by request ID
* @description Get a detailed analysis of an individual identification event, including Smart Signals.
* **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.

@@ -21,4 +21,4 @@ * It is highly recommended that you **ignore** the mobile signals for such requests.

/**
* Get visits by visitorId
* @description This endpoint allows you to get a history of visits for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
* Get visits by visitor ID
* @description Get a history of visits (identification events) for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
* Only information from the _Identification_ product is returned.

@@ -31,2 +31,13 @@ *

get: operations['getVisits']
/**
* Delete data by visitor ID
* @description Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations.
* All delete requests are queued:
*
* * 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.
*
* 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.
*/
delete: operations['deleteVisitorData']
}

@@ -139,4 +150,4 @@ '/webhook': {

}
ErrorEvent403Response: {
/** ErrorEvent403ResponseError */
ErrorCommon403Response: {
/** Common403ErrorResponse */
error?: {

@@ -146,5 +157,6 @@ /**

* * `TokenRequired` - `Auth-API-Key` header is missing or empty
* * `TokenNotFound` - subscription not found for specified secret key
* * `SubscriptionNotActive` - subscription is not active
* * `WrongRegion` - server and subscription region differ
* * `TokenNotFound` - No Fingerprint application found for specified secret key
* * `SubscriptionNotActive` - Fingerprint application is not active
* * `WrongRegion` - server and application region differ
* * `FeatureNotEnabled` - this feature (for example, Delete API) is not enabled for your application
*

@@ -154,3 +166,3 @@ * @example TokenRequired

*/
code: 'TokenRequired' | 'TokenNotFound' | 'SubscriptionNotActive' | 'WrongRegion'
code: 'TokenRequired' | 'TokenNotFound' | 'SubscriptionNotActive' | 'WrongRegion' | 'FeatureNotEnabled'
/** @example secret key is required */

@@ -165,3 +177,3 @@ message: string

* @description Error code:
* * `RequestNotFound` - request not found for specified id
* * `RequestNotFound` - The specified request ID was not found. It never existed, expired, or it has been deleted.
*

@@ -190,2 +202,16 @@ * @example RequestNotFound

}
ErrorVisitsDelete404Response: {
/** ErrorVisitsDelete404ResponseError */
error?: {
/**
* @description Error code: * `VisitorNotFound` - The specified visitor ID was not found. It never existed or it may have already been deleted.
*
* @example VisitorNotFound
* @enum {string}
*/
code: 'VisitorNotFound'
/** @example visitor not found */
message: string
}
}
WebhookVisit: {

@@ -382,2 +408,4 @@ /** @example 3HNey93AkBW6CRbxV6xP */

score: number
/** @description The revision name of the method used to calculate the Confidence score. This field is only present for customers who opted in to an alternative calculation method. */
revision?: string
}

@@ -772,3 +800,3 @@ /**

/**
* @description User's browser timezone doesn't match the timezone from which the request was originally made.
* @description The browser timezone doesn't match the timezone inferred from the request IP address.
* @example false

@@ -787,2 +815,7 @@ */

auxiliaryMobile: boolean
/**
* @description The browser runs on a different operating system than the operating system inferred from the request network signature.
* @example false
*/
osMismatch: boolean
}

@@ -969,4 +1002,4 @@ }

/**
* Get event by requestId
* @description This endpoint allows you to get a detailed analysis of an individual request.
* Get event by request ID
* @description Get a detailed analysis of an individual identification event, including Smart Signals.
* **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.

@@ -980,3 +1013,3 @@ * It is highly recommended that you **ignore** the mobile signals for such requests.

path: {
/** @description The unique [identifier](https://dev.fingerprint.com/docs/js-agent#requestid) of each analysis request. */
/** @description The unique [identifier](https://dev.fingerprint.com/docs/js-agent#requestid) of each identification request. */
request_id: string

@@ -995,3 +1028,3 @@ }

content: {
'application/json': components['schemas']['ErrorEvent403Response']
'application/json': components['schemas']['ErrorCommon403Response']
}

@@ -1008,4 +1041,4 @@ }

/**
* Get visits by visitorId
* @description This endpoint allows you to get a history of visits for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
* Get visits by visitor ID
* @description Get a history of visits (identification events) for a specific `visitorId`. Use the `visitorId` as a URL path parameter.
* Only information from the _Identification_ product is returned.

@@ -1055,3 +1088,3 @@ *

/**
* @description Unique identifier of the visitor issued by Fingerprint Pro.
* @description Unique [visitor identifier](https://dev.fingerprint.com/docs/js-agent#visitorid) issued by Fingerprint Pro.
* @example uYIm7Ksp5rf00SllPhFp

@@ -1087,2 +1120,38 @@ */

}
/**
* Delete data by visitor ID
* @description Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations.
* All delete requests are queued:
*
* * 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.
*
* 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.
*/
deleteVisitorData: {
parameters: {
path: {
/** @description The [visitor ID](https://dev.fingerprint.com/docs/js-agent#visitorid) you want to delete. */
visitor_id: string
}
}
responses: {
/** @description OK. The visitor ID is scheduled for deletion. */
200: {
content: never
}
/** @description Forbidden. Access to this API is denied. */
403: {
content: {
'application/json': components['schemas']['ErrorCommon403Response']
}
}
/** @description Not found. The visitor ID cannot be found in this application's data. */
404: {
content: {
'application/json': components['schemas']['ErrorVisitsDelete404Response']
}
}
}
}
}

@@ -6,1 +6,2 @@ export * from './urlUtils'

export * from './errors/unsealError'
export * from './webhook'

@@ -25,2 +25,5 @@ import { createDecipheriv } from 'crypto'

/**
* @private
* */
export function parseEventsResponse(unsealed: string) {

@@ -47,2 +50,5 @@ const json = JSON.parse(unsealed)

/**
* @private
* */
export async function unseal(sealedData: Buffer, decryptionKeys: DecryptionKey[]) {

@@ -49,0 +55,0 @@ if (sealedData.subarray(0, SEALED_HEADER.length).toString('hex') !== SEALED_HEADER.toString('hex')) {

@@ -1,14 +0,16 @@

import { getEventUrl, getVisitorsUrl } from './urlUtils'
import { getDeleteVisitorDataUrl, getEventUrl, getVisitorsUrl } from './urlUtils'
import {
VisitorHistoryFilter,
VisitorsResponse,
Region,
Options,
AuthenticationMode,
DeleteVisitorError,
EventError,
EventResponse,
EventError,
isDeleteVisitorError,
isEventError,
isVisitorsError,
Options,
Region,
VisitorHistoryFilter,
VisitorsError,
isVisitorsError,
VisitorsError429,
VisitorsResponse,
} from './types'

@@ -31,6 +33,2 @@

constructor(options: Readonly<Options>) {
if (!options.region) {
throw Error('Region is not set')
}
if (!options.apiKey) {

@@ -40,3 +38,3 @@ throw Error('Api key is not set')

this.region = options.region
this.region = options.region ?? Region.Global
this.apiKey = options.apiKey

@@ -47,3 +45,26 @@ this.authenticationMode = options.authenticationMode ?? AuthenticationMode.AuthHeader // Default auth mode is AuthHeader

public async getEvent(requestId: string) {
/**
* Retrieves a specific identification event with the information from each activated product — Identification and all active [Smart signals](https://dev.fingerprint.com/docs/smart-signals-overview).
*
* @param requestId - identifier of the event
*
* @returns {Promise<EventResponse>} - promise with event response. For more information, see the [Server API documentation](https://dev.fingerprint.com/reference/getevent).
*
* @example
* ```javascript
* client
* .getEvent('<requestId>')
* .then((result) => console.log(result))
* .catch((err) => {
* if (isEventError(err)) {
* // You can also access the raw response
* console.log(err.response)
* console.log(`error ${err.status}: `, err.error?.message)
* } else {
* console.log('unknown error: ', err)
* }
* })
* ```
* */
public async getEvent(requestId: string): Promise<EventResponse> {
if (!requestId) {

@@ -67,3 +88,3 @@ throw new TypeError('requestId is not set')

if (response.status !== 200) {
throw { ...(jsonResponse as EventError), status: response.status } as EventError
throw { ...jsonResponse, response, status: response.status } as EventError
}

@@ -76,6 +97,6 @@ return jsonResponse as EventResponse

}
const error = (err as unknown) instanceof Error ? (err as Error).toString() : JSON.stringify(err)
throw {
status: 0,
error: error,
error: err,
}

@@ -86,5 +107,92 @@ })

/**
* Gets history for the given visitor
* Delete data by visitor ID
* Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. All delete requests are queued:
* 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.
* 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.
*
* @param visitorId The [visitor ID](https://dev.fingerprint.com/docs/js-agent#visitorid) you want to delete.*
*
* @return {Promise<void>} Promise that resolves when the deletion request is successfully queued
*
* @example
* ```javascript
* client
* .deleteVisitorData('<visitorId>')
* .then(() => {
* // Data deletion request was successfully queued
* })
* .catch((error) => {
* if (isDeleteVisitorError(error)) {
* console.log(error.status, error.error)
* }
* })
* ```
*/
public async deleteVisitorData(visitorId: string): Promise<void> {
if (!visitorId) {
throw TypeError('VisitorId is not set')
}
const url =
this.authenticationMode === AuthenticationMode.QueryParameter
? getDeleteVisitorDataUrl(this.region, visitorId, this.apiKey)
: getDeleteVisitorDataUrl(this.region, visitorId)
const headers = this.getHeaders()
await this.fetch(url, {
method: 'DELETE',
headers,
})
.then(async (response) => {
if (response.status === 200) {
return
}
const jsonResponse = await response.json()
throw { ...(jsonResponse as DeleteVisitorError), response, status: response.status } as DeleteVisitorError
})
.catch((err) => {
if (isDeleteVisitorError(err)) {
throw err
}
throw {
status: 0,
error: err,
}
})
}
/**
* Retrieves event history for the specific visitor using the given filter, returns a promise with visitor history response.
*
* @param {string} visitorId - Identifier of the visitor
* @param {VisitorHistoryFilter} filter - Visitor history filter
* @param {string} filter.limit - limit scanned results
* @param {string} filter.request_id - filter visits by `requestId`.
* @param {string} filter.linked_id - filter visits by your custom identifier.
* @param {string} filter.paginationKey - use `paginationKey` to get the next page of results. When more results are available (e.g., you requested 200 results using `limit` parameter, but a total of 600 results are available), the `paginationKey` top-level attribute is added to the response. The key corresponds to the `requestId` of the last returned event. In the following request, use that value in the `paginationKey` parameter to get the next page of results:
*
* 1. First request, returning most recent 200 events: `GET api-base-url/visitors/:visitorId?limit=200`
* 2. Use `response.paginationKey` to get the next page of results: `GET api-base-url/visitors/:visitorId?limit=200&paginationKey=1683900801733.Ogvu1j`
*
* Pagination happens during scanning and before filtering, so you can get less visits than the `limit` you specified with more available on the next page. When there are no more results available for scanning, the `paginationKey` attribute is not returned.
* @example
* ```javascript
* client
* .getVisitorHistory('<visitorId>', { limit: 1 })
* .then((visitorHistory) => {
* console.log(visitorHistory)
* })
* .catch((error) => {
* if (isVisitorsError(error)) {
* console.log(error.status, error.error)
* if (error.status === 429) {
* retryLater(error.retryAfter) // Needs to be implemented on your side
* }
* }
* })
* ```
*/

@@ -115,5 +223,5 @@ public async getVisitorHistory(visitorId: string, filter?: VisitorHistoryFilter): Promise<VisitorsResponse> {

}
throw { ...(jsonResponse as VisitorsError), status: response.status } as VisitorsError
throw { ...(jsonResponse as VisitorsError), response, status: response.status } as VisitorsError
})
.catch((err: Error) => {
.catch((err) => {
if (isVisitorsError(err)) {

@@ -124,3 +232,3 @@ throw err

status: 0,
error: new Error((err as any).toString()),
error: err,
}

@@ -127,0 +235,0 @@ })

@@ -25,3 +25,3 @@ import { components, paths } from './generatedApiTypes'

*/
region: Region
region?: Region
/**

@@ -55,8 +55,23 @@ * Authentication mode

status: 429
/**
* How many seconds to wait before retrying
*/
retryAfter: number
}
export type VisitorsError = VisitorsError403 | VisitorsError429
export type DeleteVisitError404 =
paths['/visitors/{visitor_id}']['delete']['responses']['404']['content']['application/json'] & {
status: 404
}
export function isVisitorsError(response: any): response is EventError {
export type DeleteVisitError403 =
paths['/visitors/{visitor_id}']['delete']['responses']['403']['content']['application/json'] & {
status: 403
}
export type VisitorsError = WithResponse<VisitorsError403 | VisitorsError429>
export type DeleteVisitorError = WithResponse<DeleteVisitError404 | DeleteVisitError403>
export function isVisitorsError(response: any): response is VisitorsError {
return (

@@ -71,2 +86,14 @@ (response?.hasOwnProperty('status') &&

export function isDeleteVisitorError(response: any): response is DeleteVisitorError {
return (
(response?.hasOwnProperty('status') &&
(response.status === 403 || response.status === 404) &&
response.error?.hasOwnProperty('message') &&
typeof response.error.message === 'string' &&
response.error?.hasOwnProperty('code') &&
typeof response.error.code === 'string') ||
false
)
}
export type EventResponse = paths['/events/{request_id}']['get']['responses']['200']['content']['application/json']

@@ -76,10 +103,15 @@ export type EventError403 = paths['/events/{request_id}']['get']['responses']['403']['content']['application/json']

type GenericEventError = EventError403 | EventError404
type WithResponse<T> = T & {
response: Response
}
type GenericEventError = WithResponse<EventError403 | EventError404>
type EventErrorCode<T extends GenericEventError> = T extends EventError403 ? 403 : 404
export type EventError<T extends GenericEventError = GenericEventError> = T & {
status: EventErrorCode<T>
}
export type EventError<T extends GenericEventError = GenericEventError> = WithResponse<
T & {
status: EventErrorCode<T>
}
>
export function isEventError(response: any): response is EventError {

@@ -86,0 +118,0 @@ return (

@@ -17,2 +17,5 @@ import { Region, VisitorHistoryFilter } from './types'

/**
* @private
* */
export function getEventUrl(requestId: string, region: Region, apiKey?: string) {

@@ -30,2 +33,23 @@ const params: QueryStringParameters = {

/**
* @private
* */
export function getDeleteVisitorDataUrl(region: Region, visitorId: string, apiKey?: string): string {
const queryStringParameters: QueryStringParameters = {
ii: getIntegrationInfo(),
}
if (apiKey) {
queryStringParameters.api_key = apiKey
}
const serverApiPath = getVisitorsPath(region, visitorId)
const queryString = serializeQueryStringParams(queryStringParameters)
return `${serverApiPath}?${queryString}`
}
/**
* @private
* */
export function getVisitorsUrl(

@@ -32,0 +56,0 @@ region: Region,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc