diff --git a/readme.md b/readme.md index d0bd47f..12ca0e5 100644 --- a/readme.md +++ b/readme.md @@ -26,109 +26,193 @@

# FingerprintJS Server API Node.js SDK -Node.js wrapper for [FingerprintJS Server API](https://dev.fingerprint.com/docs/server-api) -## Usage +[Fingerprint](https://fingerprint.com) is a device intelligence platform offering 99.5% accurate visitor identification. -Install package using npm -``` sh +The Fingerprint Server Node SDK is an easy way to interact with the Fingerprint [Server API](https://dev.fingerprint.com/reference/pro-server-api) from your Node application. You can retrieve visitor history or individual identification events. + +## Requirements + +TypeScript support: + +- TypeScript 4.5.5 or higher + +Supported runtimes: + +- Node.js 18 LTS or higher (we support all [Node LTS releases before end-of-life](https://nodejs.dev/en/about/releases/)). +- Deno and Bun might work but are not actively tested. +- "Edge" runtimes might work with some modifications but are not actively tested.
+ See "edge" runtimes compatibility + + This SDK can be made compatible with JavaScript "edge" runtimes that do not support all Node APIs, for example, [Vercel Edge Runtime](https://edge-runtime.vercel.app/), or [Cloudflare Workers](https://developers.cloudflare.com/workers/). + + To make it work, replace the SDK's built-in `fetch` function (which relies on Node APIs) with the runtime's native `fetch` function. Pass the function into the constructor with proper binding: + + ```js + const client = new FingerprintJsServerApiClient({ + region: Region.EU, + apiKey: apiKey, + fetch: fetch.bind(globalThis), + }); + ``` + +
+ +## How to install + +Install the package using your favorite package manager: + +```sh npm i @fingerprintjs/fingerprintjs-pro-server-api ``` -Or install package using yarn -``` sh +or + +```sh yarn add @fingerprintjs/fingerprintjs-pro-server-api ``` -### Usage of the Server API +## Getting started + +Initialize the client instance and use it to make API requests. You need to specify your Fingerprint [Secret API key](https://dev.fingerprint.com/docs/quick-start-guide#server-api) and the region of your Fingerprint application. + ```ts import { FingerprintJsServerApiClient, Region } from '@fingerprintjs/fingerprintjs-pro-server-api'; -// Init client with the given region and the secret api_key -const client = new FingerprintJsServerApiClient({region: Region.Global, apiKey: ""}); +const client = new FingerprintJsServerApiClient({ + apiKey: '', + region: Region.Global, +}); -// Get visitor history -client.getVisitorHistory("").then(visitorHistory => { - console.log(visitorHistory); +// Get visit history of a specific visitor +client.getVisitorHistory('').then((visitorHistory) => { + console.log(visitorHistory); }); +// Get a specific identification event +client.getEvent('').then((event) => { + console.log(event); +}); ``` -### Usage of the built-in webhook visit type +## Using with TypeScript + +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; ``` -### Compatibility -This SDK might be also compatible, however not actively tested, with JavaScript "edge" runtimes that do not support all Node APIs, for example, [Vercel Edge Runtime](https://edge-runtime.vercel.app/), or [Cloudflare Workers](https://developers.cloudflare.com/workers/). +The `getEvent` and `getVisitorHistory` methods can throw `EventError` and `VisitorsError`. +You can use the provided `isVisitorsError` and `isEventError` type guards to narrow error types: -To make it work, replace the SDK's built-in fetch function (which relies on Node APIs) with the runtime's native `fetch` function. Pass the function into the constructor with proper binding: -```js -const client = new FingerprintJsServerApiClient({ - region: Region.EU, - apiKey: apiKey, - fetch: fetch.bind(globalThis), -}); +```typescript +import { isVisitorsError, isEventError } from '@fingerprintjs/fingerprintjs-pro-server-api'; + +client + .getVisitorHistory('', 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); + } + }); + +client + .getEvent('') + .then((result) => console.log(result)) + .catch((err) => { + if (isEventError(err)) { + console.log(`error ${err.code}: `, err.error.message); + } else { + console.log('unknown error: ', err); + } + }); ``` -## API +## API Reference + +### `FingerprintJsServerApiClient({region: Region, apiKey: string})` constructor -#### `FingerprintJsServerApiClient({region: Region, apiKey: string})` constructor Creates an instance of the client. -##### Usage + +#### Usage + ```js -const client = new FingerprintJsServerApiClient({region: Region.EU, apiKey: ""}); +const client = new FingerprintJsServerApiClient({ region: Region.EU, apiKey: '' }); ``` -##### Params + +#### 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`) + --- -#### `client.getVisitorHistory(visitorId: string, filter?: VisitorHistoryFilter): Promise` +### `client.getVisitorHistory(visitorId: string, filter?: VisitorHistoryFilter): Promise` + Gets history for the given visitor and given filter, returns a promise with visitor history response. -##### Usage + +#### Usage + ```js -client.getVisitorHistory("", filter) - .then(visitorHistory => { +client + .getVisitorHistory('', filter) + .then((visitorHistory) => { console.log(visitorHistory); }) - .catch(error => { + .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 + retryLater(error.retryAfter); // this function needs to be implemented on your side } }); ``` -##### Params + +#### Params + - `visitorId: string` - identifier of the visitor - `filter?: VisitorHistoryFilter` - visitor history filter, more info in [the API documentation](https://dev.fingerprint.com/docs/server-api#query-parameters) -##### Returns -- `Promise` - promise with visitor history response ---- -#### `VisitorHistoryFilter` + +##### `VisitorHistoryFilter` + Filter for querying API - see [query parameters](https://dev.fingerprint.com/docs/server-api#query-parameters). -##### Usage + +Usage: + ```js const filter = { - request_id: "", - linked_id: "", - limit: 5, - paginationKey: "" + request_id: '', + linked_id: '', + limit: 5, + paginationKey: '', }; ``` -##### Properties + +Properties: + - `request_id: string` - filter visits by `requestId`. 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. + - `linked_id: string` - filter visits by your custom identifier. 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. + +- `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: @@ -136,9 +220,15 @@ const filter = { 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. ---- -#### Server `VisitorsResponse` response -Find more info in [the API documentation](https://dev.fingerprint.com/docs/server-api#response) + +#### Returns + +- `Promise` - promise with visitor history response + +##### Server `VisitorsResponse` response + +Find more info in the [Server API documentation](https://dev.fingerprint.com/reference/getvisits) + ```json { "visitorId": "Ibk1527CUFmcnjLwIs4A9", @@ -183,7 +273,7 @@ Find more info in [the API documentation](https://dev.fingerprint.com/docs/serve "os": "Windows", "osVersion": "7", "device": "Other", - "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....", + "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ...." }, "confidence": { "score": 0.97 @@ -204,27 +294,39 @@ Find more info in [the API documentation](https://dev.fingerprint.com/docs/serve } ``` -#### `client.getEvent(requestId: string): Promise` +### `client.getEvent(requestId: string): Promise` + Get events with all the information from each activated product - Bot Detection and Identification. -##### Usage + +#### Usage + ```typescript -client.getEvent("") - .then(eventInfo => { +client + .getEvent('') + .then((eventInfo) => { console.log(eventInfo); }) - .catch(error => { + .catch((error) => { if (error.status === 403 || error.status === 404) { console.log(error.code, error.message); } }); ``` -##### Params + +#### Params + - `requestId: string` - identifier of the event -##### Returns + +#### Returns + - `Promise` - promise with event response + --- -#### Server `EventResponse` response + +##### Server `EventResponse` response + Find more info in the [API documentation](https://dev.fingerprint.com/docs/server-api#response-1). + ```json { "products": { @@ -260,7 +362,7 @@ Find more info in the [API documentation](https://dev.fingerprint.com/docs/serve "isoCode": "63", "name": "North Rhine-Westphalia" } - ], + ] }, "browserDetails": { "browserName": "Chrome", @@ -269,15 +371,15 @@ Find more info in the [API documentation](https://dev.fingerprint.com/docs/serve "os": "Windows", "osVersion": "7", "device": "Other", - "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....", + "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ...." }, "confidence": { - "score": 0.97 + "score": 0.97 }, "visitorFound": true, "firstSeenAt": { - "global": "2022-03-16T11:26:45.362Z", - "subscription": "2022-03-16T11:31:01.101Z" + "global": "2022-03-16T11:26:45.362Z", + "subscription": "2022-03-16T11:31:01.101Z" }, "lastSeenAt": { "global": "2022-03-16T11:28:34.023Z", @@ -298,39 +400,11 @@ Find more info in the [API documentation](https://dev.fingerprint.com/docs/serve } } ``` -### Using with TypeScript -`getEvent` and `getVisitorHistory` methods return generic types `Promise` and `Promise` and throw `EventError` and `VisitorsError`. +## Support and feedback -You can use typeguards to narrow error types as in example below. +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). -```typescript -import { isVisitorsError, isEventError } from '@fingerprintjs/fingerprintjs-pro-server-api'; +## License -client - .getVisitorHistory("", 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) - } - }); - -client - .getEvent("") - .then(result => console.log(result)) - .catch(err => { - if (isEventError(err)) { - console.log(`error ${err.code}: `, err.error.message) - } else { - console.log('unknown error: ', err) - } - }); -``` +This project is licensed under the [MIT license](./LICENSE).