FinScan
Functional documentation​
This provider screens an individual or a company against the FinScan ISI service and maps the outcome to CDD parameters. The request is built from basic party data (name, address, gender) and a configurable set of FinScan lists. Each investigable match FinScan returns — a "pair" — flags the CDD parameters the customer has mapped to that pair's category, SCREENING_HIT records whether anything matched at all, and every unmatched parameter stays NO.
:::info Synchronous, in-flow resolution The whole exchange is resolved synchronously, within the check, even though FinScan persists a screening case asynchronously. On a hit the provider polls FinScan in-flow (first after ~20s, then every 10s, for up to ~3 minutes) until the case's pairs are available, then returns a complete result through the normal due-diligence write path — so this provider can take up to ~3 minutes and relies on the websocket-backed check path that allows it. Webhook notifications are not consumed. :::
Screening flow​
POST /api/v1/ISI/ISIGetApiToken— fetches a bearer token using the configured ISI credentials. A FinScan token is valid for one hour, so a single token is fetched per screening and reused for every subsequent call, poll included.POST /api/v1/ISI/ISIFocusSearchAddUpdateCase— screens the party against the configuredsearchListsand returns the preliminary list records. Screening runs withlogSearchesWithoutMatches: "No", so a clean screening creates no client in FinScan.SCREENING_HITis answered first: on a clean screening every configured parameter is a realNOand the provider returns immediately, with no client to poll for or clean up.- On a hit,
POST /api/v2/ISI/ISIFocusClientSyncis polled until the client lands, its pairs are read viaPOST /api/v1/ISI/ISIClientGet, and each pair is resolved into CDD parameters from the pair detail — itsfnsCategories(viacategoryMatches) andlistPEPCategory(viapepCategoryMatches) — never guessed from the requestedlistId. - If the client never lands within the poll budget,
SCREENING_HITis set toYES, the remaining parameters stayUNDEFINED, and the result is marked failed. - The FinScan client is then handled per the
clientLifecyclesetting — by default deactivated once the pairs are read, keeping it out of FinScan's recurring batch screening.
A fresh FinScan client id is used per screening: FinScan accumulates pairs on a client id and never clears them, so reusing one would leak matches between screenings.
Input data points​
- Individual
- First name (required)
- Last name (required)
- Gender
- Address (street, postal code, city, country code)
- Company
- Name (required)
Applicable CDD parameters​
This provider supports the parameters defined by the settings — the union of all values across each mapping's categoryMatches and pepCategoryMatches, plus the always-present SCREENING_HIT. The same provider can support disjoint parameter sets for individuals vs companies. A pair only flags its parameters when its FinScan rankScore meets the configured minimumRankScore.
Configuration​
- Implementation class:
FinScanDueDiligenceProvider - Sandbox resource URI:
https://hosted3.finscan.com/ISI_TEST
Authentication​
FinScan ISI credentials are sourced from the standard authentication block:
| Harmoney setting | FinScan ISI field |
|---|---|
authentication.clientId | organizationName |
authentication.userId | userName |
authentication.clientSecret | password |
As for every provider, reference these credentials from the vault rather than inlining them.
:::warning Credentials are stored in the provider audit trail
FinScan expects its credentials in the body of every ISI request rather than in a header, and provider request bodies are persisted as the audit record of the exchange. The FinScan password therefore appears in ProviderResponse for each call, and the API token it returns does too when response saving is enabled for the provider.
Treat read access to ProviderResponse — including database exports and restored dumps — as access to the FinScan credentials, and rotate them if that access is ever broader than intended. Masking these fields at the platform level is being handled separately.
:::