# Introduction to OneSDK Source: https://docs.frankieone.com/docs/about-onesdk OneSDK is a powerful client-side JavaScript library that simplifies customer onboarding by integrating FrankieOne’s KYC (Know Your Customer) and IDV (Identity Verification) services directly into your application. ## What is OneSDK? OneSDK is FrankieOne’s client-side JavaScript SDK that enables fast, flexible, and secure integration of KYC and Identity Verification (IDV) services into your digital onboarding experience. It allows you to embed verification workflows directly into your product — whether through a hosted page, an iFrame, or a fully embedded integration inside your own app. OneSDK connects your frontend to FrankieOne’s orchestration platform, giving you access to a wide ranges of global verification vendors and data sources through a single, unified SDK and API. ## Why Choose OneSDK? Pre-built templates, modular components, and straightforward APIs help you launch verification experiences quickly and reliably. Access multiple vendors through FrankieOne’s orchestration layer, enabling seamless identity checks across document, biometric, and AML workflows. Easily switch, mix, or expand vendors without refactoring your code, ensuring long-term flexibility as your business and regulatory needs evolve. Gain end-to-end visibility with detailed event logs, audit trails, and analytics — all designed to maintain compliance and monitor performance with confidence. ## Core Components Capture and verify identity documents like passports, driver's licenses, and national ID cards. Implement face matching and liveness detection for enhanced security. Detect and prevent fraud through advanced risk assessment algorithms. A OneSDK workflow is a carefully orchestrated sequence of modules that work together to verify a user comprehensively. This approach provides you with a unified view of the onboarded entity. ## When to Use OneSDK? Use OneSDK whenever you want to deliver a smooth, compliant, and customisable verification experience without building vendor integrations or UI from scratch. For most businesses, Pre-Built Hosted Flows are the recommended starting point — fast to deploy, fully managed, and easily customised through the FrankieOne Portal or API. ## How does OneSDK Work? A OneSDK integration connects your client application to the FrankieOne API and multiple verification vendors in one seamless flow. The user starts verification from your app or link. OneSDK handles document capture, biometrics, and form input securely in the browser. FrankieOne orchestrates verification across connected vendors. Results are returned to your system via API or webhook. This approach simplifies integration while maintaining flexibility — you manage the experience, and FrankieOne manages the complexity of vendor connections. ## Integration Options OneSDK supports a range of integration approaches depending on your technical capability and UX goals. For most customers, Pre-built Hosted Flows are the fastest and most reliable way to go live — allowing you to start verifying customers in hours, not weeks. | Category | Pre-Built Hosted Flows | Custom Hosted Flows | Embedded Components | API-Only (No SDK) | | :------------------------- | :---------------------------------------------------- | :--------------------------------------------------- | :----------------------------------------------- | :------------------------------ | | **Integration Effort** | 🔵⚪️⚪️⚪️
No Code (Portal Only) / Single API Call | 🔵🔵⚪️⚪️
Some coding required | 🔵🔵🔵🔵
Most Coding (Frontend Development) | 🔵🔵🔵🔵
Highest | | **Branding Control** | 🎨🎨
Logo, fonts and colours | 🎨🎨🎨
More customization | 🎨🎨🎨🎨
Extensive control | 🎨🎨🎨🎨
Extensive control | | **Typical Time to Market** | 🚀 Within days | 🚄 Usually 3-6 weeks | 🚢 2 months+ subject to requirements | Depending on requirements | | **Hosting** | FrankieOne Hosted | FrankieOne Hosted | Your Site | N/A | | **Costs** | Monthly Hosting Fee | Once-off Implementation Fee plus Monthly Hosting Fee | Once-off Implementation Fee | Refer to API Cost Models | As your requirements grow, you can easily evolve toward Custom Hosted or Embedded OneSDK integrations for deeper branding or in-app experiences. ## Best Practices ##### Optimization Tips * Initialize OneSDK as early as possible in your app lifecycle. * Implement proper error handling for each verification step. * Use the testing environment for development and integration. * Monitor verification analytics to optimize your conversion rates. ##### Important Considerations * Always handle user consent appropriately. * Implement proper session management. * Store sensitive data securely. * Follow data privacy regulations in your region. ## Next Steps Get up and running with OneSDK in minutes. Review detailed API documentation and examples. Explore common implementation scenarios. # AML Screening & Monitoring Source: https://docs.frankieone.com/docs/anti-money-laundering Learn how FrankieOne's AML solution helps you screen against global watchlists, manage risk, and maintain ongoing compliance. ## What is AML Screening? Anti-Money Laundering (AML) screening is a critical compliance process for identifying individuals and organizations with connections to financial crime. It involves checking customer data against global watchlists to detect risks related to money laundering, terrorism financing, sanctions violations, and political exposure. FrankieOne's solution streamlines this process, from initial real-time screening at onboarding to continuous, automated monitoring throughout the customer lifecycle. *** ## How AML Screening Works Our AML capabilities are integrated directly into the FrankieOne workflow engine. First, you create an `individual` entity containing the customer's personal details, such as their full name, date of birth, and country of residence. You then execute a workflow that has been configured with an **AML Step**. Our platform takes the entity's details and screens them against our connected data sources. The workflow returns a clear result for the AML step—typically **`CLEAR`** or **`HIT`**. A `HIT` generates detailed Process Result Objects (PROs) and `issues` for any potential matches, allowing your team to investigate and classify the results. *** ## What We Screen For Our AML solution checks against a wide array of global sources to provide a comprehensive risk profile. * **Politically Exposed Persons (PEPs):** Identify individuals who hold prominent public functions and may present a higher risk for bribery or corruption. * **Sanctions Lists:** Screen against lists of individuals, entities, and countries subject to economic or trade sanctions by governments and international bodies. * **Adverse Media:** Scan global news sources for negative information linked to an individual that may indicate an elevated risk. * **Other Regulatory & Law Enforcement Watchlists:** Check against a wide range of official lists to identify potential bad actors. ### Intelligent Matching To increase accuracy and reduce false positives, our system uses sophisticated matching logic: * **Name Matching**: Checks against the entity's full name, as well as known aliases. * **Contextual Filtering**: Uses the entity's **date of birth**, **nationality**, and **country of residence** to filter out irrelevant matches from the screening results. *** ## Classifying AML Hits When an AML screening results in a `HIT`, your compliance team needs to review the potential matches and classify them. This is a critical step in managing your AML risk. You can update the status of one or more AML-related Process Result Objects (PROs) using the API. **Endpoint:** ```http theme={null} PATCH /v2/individuals/{entityId}/results/aml ``` **Request Body:** ```json theme={null} { "processResults": [ "pro_01J285FC7DH5G113KF109RJHSD", "pro_01J285FC6MDNE7SZPVS8D3GC7S" ], "manualStatus": "FALSE_POSITIVE", "comment": { "text": "Reviewed by compliance officer. Matches are for a different individual with a similar name." } } ``` ### Manual Status Options (`manualStatus`) When classifying a hit, you can set one of the following statuses: | Status | Description | | :--------------------- | :-------------------------------------------------------------------------------------------------------------------- | | `FALSE_POSITIVE` | The match is not the same person you are onboarding. | | `TRUE_POSITIVE` | The match is the same person, but a final decision has not been made. The hit remains unresolved. | | `TRUE_POSITIVE_ACCEPT` | The match is the same person, and your organization has decided to accept the risk and proceed with the relationship. | | `TRUE_POSITIVE_REJECT` | The match is the same person, and your organization has decided to reject the relationship. | | `UNKNOWN` | It is unclear if the match is the same person. The hit remains unresolved. | | `UNKNOWN_ACCEPT` | It is unclear if the match is the same person, but your organization has decided to accept the risk. | | `UNKNOWN_REJECT` | It is unclear if the match is the same person, and your organization has decided to reject the relationship. | After classifying hits, it is best practice to re-run the workflow. The AML step will re-evaluate the results based on your classifications. For example, a workflow that initially resulted in a `REVIEW` status due to unresolved hits may change to `PASS` if all hits are classified as `FALSE_POSITIVE`. *** ## Ongoing Monitoring Meeting your compliance obligations doesn't stop at onboarding. FrankieOne's Ongoing Monitoring feature automates the continuous screening of your customers. Once enabled, our platform perpetually monitors the entity against our data sources and automatically alerts you by triggering a pre-configured **"monitoring workflow"** if their status changes—for example, if they are added to a sanctions list or become a PEP. > *For a detailed guide on how to enable, disable, and manage this feature, please refer to our **[Ongoing Monitoring Documentation](/docs/ongoing-monitoring-v2)**.* *** ## Additional Resources * [Interpreting Workflow Results](/docs/interpreting-workflows-v2) * [Handling AML Results]() * [Ongoing Monitoring](/docs/ongoing-monitoring-v2) # Interpreting AML Screening Results Source: https://docs.frankieone.com/docs/anti-money-laundering-results A detailed guide to understanding the results of an AML check, from the high-level summary down to the details of each watchlist match. ## How to Read an AML Result When you execute a workflow containing an AML step, the API response provides a rich set of data to help you understand the outcome. This guide provides a structured, "top-down" walkthrough of how to parse the `workflowResult` object. The examples in this guide refer to a workflow execution response where a PEP match was found. Click to expand and see the full structure. ```json theme={null} { "requestId": "01HN9XHZN6MGXM9JXG50K59Q85", "workflowResult": { "workflowExecutionId": "wfe_01J...", "workflowExecutionState": "COMPLETED", "status": "REVIEW", "result": "REVIEW", "riskAssessment": { "riskLevel": "HIGH", "riskScore": 100, "riskFactors": [ { "factor": "is_pep", "value": "true", "score": 100 } ] }, "issues": [ { "category": "AML", "issue": "PEP", "severity": "WARNING" } ], "workflowStepResults": [ { "stepName": "AML", "result": "HIT", "summary": { "totalHits": 1, "totalUnresolved": 1, "numUnresolvedPEP": 1 }, "processResults": [ { "processResultId": "pro_01J...", "result": "HIT", "class": "AML", "supplementaryData": { "type": "AML", "matchData": { "name": "John Doe" }, "pepData": [ { "level": "2", "position": "Former Member of Parliament", "countryCode": "AUS" } ] }, "manualStatus": "UNRESOLVED" } ] } ] } } ``` *** ## Part 1: The Overall Outcome (Final Verdict) Always start by checking the top-level fields of the `workflowResult` object. These give you the final, authoritative outcome. | Field | Importance | Description | | :--------------------------- | :--------- | :---------------------------------------------------------------------------------------------------------------------- | | **`status`** | ‼️ | The conclusive recommendation (e.g., `PASS`, `FAIL`, `REVIEW`). **Base your primary business logic on this value.** | | **`workflowExecutionState`** | ‼️ | Confirms the workflow's technical status. **Must be `COMPLETED`**. | | **`issues`** | ⚠️ | An array of problems that require manual review. If `status` is `REVIEW`, this array contains the specific reasons why. | | **`riskAssessment`** | ⚠️ | The final risk profile of the entity, including the `riskLevel` and `riskScore`. | In the example, the `status` is `REVIEW`, which is directly caused by the `issues` array containing a `PEP` issue. ### Understanding AML Issues When the AML step finds a potential match, it generates an `issue` object. This is what typically drives the overall workflow `status` to `REVIEW`. | Category | Issue | Severity | Trigger Condition | | :------- | :---------- | :-------- | :---------------------------------------------------------- | | `AML` | `PEP` | `WARNING` | At least one valid Process Result contains `pepData`. | | `AML` | `SANCTIONS` | `WARNING` | At least one valid Process Result contains `sanctionData`. | | `AML` | `MEDIA` | `WARNING` | At least one valid Process Result contains `mediaData`. | | `AML` | `WATCHLIST` | `WARNING` | At least one valid Process Result contains `watchlistData`. | *** ## Part 2: The AML Step Result (`workflowStepResults`) Next, drill down into the `workflowStepResults` array and find the object where `stepName` is **`AML`**. This object contains the specific results of the screening. | Key Field | Description | | :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`result`** | The most important field for the step. A `result` of **`HIT`** means at least one potential match was found and requires review. A `result` of **`CLEAR`** means no matches were found. | | **`summary`** | An aggregated summary of the screening results, broken down by match type. | | **`processResults`** | An array containing the detailed evidence for each individual watchlist match. | ### The AML Summary Object The `summary` object gives you a quick, quantitative overview of the screening results. ```json theme={null} "summary": { "stepName": "AML", "totalHits": 12, "totalFalsePositives": 0, "totalTruePositives": 0, "totalUnresolved": 12, "numUnresolvedPEP": 1, "numUnresolvedSanction": 1, "numUnresolvedWatchlist": 10, "numUnresolvedAdverseMedia": 0, "providerSummaries": [...] } ``` This summary immediately tells you the scale and severity of the results. For example, `numUnresolvedSanction` highlights if a high-risk sanctions match is present and needs immediate attention. *** ## Part 3: The Process Results (The Raw Evidence) When an AML step returns a `HIT`, the `processResults` array will contain one or more Process Result Objects (PROs), each with `class: "AML"`. Each PRO represents a single potential match from a watchlist and contains all the data you need for your investigation. ### Anatomy of an AML PRO The most critical part of an AML PRO is the **`supplementaryData`** object. This is where you will find the details of the matched entity. | `supplementaryData` Field | Description | | :------------------------ | :------------------------------------------------------------------------------------------------------------------ | | **`matchData`** | Core information about the matched profile (name, date of birth, countries of association). | | **`pepData`** | If the match is a Politically Exposed Person, this array contains details about their position, level, and country. | | **`sanctionData`** | If the match is on a Sanctions list, this array contains details about the sanction, its source, and the reason. | | **`watchlistData`** | This array contains details for matches on other regulatory or law enforcement watchlists. | | **`mediaData`** | If the match is from Adverse Media, this array provides snippets and links to relevant news articles. | | **`referenceDocs`** | An array of URLs to source documents for further evidence. | This example shows a `processResult` for a `HIT` where the individual was matched against a PEP list. The `pepData` array is populated with the specific details of the political exposure. ```json theme={null} { "processResultId": "pro_01J...", "result": "HIT", "class": "AML", "supplementaryData": { "type": "AML", "matchData": { "name": "John Citizen" }, "pepData": [ { "level": "2", "position": "Former Member of Parliament", "countryCode": "AUS", "listingStart": "2010-01-01" } ] }, "manualStatus": "UNRESOLVED" } ``` *** ## Part 4: Next Steps - Classifying Hits and Re-evaluating After your compliance team reviews the evidence in the `processResults`, they must classify each hit (e.g., as a `FALSE_POSITIVE`). This is done by updating the `manualStatus` of each PRO. > For a detailed guide on how to perform this action via the API, please see our **[AML Screening & Monitoring Documentation](/docs/anti-money-laundering)**. ### Re-running the Workflow Once all hits have been classified, you **must re-run the workflow** for the entity. This is a critical step for two reasons: 1. **To Update the `status`**: The overall `workflowResult.status` will only change from `REVIEW` to `PASS` or `CLEAR` after the workflow is executed again and the AML step confirms that no unresolved hits remain. 2. **To Clear `issues`**: The re-execution will cause the AML step to re-evaluate the issues. If all PROs that previously caused a `PEP` issue are now classified as `FALSE_POSITIVE`, the issue will be cleared from the workflow result. This re-evaluation ensures your entity's compliance status is officially updated and your audit trail is accurate. # Assessing Risk in FrankieOne Source: https://docs.frankieone.com/docs/assessing-risk This guide provides a comprehensive overview of how to implement and configure the Risk-Based Onboarding Engine in FrankieOne v2.0.0. It covers the core concepts of risk calculation, workflow integration, and the detailed configuration of risk factors. ## How Risk Works in Workflows The FrankieOne v2 Risk Engine transforms static, check-based verification into a dynamic, intelligence-driven framework. This enables you to design sophisticated, risk-based user journeys where the level of due diligence is directly proportional to the calculated risk of an entity. ### Core Concepts The subject of the risk assessment, which can be an INDIVIDUAL or an ORGANIZATION. A container for a specific customer context (e.g., KYC Onboarding). Each service profile is assigned one and only one risk profile. The central JSON configuration that governs all risk calculations. It defines the risk levels (e.g., LOW, MEDIUM, HIGH) and the factors to be evaluated. A specific rule that extracts data, applies scoring logic, and produces a numerical score. Each factor is an independent unit of risk logic. The final output of a risk evaluation generated at the end of a workflow. It contains the aggregated score, the corresponding risk level, and a detailed list of all contributing factors. ### The Risk Assessment Lifecycle Risk is assessed in a multi-stage process integrated directly into the workflow execution. The system loads all VALID risk factors already associated with the entity's service profile into the workflow's context. The initial risk score is based on this pre-existing state. As the workflow progresses, steps like AML, IDV, and Onboarding Fraud checks generate processResults, which serve as the source data for many risk factors. A dedicated RISK step is triggered. This step evaluates all factors defined in the risk profile, applies the configured scoring logic (scoreMethod), and aggregates the results to produce a final score for each factor. The scores from all evaluated risk factors are summed to produce the final workflowRiskScore. This score is then mapped to a workflowRiskLevel. The complete RiskAssessment is added to the workflowResult. The new risk assessment is persisted. Any previous factors whose underlying data has changed are marked as STALE. ### Risk Factor Statuses Each risk factor has a status to manage its lifecycle and ensure calculation accuracy: | Status | Description | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **VALID** | The default status. The factor is current and contributes to the risk score. | | **STALE** | The underlying data used to generate the factor has changed (e.g., an entity's address was updated). Stale factors are excluded from future calculations and are replaced by new, `VALID` factors. | | **OVERRIDDEN** | A user has manually overridden the factor's score. The `manualOverrideScore` will be used instead of the system-calculated score. | | **DISCARDED** | The factor was generated during a workflow but later deemed irrelevant within the same execution. It is excluded from the final risk assessment. | *** ## Risk Profile Configuration The entire risk engine is driven by the `risk_profiles.json` configuration file. Each profile defines the `levels` and `factors` for risk calculation. ### `levels` Schema The `levels` array defines the qualitative risk bands and their corresponding numerical score ranges. ```json theme={null} "levels": [ { "label": "LOW", "range": { "min": 0, "max": 40 } }, { "label": "MEDIUM", "range": { "min": 41, "max": 70 } }, { "label": "HIGH", "range": { "min": 71, "max": 90 }, "extra": { "GenerateIssue": { "category": "RISK", "issue": "RISK_THRESHOLD_HIGH", "severity": "REVIEW" } } }, { "label": "UNACCEPTABLE", "range": { "min": 91 }, "extra": { "GenerateIssue": { "category": "RISK", "issue": "RISK_THRESHOLD_UNACCEPTABLE", "severity": "BLOCK" } } } ] ``` * **label**: The name of the risk level (e.g., `LOW`, `HIGH`). * **range**: Defines the numerical score boundaries. `min` and `max` are inclusive. * **extra.GenerateIssue**: An optional object that instructs the engine to generate a workflow issue when the risk level is reached. ### `factors` Schema The `factors` array lists all risk factors to be evaluated. Each factor object is a rule for calculating a specific risk score component. ```json theme={null} { "name": "fraud_email", "description": "Fraud Email Signal", "default": "LOW", "scoreMethod": "lookup", "aggregate": "max", "defaultScore": { "name": "default", "score": 0, "value": "LOW", "flags": ["include_zero"] }, "scores": [ { "value": "LOW", "score": 0, "flags": ["include_zero"] }, { "value": "MEDIUM", "score": 10 }, { "value": "HIGH", "score": 20 }, { "value": "UNACCEPTABLE", "score": 30 }, { "value": "UNKNOWN", "score": 40 } ] } ``` * **name**: The unique identifier for the risk factor (e.g., `fraud_email`). * **description**: A human-readable description for display and auditing. * **handler**: The name of the internal service responsible for data extraction and scoring logic (e.g., `jurisdiction_lookup`). * **scoreMethod**: The method for assigning a score (`lookup`, `lookup_range`, `bool`). * **aggregate**: The method for aggregating multiple scores into a single factor score (`sum`, `max`, `min`, `average`, `count`). This applies only when a handler returns multiple values. * **scores**: An array of objects defining the value-to-score mapping. * **defaultScore**: A fallback score to apply if the input data cannot be mapped via the `scores` array. *** ## Risk Factor Library This section provides a comprehensive catalogue of the risk factors available in the FrankieOne platform. Each factor is designed to assess a specific element of risk during the onboarding process. ### KYC Risk Factors (Individuals) These factors are applicable to `INDIVIDUAL` entities and focus on identity attributes, jurisdiction, and AML signals. Calculates risk based on the individual's age at the time of workflow execution. Example Configuration: ```json theme={null} { "name": "entity_age", "description": "Calculates risk based on the entity's age.", "handler": "entity_age", "scoreMethod": "lookup_range", "scores": [ { "name": "Minor", "range": { "max": 17 }, "score": 100 }, { "name": "Young Adult", "range": { "min": 18, "max": 25 }, "score": 15 }, { "name": "Standard Adult", "range": { "min": 26 }, "score": 0 } ], "defaultScore": { "value": "N/A", "score": 80 } } ``` Applies risk based on the type(s) of identity documents provided. It aggregates scores if multiple documents are present. Example Configuration: ```json theme={null} { "name": "document_type", "description": "Scores risk based on the provided document type.", "handler": "document_type_lookup", "scoreMethod": "lookup", "aggregate": "max", "scores": [ { "value": "PASSPORT", "score": 5 }, { "value": "DRIVERS_LICENSE", "score": 10 }, { "value": "UTILITY_BILL", "score": 40 } ], "defaultScore": { "value": "No Documents", "score": 0 } } ``` Scores risk based on the provided nationality. Example Configuration: ```json theme={null} { "name": "nationality_risk", "description": "Scores risk based on the provided nationality.", "handler": "jurisdiction_lookup", "config": { "source": "nationality" }, "scoreMethod": "lookup", "aggregate": "max", "scores": [ { "value": "IRN", "score": 100 }, { "value": "RUS", "score": 50 }, { "value": "AUS", "score": 0 } ], "defaultScore": { "value": "Other", "score": 30 } } ``` Scores risk based on the current residential address country. Example Configuration: ```json theme={null} { "name": "residential_country_risk", "description": "Risk based on the current residential address country.", "handler": "jurisdiction_lookup", "config": { "source": "address", "addressType": "RESIDENTIAL" }, "scoreMethod": "lookup", "aggregate": "max", "scores": [ { "value": "NGA", "score": 70 }, { "value": "AUS", "score": 5 } ], "defaultScore": { "value": "Other", "score": 30 } } ``` These boolean factors check for the presence of corresponding data in AML `processResults`. Example Configuration (for `is_pep`): ```json theme={null} { "name": "is_pep", "description": "Entity Has PEP Hits", "handler": "is_pep", "scoreMethod": "bool", "scores": [ { "value": true, "score": 50 } ] } ``` Scores risk based on the numerical PEP classification level (1-4). Example Configuration: ```json theme={null} { "name": "pep_level", "description": "Risk based on the PEP classification level", "handler": "pep_level_lookup", "scoreMethod": "lookup", "aggregate": "max", "scores": [ { "value": "1", "score": 100 }, { "value": "2", "score": 80 }, { "value": "3", "score": 50 }, { "value": "4", "score": 30 } ], "defaultScore": { "value": "N/A", "score": 0 } } ``` Scores risk based on the number of times an entity has executed a specific workflow. Example Configuration: ```json theme={null} { "name": "workflow_attempts", "description": "Total onboarding attempts for this workflow.", "handler": "workflow_attempts_counter", "scoreMethod": "lookup_range", "scores": [ { "name": "First Attempt", "range": { "max": 1 }, "score": 0 }, { "name": "Multiple Attempts", "range": { "min": 2, "max": 3 }, "score": 30 }, { "name": "High Attempts", "range": { "min": 4 }, "score": 70 } ] } ``` Scores risk based on custom key-value data provided by the client in the individual.customAttributes object. Example Configuration: ```json theme={null} { "name": "product_type_risk", "description": "Scores risk based on the client-provided 'product_type' attribute.", "handler": "custom_attribute_lookup", "config": { "attributeName": "product_type" }, "scoreMethod": "lookup", "scores": [ { "value": "Card Present", "score": 5 }, { "value": "Online Payments", "score": 20 } ], "defaultScore": { "value": "Other", "score": 10 } } ``` Scores risk based on the number of potential duplicate profiles for the entity that have not yet been resolved. Example Configuration: ```json theme={null} { "name": "unresolved_duplicates", "description": "Unresolved duplicates", "handler": "unresolved_duplicates", "scoreMethod": "lookup_range", "scores": [ { "name": "Any unresolved duplicates", "range": { "min": 1 }, "score": 20 } ] } ``` Scores risk based on the number of duplicate profiles that have been confirmed as `TRUE_POSITIVE`. Example Configuration: ```json theme={null} { "name": "true_positive_duplicates", "description": "Resolved duplicates", "handler": "true_positive_duplicates", "scoreMethod": "lookup_range", "scores": [ { "name": "Any resolved duplicates", "range": { "min": 1 }, "score": 2 } ] } ``` ### Onboarding Fraud Risk Factors This section details the risk factors derived from Onboarding Fraud checks. These checks provide signals for device, IP address, phone number, and email address risk. This factor scores risk based on the number of sessions used during an onboarding workflow. An excessive number of sessions can indicate suspicious behavior. Example Configuration: ```json theme={null} { "name": "fraud_count_session", "description": "Fraud Session Count", "scoreMethod": "lookup", "defaultScore": { "name": "Default", "value": "0", "score": 0, "flags": ["include_zero"] }, "scores": [ { "name": "Up to 2", "range": { "max": 2 }, "score": 0 }, { "name": "Between 3-5", "range": { "min": 3, "max": 5 }, "score": 10 }, { "name": "Greater than 5", "range": { "min": 6 }, "score": 20 } ] } ``` This factor aggregates risk signals from IP address checks across one or more sessions. Example Configuration: ```json theme={null} { "name": "fraud_ip_address", "description": "Fraud IP Signal", "aggregate": "max", "defaultScore": { "name": "default", "value": "LOW", "score": 0, "flags": ["include_zero"] }, "scores": [ { "value": "LOW", "score": 0, "flags": ["include_zero"]}, { "value": "MEDIUM", "score": 10 }, { "value": "HIGH", "score": 20 }, { "value": "UNACCEPTABLE", "score": 30 }, { "value": "UNKNOWN", "score": 40 } ] } ``` This factor aggregates risk signals from device checks across one or more sessions. Example Configuration: ```json theme={null} { "name": "fraud_device", "description": "Fraud Device Signal", "aggregate": "max", "defaultScore": { "name": "default", "score": 0, "value": "LOW", "flags": ["include_zero"] }, "scores": [ { "value": "LOW", "score": 0, "flags": ["include_zero"] }, { "value": "MEDIUM", "score": 10 }, { "value": "HIGH", "score": 20 }, { "value": "UNACCEPTABLE", "score": 30 }, { "value": "UNKNOWN", "score": 40 } ] } ``` This factor scores risk based on the fraud signal for the selected entity email address. Example Configuration: ```json theme={null} { "name": "fraud_email", "description": "Fraud Email Signal", "defaultScore": { "name": "default", "score": 0, "value": "LOW", "flags": ["include_zero"] }, "scores": [ { "value": "LOW", "score": 0, "flags": ["include_zero"] }, { "value": "MEDIUM", "score": 10 }, { "value": "HIGH", "score": 20 }, { "value": "UNACCEPTABLE", "score": 30 }, { "value": "UNKNOWN", "score": 40 } ] } ``` This factor scores risk based on the fraud signal for the selected entity phone number. Example Configuration: ```json theme={null} { "name": "fraud_phone_number", "description": "Fraud Phone Signal", "defaultScore": { "name": "default", "score": 0, "value": "LOW", "flags": ["include_zero"] }, "scores": [ { "value": "LOW", "score": 0, "flags": ["include_zero"] }, { "value": "MEDIUM", "score": 10 }, { "value": "HIGH", "score": 20 }, { "value": "UNACCEPTABLE", "score": 30 }, { "value": "UNKNOWN", "score": 40 } ] } ``` *** ## Risk in Workflows: The Fraud Step The Onboarding Fraud solution is integrated into workflows via a dedicated **Fraud Step**. ### Step Results The Fraud Step can return one of three results: | Result | Description | | :------------ | :-------------------------------------------------------------------------------------------- | | **CLEAR** | All underlying checks passed without raising any concerns. No operator action is required. | | **HIT** | One or more underlying checks returned results that should be reviewed by an operator. | | **UNCHECKED** | The step was unable to generate any results, likely due to a data validation or system issue. | ### Impact of Resolving Results on Risk Calculation When an operator resolves a `HIT`, their action directly impacts how risk is calculated on subsequent workflow runs. | Operator Action/Status | Effect on Risk Calculation | | :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | | **No manualStatus** (Unresolved) | The risk from the provider is used as is. | | FALSE\_POSITIVE | The risk for the result is ignored entirely and excluded from the calculation. | | TRUE\_POSITIVE\_ACCEPT | The risk for the result is forced to LOW to reflect that the signal is real but the risk has been accepted by the operator. | | TRUE\_POSITIVE\_REJECT | The risk for the result remains as it was from the provider, reflecting that the signal is real and has been rejected by the operator. | *** ## Advanced Configuration ### Aggregation Methods Aggregation applies only when a factor's handler yields multiple input values (e.g., multiple device risk scores). The engine first calculates an "item score" for each value and then collapses them into a single "factor score" using one of the following methods: | Method | Description | | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | | **max** | The final factor score is the highest score from all evaluated items. | | **sum** | The final factor score is the sum of all item scores. | | **min** | The final factor score is the lowest score from all evaluated items. | | **average** | The final factor score is the mathematical average of all item scores. | | **count** | The final score is determined by the total number of input items, which is then mapped against the ranges defined in the scores array. | ### Connector-Level HIT/CLEAR Mapping For some third-party providers, you can configure how their risk levels map to FrankieOne's `HIT` or `CLEAR` results at the connector level. This allows for fine-tuning of your risk appetite. By default, the mapping is: * `HIGH`, `MEDIUM`, `UNACCEPTABLE` -> **HIT** * `LOW` -> **CLEAR** You can override this behavior in the connector configuration. For example, to treat `MEDIUM` risk as `CLEAR`: ```json theme={null} "connector": { "provider": { "...rest of provider config": "", "v2": { "riskLevelPROResultMapping": { "FRAUD_DEVICE": { "MEDIUM": "CLEAR" }, "FRAUD_IP_ADDRESS": { "MEDIUM": "CLEAR" }, "FRAUD_EMAIL_ADDRESS": { "MEDIUM": "CLEAR" }, "FRAUD_PHONE_NUMBER": { "MEDIUM": "CLEAR" } } }, "...rest of provider config": "" } } ``` # Australian Documents Source: https://docs.frankieone.com/docs/australian-documents-v2 The FrankieOne KYC v2 API supports a variety of Australian documents for identity verification. This guide provides details on how to handle these documents effectively. ## Supported Australian Documents The FrankieOne KYC v2 API supports the following Australian documents: | Document Name | Document Type | | :---------------------------- | :------------------- | | Birth Certificate | `BIRTH_CERT` | | Centrelink Card | `CONCESSION` | | Citizenship Certificate | `CITIZENSHIP` | | Immigration Card (ImmiCard) | `IMMIGRATION` | | Drivers License | `DRIVERS_LICENSE` | | Marriage Certificate | `MARRIAGE_CERT` | | Name Change Certificate | `NAME_CHANGE` | | National Health ID (Medicare) | `NATIONAL_HEALTH_ID` | | Passport | `PASSPORT` | *** ### Birth Certificates Birth certificates are official documents issued by the government that record an individual's birth. They include details such as the individual's name, date of birth, place of birth, and parentage. When submitting a birth certificate for verification, ensure the document is clear, complete, and issued by an official authority. All required details, as specified below, must be included: **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :----------------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format must be `YYYY-MM-DD` | | Document Type | `type` | Must be `BIRTH_CERT` | | Name | `name` | Must match the birth certificate exactly (Given name, Middle name, Family name, and Other names) | | Field Name | Field | Notes | | :----------------------------- | :--------------------------------------- | :------------------------------------------------------------------------------------------------ | | Certificate Number | `secondaryIdentifier` | Enter in the `secondaryIdentifier` field | | Date of Print | `supplementaryData.dateOfPrint` | Enter in Supplementary Data as `dateOfPrint`. Format: `YYYY-MM-DD` | | Registered Family Name | `supplementaryData.registeredFamilyName` | Enter in Supplementary Data as `registeredFamilyName` | | Registered Given Name | `supplementaryData.registeredGivenName` | Enter in Supplementary Data as `registeredGivenName` | | Registered Other Given Name(s) | `supplementaryData.registeredOtherNames` | Enter in Supplementary Data as `registeredOtherNames` | | Registration Date | `supplementaryData.registrationDate` | Enter in Supplementary Data as `registrationDate`. Accepts `YYYY-MM-DD` or `YYYY` | | Registration District | `supplementaryData.registrationDistrict` | Optionally enter in Supplementary Data as `registrationDistrict` if available | | Registration Number | `primaryIdentifier` | Enter in the `primaryIdentifier` field | | Registration State | `subdivision` | Use the `subdivision` field. Accepted values: `VIC`, `NSW`, `ACT`, `WA`, `SA`, `NT`, `QLD`, `TAS` | Always provide all available information for the most accurate verification. Matching requirements for registration number and date may vary depending on: * **Issuing State or Territory** * **Registration Date** * **Historical Registry Format** **For NSW, VIC, WA, SA, TAS, ACT, and NT:**\ You must provide at least one of the following: * Registration Number (`primaryIdentifier`) * Certificate Number (`secondaryIdentifier`) **For Queensland (QLD) Only:**\ You must provide either: * Registration Date (`supplementaryData.registrationDate`) * Certificate Number (`secondaryIdentifier`) Supplying both fields where available is recommended for optimal verification success. Tips for Birth Certificate Verification For best results when processing birth certificates: * Provide all available fields, including optional ones * Use names and dates exactly as shown on the certificate * Pay attention to historical date formats and registration district spelling * Note any differences between registered and current legal names * **Matching requirements may vary by state, territory, or certificate age.** Supplying complete and accurate information maximizes verification success. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Always "IDENTITY" for identity documents "primaryIdentifier": "000734130", // Registration Number as shown on the birth certificate "secondaryIdentifier": "P0001975", // Certificate Number as shown on the birth certificate "type": "BIRTH_CERT", // Document type, must be "BIRTH_CERT" for birth certificates "subdivision": "NSW", // Registration State (e.g., VIC, NSW, ACT, WA, SA, NT, QLD, TAS) "country": "AUS", // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia "supplementaryData": { // Additional birth certificate details "type": "BIRTH_CERT", // Supplementary data type, must be "BIRTH_CERT" "registrationDate": "2000", // Registration date (format: "YYYY" or "YYYY-MM-DD" as shown on the certificate) "registrationDistrict": "Sydney", // Registration district (optional, if available on the certificate) "dateOfPrint": "2000-03-24", // Date the certificate was printed (format: "YYYY-MM-DD") "registeredGivenName": "Johnny", // Registered given name(s) as shown on the certificate "registeredOtherNames": "Hugo Boss", // Registered other given name(s), if present "registeredFamilyName": "Danger" // Registered family name as shown on the certificate } } } ``` *** ### Centrelink Cards Centrelink cards are official documents issued by the Australian government that provide access to social security and welfare benefits. These cards contain personal details such as the cardholder's name, date of birth, and Customer Reference Number (CRN). **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :-------------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format must be `YYYY-MM-DD` | | Document Type | `type` | Must be one of `CONCESSION`, `HEALTH_CONCESSION`, or `PENSION` | | Name | `name` | Must match the Centrelink card exactly (Given name, Middle name, Family name, and any others) | | Field Name | Field | Notes | | :------------------------ | :------------------ | :----------------------------------------------------------- | | Customer Reference Number | `primaryIdentifier` | Enter the Centrelink Customer Reference Number in this field | | Card Expiry Date | `expiryDate` | Enter the expiry date in this field. Format: `YYYY-MM-DD` | Ensure the card is valid and not expired. The `expiryDate` field must be provided in the correct format. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", "expiryDate": { "year": "1990", // Expiry year of the Centrelink card (YYYY) "month": "03", // Expiry month of the Centrelink card (MM) "day": "27", // Expiry day of the Centrelink card (DD) "unstructured": "27-03-1990", // Expiry date in unstructured format (DD-MM-YYYY) }, "primaryIdentifier": "000734130", // Centrelink Customer Reference Number (CRN) "type": "CONCESSION", // Document type: CONCESSION, HEALTH_CONCESSION, or PENSION "country": "AUS" // Country code (ISO 3166-1 alpha-3), must be AUS for Australia } } ``` *** ### Citizenship Certificates Citizenship certificates are official documents issued by the Australian government that confirm an individual's Australian citizenship. These certificates contain personal details such as the individual's name, date of birth, and certificate (stock) number. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :----------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD` | | Document Type | `type` | Must be `CITIZENSHIP` | | Name | `name` | Must match the certificate exactly (Given name, Middle name, Family name, and Other names) | | Field Name | Field | Notes | | :---------------- | :----------------------------------- | :---------------------------------------------------------------------------------- | | Stock Number | `primaryIdentifier` | Enter the certificate's stock number in this field | | Acquisition Date | `supplementaryData.acquisitionDate` | Must be in `YYYY-MM-DD` format | | Primary Country | `supplementaryData.primaryCountry` | Must be `AUS` (Australian citizenship) | | Secondary Country | `supplementaryData.secondaryCountry` | Optional for dual citizenships; must be a valid ISO 3166-1 alpha-3 code if provided | **Ensure the certificate is valid and issued by the appropriate authority.** The `acquisitionDate` field must be provided in the correct format. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class, always "IDENTITY" for identity documents "primaryIdentifier": "000734130", // Stock Number as shown on the citizenship certificate "type": "CITIZENSHIP", // Document type, must be "CITIZENSHIP" "country": "AUS", // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia "supplementaryData": { // Additional certificate details "type": "CITIZENSHIP", // Supplementary data type, must be "CITIZENSHIP" "acquisitionDate": "2000-01-23", // Date citizenship was acquired, format: YYYY-MM-DD "primaryCountry": "AUS", // Primary country of citizenship, must be "AUS" "secondaryCountry": "NZL" // Optional: Secondary country for dual citizenships (ISO 3166-1 alpha-3) } } } ``` *** ### Drivers Licenses Australian driver licences are official documents issued by Australian state or territory governments, authorizing individuals to operate vehicles. Each licence contains personal details such as the holder’s name, date of birth, licence number, and card number. Requirements and formats may vary by jurisdiction. | Field Name | Field | Notes | | :------------ | :------------ | :------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD` | | Document Type | `type` | Must be `DRIVERS_LICENSE` | | Name | `name` | Must match the licence exactly (Given name, Middle name, Family name, and Other names) | | Field Name | Field | Notes | | :------------- | :-------------------- | :-------------------------------------------------------------------------------------------------------- | | Licence Number | `primaryIdentifier` | Enter the licence number as shown on the card | | Card Number | `secondaryIdentifier` | Enter the card number as shown on the card. This field is mandatory for all states except Victoria (VIC). | | Subdivision | `subdivision` | State or territory of issue. Accepted values: `VIC`, `NSW`, `ACT`, `WA`, `SA`, `NT`, `QLD`, `TAS` | Provide both the licence number and card number where available. These may differ by state and are both required for accurate verification. | State | Format | Length | Example | | :---- | :----------- | :------- | :---------- | | ACT | Numeric | Up to 10 | `123456789` | | NT | Numeric | Up to 10 | `123456789` | | QLD | Numeric | 8-9 | `12345678` | | NSW | Alphanumeric | 6-8 | `N49187` | | SA | Alphanumeric | 6 | `ABC123` | | TAS | Alphanumeric | 6-8 | `A12345` | | VIC | Numeric | Up to 10 | `123456789` | | WA | Numeric | 7 | `1234567` | | State | Format | Length | Example | | :---- | :----------- | :----- | :----------- | | ACT | Alphanumeric | 10 | `ABC1234567` | | NT | Numeric | 6-8 | `123456` | | QLD | Alphanumeric | 10 | `ABC1234567` | | NSW | Numeric | 10 | `1234567890` | | SA | Alphanumeric | 9 | `ABC123456` | | TAS | Alphanumeric | 9 | `ABC123456` | | VIC | Alphanumeric | 8 | `ABC12345` | | WA | Alphanumeric | 8-10 | `ABC123456` | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class, always "IDENTITY" for identity documents "primaryIdentifier": "000734130", // Licence Number as shown on the driver licence "secondaryIdentifier": "P0001975", // Card Number as shown on the driver licence (may be required for some states) "type": "DRIVERS_LICENSE", // Document type, must be "DRIVERS_LICENSE" "subdivision": "VIC", // State or territory of issue (e.g., VIC, NSW, QLD, etc.) "country": "AUS" // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia } } ``` Australian Capital Territory Driver Licence sample - front Australian Capital Territory Driver Licence sample - back Northern Territory Driver Licence - post 1 November 2020 sample - front Northern Territory Driver Licence - post 1 November 2020 sample - back Northern Territory Driver Licence - pre 1 November 2020 sample - front Northern Territory Driver Licence - pre 1 November 2020 sample - back Queensland Driver Licence – post 12 June 2019 sample - front Queensland Driver Licence sample - back Queensland Driver Licence - pre 12 June 2019 sample - front Queensland Driver Licence sample - back New South Wales Driver Licence sample - front New South Wales Driver Licence sample - back New South Wales Digital Driver Licence sample South Australia Driver Licence sample - front South Australia Driver Licence sample - back South Australia Digital Driver Licence sample – Overview Tab South Australia Digital Driver Licence sample – DetailsTab Tasmania Driver Licence sample - front Tasmania Driver Licence sample - back Victoria Driver Licence – post 7 November 2022 sample - front Victoria Driver Licence - post 7 November 2022 sample - back Victoria Driver Licence - pre 7 November 2022 sample - front Victoria Driver Licence – pre 7 November 2022 sample - back Western Australia Driver Licence sample - front Western Australia Driver Licence sample - back ##### Victorian Licence Verification – Card Number Handling (Effective July 1, 2023) Victorian driver licence card number verification is now subject to special rules: * For licences flagged as compromised (e.g., due to the Optus breach), the DVS will verify the current card number. * For non-compromised licences, the card number is not checked and may match the licence number. * Always collect and submit the card number, as verification requirements may change based on historical or future data breaches. * If you are a direct DVS user, you may see an audit log entry: “Successful Match – Card Number hasn’t been checked.” *** ### Immigration Cards (ImmiCard) ImmiCards are official identity documents issued by the Australian Department of Home Affairs to eligible non-citizens, including visa holders, refugees, and humanitarian entrants. Each ImmiCard contains the holder’s name, date of birth, and a unique ImmiCard number. ImmiCards are used as evidence of identity and residency status in Australia. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :-------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format must be `YYYY-MM-DD` | | Document Type | `type` | Must be `IMMIGRATION` | | Name | `name` | Must match the ImmiCard exactly (Given name, Middle name, Family name, and Other names) | For individuals with a single name, use a hyphen (`-`) in the `givenName` field. **Example:** For "Cher", use `{"givenName": "-", "familyName": "Cher"}`. | Field Name | Field | Notes | | :-------------- | :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ImmiCard Number | `primaryIdentifier` | Enter the ImmiCard number exactly as shown on the card. Must be 9 characters: 3 letters (A-Z, case-insensitive) followed by 6 digits (0-9). Example: `PRE123456` | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Always "IDENTITY" for identity documents "primaryIdentifier": "PRE123456", // ImmiCard Number (must be 3 uppercase letters followed by 6 digits, e.g., "PRE123456") "type": "IMMIGRATION", // Document type, must be "IMMIGRATION" for ImmiCard "country": "AUS" // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia } } ``` ##### Common Validation Issues When submitting ImmiCard documents, ensure: * The ImmiCard number is exactly 9 characters: 3 uppercase letters (A–Z) followed by 6 digits (0–9), e.g., `PRE123456`. * Name fields must match the ImmiCard exactly, including case, spelling, and spacing. For individuals with a single name, use a hyphen (`-`) for the given name (e.g., `{"givenName": "-", "familyName": "Cher"}`). * The date of birth must be in `YYYY-MM-DD` format. * Include all names as shown on the card. * Double-check all values for accuracy to avoid verification failures. *** ### Marriage Certificate Marriage certificates are official documents that record the marriage of two individuals. They include personal details such as the names of the individuals, date of marriage, and the issuing authority. ##### Best Practices for Marriage Certificate Verification * Confirm the certificate format before mapping fields. * Use correct ISO date formats for all date fields. * Follow state-specific requirements, especially for Victoria. * Provide all available optional fields for higher verification accuracy. * Ensure names match the certificate exactly, including spelling and order. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :--------------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD` | | Document Type | `type` | Must be `MARRIAGE_CERT` | | Name | `name` | Must match the certificate exactly (Given name, Middle name, Family name, and any other names) | | Field Name | Field | Notes | | :-------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------- | | Registration Number | `primaryIdentifier` | Enter the official registration number as shown on the certificate | | Certificate Number | `secondaryIdentifier` | Enter the certificate number as shown on the certificate | | Document Type | `type` | Must be `MARRIAGE_CERT` | | Registration State | `subdivision` | State or territory of registration: `VIC`, `NSW`, `ACT`, `WA`, `SA`, `NT`, `QLD`, `TAS` | | Registration Date | `supplementaryData.registrationDate` | Date the marriage was registered. Format: `YYYY-MM-DD` or `YYYY` as shown on the certificate | | Date of Print | `supplementaryData.dateOfPrint` | Date the certificate was printed. Format: `YYYY-MM-DD` | | Marriage Date | `supplementaryData.marriageDate` | Date the marriage took place. Format: `YYYY-MM-DD` | | Partner 1 Given Name | `supplementaryData.partner1GivenName` | Given name(s) of Partner 1 as shown on the certificate | | Partner 1 Family Name | `supplementaryData.partner1FamilyName` | Family name of Partner 1 as shown on the certificate | | Partner 1 Other Name | `supplementaryData.partner1OtherName` | Other name(s) of Partner 1, if present (optional) | | Partner 2 Given Name | `supplementaryData.partner2GivenName` | Given name(s) of Partner 2 as shown on the certificate | | Partner 2 Family Name | `supplementaryData.partner2FamilyName` | Family name of Partner 2 as shown on the certificate | | Partner 2 Other Name | `supplementaryData.partner2OtherName` | Other name(s) of Partner 2, if present (optional) | Ensure the registration state matches the issuing authority on the marriage certificate. Provide all available details for the most accurate verification. **State/Territory Matching Requirements:** * **NSW, VIC, WA, SA, TAS, ACT, NT:**\ You must provide at least one of the following: * Registration Number (`primaryIdentifier`) * Certificate Number (`secondaryIdentifier`) * **Queensland (QLD):**\ You must provide either: * Registration Date (`supplementaryData.registrationDate`) * Certificate Number (`secondaryIdentifier`) Supplying both fields where available is recommended for optimal verification success. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class, always "IDENTITY" for identity documents "primaryIdentifier": "000734130", // Registration Number as shown on the marriage certificate "secondaryIdentifier": "P0001975", // Certificate Number as shown on the marriage certificate "type": "MARRIAGE_CERT", // Document type, must be "MARRIAGE_CERT" for marriage certificates "country": "AUS", // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia "subdivision": "NSW", // Registration State or Territory (e.g., VIC, NSW, ACT, WA, SA, NT, QLD, TAS) "supplementaryData": { "type": "MARRIAGE_CERT", // Supplementary data type, must be "MARRIAGE_CERT" "registrationDate": "2023", // Date the marriage was registered; format: "YYYY" or "YYYY-MM-DD" as shown on the certificate "dateOfPrint": "2023-10-01", // Date the certificate was printed; format: "YYYY-MM-DD" "marriageDate": "2023-10-01", // Date the marriage took place; format: "YYYY-MM-DD" "partner1GivenName": "John", // Given name(s) of Partner 1 as shown on the certificate "partner1FamilyName": "Doe", // Family name of Partner 1 as shown on the certificate "partner1OtherName": "Jonah", // Other name(s) of Partner 1, if present (optional) "partner2GivenName": "Jane", // Given name(s) of Partner 2 as shown on the certificate "partner2FamilyName": "Doe", // Family name of Partner 2 as shown on the certificate "partner2OtherName": "Jonesy" // Other name(s) of Partner 2, if present (optional) } } } ``` ##### Victoria (VIC) State-Specific Requirements For marriage certificate verification in Victoria: * Enter the details from the left-hand column or first row as Name 2, regardless of the order on the certificate. * Always refer to the latest DVS specifications for Victoria and other states to ensure correct field mapping. ##### Marriage Certificate Formats Australian marriage certificates may use different participant labels depending on the certificate version: * **Traditional:** Bride/Groom * **Modern:** Partner 1/Partner 2 Use the format that matches the certificate you are processing. *** ### Name Change Certificates Name change certificates are official documents issued by Australian state or territory authorities to record an individual's legal change of name. These certificates include details such as the person's previous name(s), new name(s), date of registration, and the issuing authority. Name change certificates are required for official identity verification when an individual has changed their legal name. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :-------------------------------------------------------------------------------------- | | Country | `country` | Must be `AUS` | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD` | | Document Type | `type` | Must be `NAME_CHANGE` | | Name | `name` | Must match the certificate exactly (Given, Middle, Family, and Other names, if present) | | Field Name | Field | Notes | | :--------------------- | :-------------------------------------------- | :--------------------------------------------------------------------------------------- | | Registration Number | `primaryIdentifier` | Official registration number as shown on the certificate | | Certificate Number | `secondaryIdentifier` | Certificate number as shown on the certificate | | Registration State | `subdivision` | State/territory of registration: `VIC`, `NSW`, `ACT`, `WA`, `SA`, `NT`, `QLD`, `TAS` | | Registration Date | `supplementaryData.registrationDate` | Date the name change was registered (`YYYY-MM-DD` or `YYYY` as shown on the certificate) | | Date of Print | `supplementaryData.dateOfPrint` | Date the certificate was printed (`YYYY-MM-DD`) | | Registered Family Name | `supplementaryData.registeredFamilyName` | As shown on the certificate; may differ from current legal name | | Registered Given Name | `supplementaryData.registeredGivenName` | As shown on the certificate | | Registered Other Names | `supplementaryData.registeredOtherGivenNames` | Other given names, if present | Provide all names exactly as shown on the certificate, including any previous names. Supplying complete and accurate information maximizes verification success. **State/Territory Matching Requirements:** * **NSW, VIC, WA, SA, TAS, ACT, NT:**\ You must provide at least one of the following: * Registration Number (`primaryIdentifier`) * Certificate Number (`secondaryIdentifier`) * **Queensland (QLD):**\ You must provide either: * Registration Date (`supplementaryData.registrationDate`) * Certificate Number (`secondaryIdentifier`) Supplying both fields where available is recommended for optimal verification success. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Always "IDENTITY" for identity documents "primaryIdentifier": "000734130", // Registration Number as shown on the name change certificate "secondaryIdentifier": "P0001975", // Certificate Number as shown on the name change certificate "type": "NAME_CHANGE", // Document type, must be "NAME_CHANGE" for name change certificates "country": "AUS", // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia "subdivision": "VIC", // Registration State or Territory (e.g., VIC, NSW, ACT, WA, SA, NT, QLD, TAS) "supplementaryData": { "type": "NAME_CHANGE", // Supplementary data type, must be "NAME_CHANGE" "registrationDate": "2000-01-20", // Date the name change was registered; format: "YYYY-MM-DD" or "YYYY" as shown on the certificate "dateOfPrint": "2000-01-20", // Date the certificate was printed; format: "YYYY-MM-DD" "registeredFamilyName": "Doe", // Registered family name as shown on the certificate (may differ from current legal name) "registeredGivenName": "John", // Registered given name(s) as shown on the certificate "registeredOtherGivenNames": "Chris" // Other registered given names, if present (optional) } } } ``` *** ### National Health ID (Medicare) National Health ID cards, commonly known as Medicare cards, are issued by the Australian government to provide access to healthcare services. They include personal details such as the individual's name, date of birth, and Medicare number. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :---------------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Must be in `YYYY-MM-DD` format | | Document Type | `type` | Must be `NATIONAL_HEALTH_ID` | | Name | `name` | Must match the card exactly (Given name, Middle name, Family name, and any other names present) | | Field Name | Field | Notes | | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------ | | Card Number | `primaryIdentifier` | Medicare card number as shown on the card (usually 10 digits, e.g., `1234 56789 0`) | | Card Type | `subtype` | Card type: `G` (Green), `B` (Blue), or `Y` (Yellow) | | Expiry Date | `expiryDate` | Card expiry date in `YYYY-MM-DD` or `YYYY-MM` format as per the card | | Individual Reference | `supplementaryData.reference` | Individual reference number (optional, as shown on the card; usually 1 digit at the end) | | Name on Card | `supplementaryData.nameOnCardLine1`,
`supplementaryData.nameOnCardLine2`,
`supplementaryData.nameOnCardLine3`,
`supplementaryData.nameOnCardLine4`,
`supplementaryData.middleNameOnCard` | Names as printed on the card, including all lines and middle name if present. Provide exactly as shown. | #### Important Notes for Medicare Card Verification * The `subtype` field indicates the card type (`G` = Green, `B` = Blue, `Y` = Yellow). * Supplementary fields such as `nameOnCardLine1`, `nameOnCardLine2`, `nameOnCardLine3`, `nameOnCardLine4`, and `middleNameOnCard` are optional but recommended for higher verification accuracy; fill them exactly as they appear on the card. * The `supplementaryData.reference` (individual reference number) is optional but can assist with verification. * Ensure all fields are completed accurately and match the card to avoid verification issues. * **Optional Field** - The `subdivision` field must match the state or territory where the card was issued (e.g., VIC, NSW, QLD, etc.).
**Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Always "IDENTITY" for identity documents "expiryDate": { "year": "1990", // Expiry year as shown on the Medicare card (YYYY) "month": "03", // Expiry month as shown on the Medicare card (MM) "day": "27", // Expiry day as shown on the Medicare card (DD) "unstructured": "1990-03-27", // Expiry date in unstructured format (YYYY-MM-DD), as printed on the card "type": "GREGORIAN" // Calendar type; use "GREGORIAN" for standard dates }, "primaryIdentifier": "000734130", // Medicare card number (usually 10 digits, e.g., "1234567890") "type": "NATIONAL_HEALTH_ID", // Document type, must be "NATIONAL_HEALTH_ID" for Medicare cards "subtype": "G", // Card type: "G" (Green), "B" (Blue), or "Y" (Yellow) as indicated on the card "subdivision": "VIC", // State or territory of issue (e.g., VIC, NSW, QLD, etc.) "country": "AUS", // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia "supplementaryData": { "type": "NATIONAL_HEALTH_ID", // Supplementary data type, must be "NATIONAL_HEALTH_ID" "reference": "1", // Individual reference number (usually a single digit at the end of the card number) "nameOnCardLine1": "Johnny", // First line of the name as printed on the card "nameOnCardLine2": "Danger", // Second line of the name as printed on the card (if present) "nameOnCardLine3": "null", // Third line of the name as printed on the card (if present, otherwise "null") "nameOnCardLine4": "null", // Fourth line of the name as printed on the card (if present, otherwise "null") "middleNameOnCard": "null" // Middle name as printed on the card (if present, otherwise "null") } } } ``` *** ### Australian Passports Australian passports are official travel documents issued by the Australian government that certify an individual's identity and citizenship. Each passport contains key personal information, including the holder's full name, date of birth, passport number, nationality, and expiration date. When submitting an Australian passport for verification, ensure that all details are entered exactly as they appear on the passport. This includes correct spelling, capitalization, special characters, and the precise order of names. Accurate data entry is critical for successful verification. Verify Australian passports for citizens and permanent residents. Ensure all details match the passport exactly, including name, date of birth, and passport number. Verify Australian visas for temporary residents and visitors. Use the passport number associated with the visa and match all personal details as shown on the travel document. ##### Key Passport Verification Guidelines **Exact Name Matching** * Enter names exactly as shown on the passport, including capitalization, special characters, spaces, and diacritics. **Country Codes** * For Australian passports, use `AUS`. * For visas, use the ISO 3166-1 alpha-3 code of the passport’s issuing country. **Document Numbers** * Always provide the passport number, even for visa verification. * Ensure the passport number matches the one associated with the visa. * Incorrect or expired passport numbers will cause verification to fail. **Name Order for Visas** * For visa holders, follow the name order and format as printed on the passport, regardless of local conventions. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------- | | Country | `country` | Must be set to `AUS` | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD` | | Document Type | `type` | Must be `PASSPORT` | | Name | `name` | Enter the full name exactly as shown on the passport (including all given, middle, family, and other names; match spelling, order, and capitalization) | | Gender | `gender` | Must be provided in the entity object as `M`, `F`, or `X` | | Field Name | Field | Notes | | :--------------- | :------------------ | :--------------------------------------------------------- | | Passport Number | `primaryIdentifier` | Enter the passport number exactly as shown on the document | | Document Type | `type` | Must be `PASSPORT` | | Country of Issue | `country` | Must be `AUS` | The passport number, also known as the travel document number, must adhere to the following formats for successful validation: * 8 characters: 1 letter followed by 7 numbers. * 9 characters: 2 letters followed by 7 numbers. The DVS only supports Australian passports with these specified lengths and formats. Submitting a passport number that does not meet these criteria will result in a validation error. **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Always "IDENTITY" for identity documents "primaryIdentifier": "N1234567", // Passport number as shown on the passport (letters and numbers, exact match) "type": "PASSPORT", // Document type, must be "PASSPORT" for Australian passports "country": "AUS" // Country code (ISO 3166-1 alpha-3), must be "AUS" for Australia } } ``` # Chinese Documents Source: https://docs.frankieone.com/docs/chinese-documents-v2 The FrankieOne KYC v2 API supports some Chinese documents for identity verification. This guide provides details on how to handle these documents effectively. ## Supported Chinese Documents The FrankieOne KYC v2 API supports the following Chinese documents: | Document | Code | | :---------- | :------------ | | National ID | `NATIONAL_ID` | *** ### Chinese National ID Card (身份证) Chinese National ID Cards (身份证) are official identification documents issued by the Chinese government that confirm an individual's identity and citizenship. They include personal details such as the individual's name, date of birth, ID card number, and expiration date. **Required Fields** | Field Name | Field | Notes | | ------------- | --------------------- | ------------------------------------------------------------------------------------- | | Document Type | `type` | Must be `NATIONAL_ID`. | | Country | `country` | Must be `CHN` (China). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. | | Family Name | `familyName` | Pinyin family name in uppercase (e.g., `ZHANG`). | | Given Name | `givenName` | Pinyin given name (may include middle name), in uppercase (e.g., `WEIMING`). | | Chinese Name | `homeCountryFullName` | Full name in Chinese characters, provided in `supplementaryData.homeCountryFullName`. | * Always provide both Pinyin and Chinese character versions of the name. * Maintain correct character order in both formats. * Use uppercase for all Pinyin names. * Ensure UTF-8 encoding for Chinese characters. * All fields must be completed accurately to avoid validation errors. | Field Name | Field | Notes | | ----------- | ------------------- | -------------------------------------------------------- | | ID Number | `primaryIdentifier` | 18-digit ID number, no spaces or special characters. | | Document ID | `documentId` | Unique identifier for the document in FrankieOne system. | The `documentId` uniquely identifies the document record in our system. The `primaryIdentifier` is the official government-issued ID number. **Name Handling Guidelines:** Provide the applicant's name in Pinyin using uppercase letters, matching the order on the ID card. ```json theme={null} { "familyName": "ZHANG", // Family name in uppercase Pinyin "givenName": "WEIMING" // Given name (and middle name, if any) in uppercase Pinyin } ``` * Use uppercase letters for all Pinyin names. * Ensure the order and spelling match the official ID card. * Do not include spaces or special characters. Provide the full name in Chinese characters exactly as it appears on the ID card, using UTF-8 encoding. ```json theme={null} { "supplementaryData": { "homeCountryFullName": "张伟明" // Full name in Chinese characters } } ``` * The Chinese name must match the ID card precisely, including character order. * Place this value in `supplementaryData.homeCountryFullName`. * Ensure correct encoding to avoid data loss. *** ### Chinese Name Transliteration Check (Name Validation) For enhanced identity verification, FrankieOne offers a Chinese name transliteration check. This feature verifies that an applicant’s English/Pinyin name (e.g. “Wei Wang”) is a plausible transliteration of their name written in Chinese characters (e.g. “王伟”), helping to reduce identity fraud. The check is supported for Chinese identity documents, including the Chinese National ID and Chinese passports. The transliteration module is built in-house by FrankieOne. It is not a third-party integration, and applicants' name data is not passed to an external transliteration provider for this step. The matching logic is based on standard transliteration rules. As an internal FrankieOne module, it does not carry an external certification. **Note:** This check, historically known as `namev` in V1, uses FrankieOne’s in-built transliteration and name-matching capability to assess whether two name versions are a plausible match, helping to reduce the risk of identity fraud. **How It Works & Configuration** The transliteration check is not enabled by default. It must be configured in your workflow by the FrankieOne team as a distinct step called **`NAME_VALIDATION`**. 1. The **anglicized (English/Pinyin) name** is taken from the primary `individual.name` object (`givenName` and `familyName`). 2. The **native script (Chinese character) name** is taken from the `document.supplementaryData.homeCountryFullName` field on supported Chinese identity documents, including `NATIONAL_ID` and `PASSPORT`. 3. The `NAME_VALIDATION` step in the workflow sends these two names to the transliteration service. 4. If the native script name (`homeCountryFullName`) is not provided, the step will be skipped and the result will be `SKIPPED`. 5. When the step is executed, its outcome is added to `workflowStepResults` in the API response, with a result of `MATCH` or `NO_MATCH`. To enable this feature, please contact your FrankieOne representative and request the `NAME_VALIDATION` step be added to your KYC workflow. **Example Result** When the `NAME_VALIDATION` step is executed, a `workflowStepResult` is added to the API response. The outcome is detailed within the `processResult` object, which will have a result of `MATCH` or `NO_MATCH`. ```json theme={null} { "workflowStepResults": [ { "stepName": "NAME_VALIDATION", "result": "SUCCESS", "processResults": [ { "provider": "Frankieone", "objectType": "NAME", "class": "KYC", "result": "MATCH", "checkDate": "2025-10-15T07:40:57.000Z", "data": { "reference": "av-ref-12345", "message": "Name transliteration check passed." } } ] } ] } ``` *** **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", "documentId": "92de15f64-5717-4562-b3fc-2c963f6665a7", "primaryIdentifier": "110105199003077341", "type": "NATIONAL_ID", "country": "CHN" }, "supplementaryData": { "type": "NATIONAL_ID", "homeCountryFullName": "张伟明" } } ``` ##### Important Considerations for National ID The Chinese National ID number contains encoded information including region code, birth date, sequence number, and checksum digit. Ensure the full 18-digit number is provided without spaces or special characters. **Common validation issues to avoid:** * Using incorrect order or casing for Pinyin names * Omitting the Chinese character version of the name * Missing or incorrectly formatted date of birth (`YYYY-MM-DD`) * Providing an invalid or incomplete ID number (must be 18 digits) # Comments Source: https://docs.frankieone.com/docs/comments Learn how to add, retrieve, and manage comments on entity profiles for a complete audit trail. ## What are Comments? The Comments feature allows your operators and integrated systems to programmatically add notes and observations directly to an entity's profile (both Individuals and Organisations). This functionality is essential for maintaining a comprehensive and contextual audit trail. Every comment is timestamped and associated with the user or API key that created it, providing crucial context for compliance reviews, manual investigations, and decision-making processes. ## How It Works The process for adding a comment is straightforward and involves a single API call. Determine the `entityId` of the Individual or Organisation you wish to add a comment to. Make a `POST` request to the `/v2/comments` endpoint, providing the `entityId` and the text of your comment in the request body. FrankieOne saves the comment, linking it to the specified entity profile and recording the author and timestamp. The comment is now visible in the entity's activity history within the FrankieOne Portal and can be retrieved via the API. *** ## API Integration Guide ### Add a Comment to an Entity To add a comment, make a `POST` request to the `/v2/comments` endpoint. #### Request Body The request body must contain the ID of the entity and the content of the comment. | Field | Type | Required | Description | | ---------- | ------ | -------- | -------------------------------------------- | | `entityId` | String | Yes | The unique identifier for the entity. | | `comment` | String | Yes | The text content of the comment to be added. | **Example Request** ```json theme={null} { "entityId": "ind-0b6110e0-c167-4e69-92b0-9d3b7a5e9f7a", "comment": "Operator Jane Doe confirmed source of funds via phone call on Oct 15, 2025. Follow-up required in 30 days." } ``` #### Response Body A successful request will return a `201 Created` status code and the full comment object, including its unique `commentId` and server-generated metadata. **Example Response** ```json theme={null} { "commentId": "cmt-a1b2c3d4-e5f6-7890-1234-567890abcdef", "entityId": "ind-0b6110e0-c167-4e69-92b0-9d3b7a5e9f7a", "comment": "Operator Jane Doe confirmed source of funds via phone call on Oct 15, 2025. Follow-up required in 30 days.", "createdAt": "2025-10-15T07:10:00.000Z", "authorId": "user-a4b2c89-1234-5678-90ab-cdef12345678", "authorDisplayName": "Jane Doe" } ``` The `authorId` and `authorDisplayName` are automatically determined from the authentication context (API Key or user session) of the request. *** ## Common Use Cases Adding comments via the API is useful for a variety of scenarios: * **Documenting Manual Actions:** Record notes from offline actions, such as phone calls or in-person meetings. * **Explaining Overrides:** Provide justification when a compliance officer manually overrides a workflow decision or an automated check result. * **Integrating External System Data:** Push alerts or notes from third-party case management or fraud systems into the FrankieOne entity profile. * **Case Management:** Allow operators to add notes and updates as they investigate a case, creating a running log of their findings. # Managing Duplicate Entities Source: https://docs.frankieone.com/docs/duplicate-checks A detailed guide to detecting, reviewing, and resolving duplicate customer records using FrankieOne's automated workflow step. ## What are Duplicate Checks? Duplicate checks are essential for maintaining data integrity, reducing fraud risk, and ensuring compliance. They prevent the creation of multiple records for the same individual within your system. FrankieOne integrates this capability directly into your KYC workflow via a dedicated **`DUPLICATE`** step. This step provides: * **Automated identification** of possible duplicates using configurable, rules-based matching logic. * **Manual review and resolution** capabilities for operators to confirm or dismiss flagged duplicates. * **Seamless integration** with existing KYC processes to support both operational efficiency and regulatory compliance. To implement duplicate checks, you must have the `DUPLICATE` step added to your KYC workflow. **Speak with your FrankieOne representative to configure the duplicate step and its matching rules.** *** ## How Duplicate Checks Work The process is designed to flag potential duplicates during onboarding and provide your team with the tools to resolve them. When you execute a workflow for a new or updated entity, the `DUPLICATE` step runs. It compares the entity's attributes (e.g., name, DOB, document number) against all other entities in your system based on your configured matching rules. If a potential duplicate is found, the workflow step returns a `result` of `HIT`, and a `DUPLICATE` issue is created. This typically causes the overall workflow `status` to become `REVIEW`. For each potential duplicate found, a Process Result Object (PRO) is created. This PRO contains the granular details of the match, including which fields matched and the `entityId` of the potential duplicate. Your compliance team reviews the evidence within the PROs and makes a decision. They then resolve the match by calling the API to update the PRO's `manualStatus`. Based on the operator's resolution, the system updates the service profile states (e.g., marking one entity as `DUPLICATE`) and creates a permanent `relationship` between the two entities for future reference. *** ## Implementation and API Guide ### Step 1: Interpreting the Duplicate Check Result When the `DUPLICATE` step returns a `HIT`, you need to parse the `processResults` within that step to understand the match. Each PRO will have `class: "DUPLICATE"`. The most important information is in the **`supplementaryData`** object. ```json theme={null} { "processResultId": "01JNFWT5MKE75FMMZPWC7SDG2Z", "result": "HIT", "class": "DUPLICATE", "stepName": "DUPLICATE", "supplementaryData": { "type": "DUPLICATE", "duplicateEntityId": "98c545b6-7545-4337-85ce-30c64ef1ccff", "matchedFields": [ { "objectType": "NAME", "objectId": "840268d6-d37e-43ad-a421-d35345472df4", "duplicateObjectId": "4331b636-5cb2-46d6-bba1-03536232909b", "matchStrength": 86 }, { "objectType": "ADDRESS", "objectId": "9c5fdaeb-056a-47c7-a36e-dcb59ddce5b3", "duplicateObjectId": "c0d6872f-dd14-43f2-86b2-60e1e7ae24c4", "matchStrength": 100 } ], "matchedRules": [ { "name": "Given + Family name + Short form normalised address", "strength": "HIGH" } ] } } ``` **Key `supplementaryData` Fields:** * `duplicateEntityId`: The `entityId` of the existing profile that was matched. * `matchedFields`: An array detailing exactly which attributes matched between the two entities (e.g., `NAME`, `ADDRESS`). It includes the specific `objectId` for each attribute and the `matchStrength`. * `matchedRules`: Shows which configured rule was triggered to create this match. ### Step 2: Resolving Duplicates After reviewing the evidence, an operator must classify the match. This is done by sending a `PATCH` request with the `processResultId` and a `manualStatus`. **Endpoint:** ```http theme={null} PATCH /v2/individuals/{entityId}/results/duplicate ``` **Understanding the Manual Statuses** The `manualStatus` you send should reflect the operator's decision. | Operator's Decision | `manualStatus` to Send | Outcome | | :------------------------------------------------------------------------------------ | :--------------------- | :------------------------------------------------------------------------------------ | | "This is **not a duplicate**." | `FALSE_POSITIVE` | The potential match is dismissed. No relationship is created. | | "This is a duplicate. **Keep the new entity** and mark the old one as the duplicate." | `TRUE_POSITIVE_ACCEPT` | A relationship is created. The old entity's service profile is marked as `DUPLICATE`. | | "This is a duplicate. **Keep the old entity** and mark the new one as the duplicate." | `TRUE_POSITIVE_REJECT` | A relationship is created. The new entity's service profile is marked as `DUPLICATE`. | ```bash theme={null} curl -X PATCH \ '{{baseHost}}/v2/individuals/{{entityId}}/results/duplicate' \ -H 'api_key: YOUR_API_KEY' \ -H 'X-Frankie-CustomerID: YOUR_CUSTOMER_ID' \ -d '{ "processResults": [ "01JNFWT5MKE75FMMZPWC7SDG2Z" ], "manualStatus": "FALSE_POSITIVE", "comment": { "text": "Reviewed by operator. Confirmed different individuals with similar names." } }' ``` After resolving all duplicate-related `issues`, you should **re-run the workflow**. The `DUPLICATE` step will re-evaluate based on your resolutions, and the overall workflow `status` can then update from `REVIEW` to `PASS`. *** ## Key Concepts: State and Relationships * **Relationships**: When a duplicate is confirmed (`TRUE_POSITIVE_ACCEPT` or `TRUE_POSITIVE_REJECT`), a permanent `relationship` is created between the two entities. You can see this in the response of `GET /v2/individuals/{entityId}` under the `relationships.duplicates` array. * **`DUPLICATE` State**: An entity's service profile is moved to the `DUPLICATE` state when a relationship identifies it as such. An entity remains a duplicate as long as at least one relationship points to it. If all such relationships are removed (e.g., by being marked as `FALSE_POSITIVE` or if the source entity is deleted), its `DUPLICATE` state will be revoked. *** ## Configuration (Reference) The matching logic for the `DUPLICATE` step is highly configurable by the FrankieOne team. ```json theme={null} { "ruleSets": { "default": { "rules": [ { "name": "Document identifiers", "matchFields": [ "DOC_PRIMARY_IDENTIFIER", "DOC_TYPE", "DOC_COUNTRY" ], "method": "EXACT", "riskFactor": "VERY_HIGH" }, { "name": "Given + Family name + Date of birth", "matchFields": [ "GIVEN_NAME", "FAMILY_NAME", "DATE_OF_BIRTH" ], "method": "EXACT", "riskFactor": "VERY_HIGH" } ] } } } ``` ### Duplicate Check Logic FrankieOne's duplicate detection uses configurable rules to compare key attributes between entities. If any rule is matched, the entity is flagged as a potential duplicate. **Matching Rule Examples:** * **External Reference:** Exact match on `EXTERNAL_REFERENCE`. * **Document Identifiers:** Exact match on all of `DOC_PRIMARY_IDENTIFIER`, `DOC_SECONDARY_IDENTIFIER`, `DOC_COUNTRY`, `DOC_SUBDIVISION`, and `DOC_TYPE`. * **Phone Number:** Exact match on `PHONE_NUMBER`. * **Email Address:** Exact match on `EMAIL_ADDRESS`. * **Full Name:** Exact match on both `GIVEN_NAME` and `FAMILY_NAME`. * **Full Name + Date of Birth:** Exact match on `GIVEN_NAME`, `FAMILY_NAME`, and `DATE_OF_BIRTH`. * **Full Name + Normalised Address:** Exact match on `ADDR_NORM_SHORT`, `GIVEN_NAME`, and `FAMILY_NAME`. All rules use exact matching. You can customise which rules are active and their risk levels by working with FrankieOne. # A Detailed Guide to eKYC Rulesets Source: https://docs.frankieone.com/docs/ekyc-rulesets An in-depth guide to how FrankieOne’s KYC rulesets power your verification workflows and help you meet regional compliance requirements. ## What is a KYC Ruleset? > *A KYC Ruleset is the engine that drives a verification decision within a FrankieOne workflow.*
> *It’s a pre-configured set of logical conditions that defines exactly what is required for a customer’s identity to be considered verified.* When you execute a KYC workflow, the ruleset is applied to the customer’s data. The workflow checks this data against various independent sources (like credit bureaus or government databases), and the ruleset determines if the returned matches are sufficient to meet your specific compliance and business needs. FrankieOne provides standard, out-of-the-box rulesets designed to meet common regulatory requirements in different regions, such as **Australia’s 2+2 verification** or **Canada’s FINTRAC methods**. *** ## How Rulesets Work At its core, a ruleset is based on two simple principles: * **name** : The customer’s full name. * **dob** : The customer’s date of birth. * **address** : The customer’s residential address. * **gov\_id** : A government-issued document like a passport or driver’s licence. For each piece of information, the ruleset defines the **minimum number of successful matches** required from independent data sources.\ *Example: A rule might require that the customer’s name be successfully matched against at least**two** different sources.* By combining these conditions, rulesets can accommodate a wide range of verification scenarios — from simple identity checks to complex, multi-source regulatory requirements — ensuring workflows remain flexible and compliant. *** ## Standard Ruleset Library Below is a detailed breakdown of the common rulesets you’ll encounter when using FrankieOne’s standard workflows. *** ### 1. Australia: `two_plus` (Standard 2+2) > ***Purpose:** Meets AML/CTF compliance in Australia.* * **What it does:** Verifies an individual’s identity by matching their information against at least two independent data sources. As part of the upcoming changes to AML/CTF regulation, this ‘safe harbour’ model is being phased out in favour of a risk-based approach which will also be open to biometrics and digital IDs. These changes are expected for existing entities by **31st March 2026**. * **Logic:** Requires **2× Name Matches** **AND** a combined total of **2× Address/DOB Matches**. Australia’s AML/CTF regulations are evolving toward a risk-based approach and now recognize biometrics and digital IDs as valid verification methods. For details on upcoming changes—affecting existing entities from 31 March 2026 and new regulated entities from July 2026—refer to AUSTRAC’s official guidance. #### Passing Combinations | Combination | Name Matches | Address Matches | DOB Matches | | :---------- | :----------- | :-------------- | :---------- | | **1** | 2 | 2 | 0 | | **2** | 2 | 0 | 2 | | **3** | 2 | 1 | 1 | *** ### 2. Australia: `two_plus_gov_id` (2+2 with Gov ID) > ***Purpose:** Higher-assurance variant of 2+2, mandates successful verification of a Government ID.* * **What it does:** Increases confidence by tying the electronic verification to a physical document. * **Logic:** Requires **2× Name Matches** **AND** **1× Gov ID Match** **AND** a combined total of **2× Address/DOB Matches**. #### Passing Combinations | Combination | Name Matches | Address Matches | DOB Matches | Gov ID Matches | | :---------- | :----------- | :-------------- | :---------- | :------------- | | **1** | 2 | 2 | 0 | 1 | | **2** | 2 | 0 | 2 | 1 | | **3** | 2 | 1 | 1 | 1 | *** ### 3. International: `one_plus` (Standard 1+1) > ***Purpose:** Flexible ruleset for global use cases where a single-source verification is sufficient.* * **What it does:** Verifies an individual’s identity against at least one reliable data source. * **Logic:** Requires **1× Name Match** **AND** **1× Address or DOB Match**. #### Passing Combinations | Combination | Name Matches | Address Matches | DOB Matches | | :---------- | :----------- | :-------------- | :---------- | | **1** | 1 | 1 | 0 | | **2** | 1 | 0 | 1 | *** ### 4. Document-centric: `gov_id_only` > ***Purpose:** Relies solely on the verification of a government-issued document against an authoritative source.* * **What it does:** Confirms the authenticity of a provided ID document quickly. * **Logic:** Requires **1× Name Match** , **1× DOB Match** , **AND** **1× Gov ID Match** from the same document verification source. #### Passing Combinations | Combination | Name Matches | DOB Matches | Gov ID Matches | | :---------- | :----------- | :---------- | :------------- | | **1** | 1 | 1 | 1 | *** ### 5. Flexible Onboarding: `gov_id_with_alternative` > ***Purpose:** Prioritizes Government ID verification but provides the standard “2+2” check as a fallback.* * **What it does:** Optimizes conversion rates by providing two compliant pathways for verification in a single workflow. * **Logic:** Passes if **EITHER** of these conditions are met: * **Path A:** 1× Gov ID Match. * **OR** * **Path B:** 2× Name Matches **AND** 2× Address/DOB Matches. #### Passing Combinations | Part | Name Matches | Address Matches | DOB Matches | Gov ID Matches | | :---- | :----------- | :-------------- | :---------- | :------------- | | **A** | 1 | - | 1 | 1 | | **B** | 2 | 2 | 0 | - | | **B** | 2 | 0 | 2 | - | | **B** | 2 | 1 | 1 | - | *** ### 6. High Assurance: `safe_harbour_gov_id` > ***Purpose:** High-assurance ruleset for the strictest compliance needs, mandating multiple government ID verifications.* * **What it does:** Offers the highest level of assurance outside of a full biometric check by requiring two separate document verifications. * **Logic:** Requires **2× Name Matches** , **2× Gov ID Matches** , **AND** **2× Address/DOB Matches**. #### Passing Combinations | Combination | Name Matches | Address Matches | DOB Matches | Gov ID Matches | | :---------- | :----------- | :-------------- | :---------- | :------------- | | **1** | 2 | 2 | 0 | 2 | | **2** | 2 | 0 | 2 | 2 | | **3** | 2 | 1 | 1 | 2 | *** ### 7. International: `one_plus_gov_id` (1+1 with Gov ID) > ***Purpose:** “1+1” ruleset that mandates the inclusion of a Government ID verification.* * **What it does:** Combines the assurance of a document check with the breadth of an electronic data source check. * **Logic:** Requires **1× Name Match** , **1× Gov ID Match** , **AND** **1× Address or DOB Match**. #### Passing Combinations | Combination | Name Matches | Address Matches | DOB Matches | Gov ID Matches | | :---------- | :----------- | :-------------- | :---------- | :------------- | | **1** | 1 | 1 | 0 | 1 | | **2** | 1 | 0 | 1 | 1 | *** ### 8. Digital Services: `one_plus_dob_gov_id` > ***Purpose:** Requires Name, DOB, and a Government ID, with no address component.* * **What it does:** Focuses on verifying core identity (name, age) via a government document without the potential failure point of an address mismatch. * **Logic:** Requires **1× Name Match** , **1× DOB Match** , **AND** **1× Gov ID Match**. #### Passing Combinations | Combination | Name Matches | DOB Matches | Gov ID Matches | | :---------- | :----------- | :---------- | :------------- | | **1** | 1 | 1 | 1 | *** ### 9. Age-Restricted Services: `two_plus_age` > ***Purpose:** Specialized ruleset to verify an individual’s age with high confidence.* * **What it does:** Allows businesses to confidently verify a user is over a certain age. The “OR” logic provides flexibility to increase pass rates. * **Logic:** Passes if **EITHER** of these conditions are met: * **Path A:** 2× Name Matches **AND** 2× DOB Matches. * **OR** * **Path B:** 2× Name Matches **AND** 1× DOB Match **AND** 1× Address Match. **Best Practice for Age Verification:** Government-issued IDs are the most reliable data source for age verification as they provide an exact match against official records. When using consumer or commercial data sources, it is critical to review fuzziness settings to ensure they are set to require an exact match for the Date of Birth to avoid false negatives. #### Passing Combinations | Part | Name Matches | Address Matches | DOB Matches | | :---- | :----------- | :-------------- | :---------- | | **A** | 2 | 0 | 2 | | **B** | 2 | 1 | 1 | *** ### 10a. Address-centric: `two_plus_address` > ***Purpose:** Specialized ruleset to verify an individual’s address with high confidence.* * **What it does:** Helps meet Proof of Address (POA) requirements by ensuring an address match is always part of a successful verification. * **Logic:** Passes if **EITHER** of these conditions are met: * **Path A:** 2× Name Matches **AND** 1× DOB Match **AND** 1× Address Match. * **OR** * **Path B:** 2× Name Matches **AND** 2× Address Matches. #### Passing Combinations | Part | Name Matches | Address Matches | DOB Matches | | :---- | :----------- | :-------------- | :---------- | | **A** | 2 | 1 | 1 | | **B** | 2 | 2 | 0 | ### 10b. Address-centric: one\_plus\_address Purpose: International use case requiring name and address verification against a single data source, where address confirmation is mandatory. What it does: Verifies an individual's identity by matching their name and current address against at least one independent data source. Unlike the standard one\_plus ruleset — which accepts either an address or a date of birth as the secondary match — this variant specifically mandates a successful address match. A DOB match alone is not sufficient to pass. Logic: Requires 1× Name Match AND 1× Address Match. #### Passing Combinations | Part | Name Matches | Address Matches | DOB Matches | | :---- | :----------- | :-------------- | :---------- | | **A** | 1 | 1 | 1 | | **B** | 1 | 1 | 0 | *** ### 11. USA: `us_onboarding` > ***Purpose:** Standard ruleset for US-based onboarding that aligns with common Customer Identification Program (CIP) requirements.* * **What it does:** Provides a clear pathway to meeting baseline US federal requirements for customer identity verification under the Bank Secrecy Act (BSA). * **Logic:** Requires **1× Name Match** , **1× DOB Match** , **1× Address Match** , **AND** **1× Gov ID Match** (e.g., an SSN). #### Passing Combinations | Combination | Name Matches | DOB Matches | Address Matches | Gov ID Matches | | :---------- | :----------- | :---------- | :-------------- | :------------- | | **1** | 1 | 1 | 1 | 1 | *** ### 12. Canada: `ca_fintrac` > ***Purpose:** Multi-part ruleset designed to meet Canadian compliance requirements. Provides two distinct pathways for verification; a customer only needs to pass **one**.* * **What it does:** Verifies identity using one of the methods prescribed by the Financial Transactions and Reports Analysis Centre of Canada (FINTRAC). #### Method 1: The Credit File Method > *Most common method. Requires matching the customer’s full name, date of birth, and address against a Canadian credit file.* | Name Matches | DOB Matches | Address Matches | Source Requirement | | :----------- | :---------- | :-------------- | :------------------------------------------------------- | | 1 | 1 | 1 | All must come from a single Canadian Credit Bureau file. | #### Method 2: The Dual Process Method > *Alternative if the customer doesn’t have a credit file. Involves matching their information against two different, reliable sources.* | Name Matches | DOB Matches | Address Matches | Source Requirement | | :----------- | :---------- | :-------------- | :------------------------------------------------------- | | 2 | 2 | 2 | Must be from two different and independent data sources. | *** ## Next Steps Now that you understand the logic behind our rulesets, see our\ **[Electronic KYC with Government ID](/docs/electronic-kyc-checks)** guide for a step-by-step walkthrough of how to execute a workflow that uses one of these rulesets. # Electronic KYC with Government ID Source: https://docs.frankieone.com/docs/electronic-kyc-checks A step-by-step guide to verifying a customer's identity electronically using their personal information and a government-issued ID. ## What is an Electronic KYC (eKYC) Check? An electronic Know Your Customer (eKYC) check is the standard process for verifying a customer's identity against digital data sources. This guide focuses on a common and robust method: verifying a customer's personal information (name, DOB, address) along with a government-issued identity document. This process is fundamental to meeting your compliance obligations under regulations like Australia's Anti-Money Laundering and Counter-Terrorism Financing (AML/CTF) Act, which requires matching customer data against reliable and independent sources. ## How It Works The process involves two main API interactions: First, you create a complete digital profile of your customer by sending their personal details and government ID information to the FrankieOne API. This creates a unique `entityId` for the customer. Next, you trigger a pre-configured workflow using the `entityId`. This workflow takes the entity's data and securely checks it against trusted third-party sources, such as the Australian Government's Document Verification Service (DVS) and credit bureaus, to find matches. *** ## Implementation Guide This guide will walk you through the API calls required to perform a standard eKYC verification. ### Step 1: Create an Individual with a Government ID To begin, create an entity by calling the `POST /v2/individuals` endpoint. The request below shows how to create an individual with a name, date of birth, address, an Australian Passport, and the necessary consents. ```curl cURL theme={null} curl --location '[https://api.frankie.one/v2/individuals](https://api.frankie.one/v2/individuals)' \ --header 'api_key: {{your_api_key}}' \ --header 'X-Frankie-CustomerID: {{your_customer_id}}' \ --header 'Content-Type: application/json' \ --data '{ "individual": { "name": { "givenName": "MARY", "familyName": "TESTFOURTEEN" }, "dateOfBirth": { "year": "1963", "month": "01", "day": "01" }, "addresses": [ { "type": "RESIDENTIAL", "streetName": "NINGALOO", "streetNumber": "12", "streetType": "STREET", "locality": "EXMOUTH", "subdivision": "WA", "country": "AUS", "postalCode": "6707" } ], "documents": { "IDENTITY": [ { "type": "PASSPORT", "primaryIdentifier": "P52184975", "country": "AUS" } ] }, "consents": [ { "type": "GENERAL" }, { "type": "DOCS" } ] } }' ``` A successful `201 Created` response will contain the full entity profile, including the unique `entityId`. **You must store this `entityId`** as it is required for all subsequent API calls for this individual. ### Step 2: Execute the KYC Workflow Now, use the `entityId` from the previous step to execute your verification workflow. The `workflowName` in this example is `AUS-Basic1V-IDOnly`. ```curl HTTP theme={null} curl --location --request POST '[https://api.frankie.one/v2/individuals/](https://api.frankie.one/v2/individuals/){{entityId}}/serviceprofiles/DEFAULT/workflows/AUS-Basic1V-IDOnly/execute' \ --header 'api_key: {{your_api_key}}' \ --header 'X-Frankie-CustomerID: {{your_customer_id}}' ``` A successful execution returns a `workflowResult` object containing the complete outcome of the verification. ### Interpreting the KYC Result The `workflowResult` object contains rich information about the verification. #### The High-Level Verdict For automated decision-making, start with these top-level fields: * **`status`**: This is the definitive recommendation. The most common values are `PASS`, `FAIL`, or `REVIEW`. * **`workflowExecutionState`**: This must be `COMPLETED`. If it's anything else (e.g., `ERROR`, `TIMEOUT`), the workflow did not finish, and the `status` should not be trusted as final. #### The KYC Step Details To understand *why* the workflow passed or failed, find the `KYC` object within the `workflowStepResults` array. * **`result`**: The outcome of the KYC step itself, typically `MATCH` or `NO_MATCH`. * **`summary`**: A summary object explaining how the result was reached. The `matchedRules` array shows which data sources were successfully matched (`matchDetails`) and if the overall verification criteria were met (`isVerified: true`). ```json theme={null} "workflowStepResults": [ { "stepName": "KYC", "result": "MATCH", "summary": { "matchedRules": [ { "ruleName": "gov_id_only", "isVerified": true, "matchDetails": [ { "provider": "con_testbed-docs", "source": "au-govid1-pp", "attributesMatched": [ "dateOfBirth", "govId", "name" ] } ] } ] } } ] ``` *** ## Best Practices for Integration * **Trust the `status` field** as the final, authoritative outcome for your business logic. * **Always check `workflowExecutionState`** to ensure the workflow `COMPLETED` successfully before actioning the result. * **Log the `workflowExecutionId`** with every result. This is the key identifier for support, auditing, and debugging. * **Build logic to handle the `REVIEW` status**. When you receive a `REVIEW`, your system should flag the case for manual investigation by a compliance officer. The `issues` array in the workflow result will tell them where to look. ## Next Steps This guide provides a high-level overview of the eKYC result. For a complete reference of every field in the response, see the **[Interpreting Workflow Results](/docs/interpreting-workflows-v2)** guide. # Error Handling Source: https://docs.frankieone.com/docs/error-handling The FrankieOne API uses a standardized error format to ensure that you can reliably handle issues that arise from bad requests, server problems, or invalid data. All non-2xx responses will return a consistent JSON error object. This guide explains the structure of the error object, provides a full list of error codes, and offers practical advice on how to handle these errors in your frontend application. *** ## The Error Object All errors returned from the FrankieOne API are wrapped in a standard `ErrorObject`. | Attribute | Type | Description | | :-------------------- | :------ | :------------------------------------------------------------------------------------------------------------------- | | errorCode | string | A unique code in the format `PREFIX-NUMBER` that identifies the error. | | errorMsg | string | A human-readable message summarizing the error. | | httpStatusCode | integer | The standard HTTP status code for the response (e.g., 400, 404, 500). | | details | array | An array of issue objects providing specific context about what went wrong. | | details.issue | string | A detailed description of the specific issue. | | details.issueLocation | string | The location in the request payload, path, or header where the issue occurred (e.g., `body.individual.dateOfBirth`). | | requestId | string | The unique ID for the API request, which should be logged and provided to support if you need assistance. | *** ### Example Error Object Here is an example of an error returned due to an invalid date of birth format in the request body. ```json theme={null} { "errorCode": "VAL-1002", "errorMsg": "Data supplied is incorrect/badly formatted", "httpStatusCode": 400, "details": [ { "issue": "Invalid format. Must be YYYY-MM-DD", "issueLocation": "dateOfBirth" } ], "requestId": "01HN9XHZN6MGXM9JXG50K59Q85" } ``` *** ## Understanding Error Codes The `errorCode` is a combination of a prefix (the Issue Location) and a number. This structure helps you quickly identify the source of the problem. ### Issue Location Codes (Prefix) | Prefix | Description | | :----- | :------------------------------------------------------------------------------------------------------------------------- | | API | Errors in your API message, such as an incorrectly constructed URL or method. | | AUTH | Authorization or security-related errors, like a missing or invalid API key. | | VAL | API data validation errors. The details array will specify which fields are invalid. | | ENT | Errors related directly to Entity functions (e.g., an entity not found). | | DOC | Errors related directly to Document functions. | | CHECK | Errors related to Check/Verify functions. Indicates a problem with performing a check, not the result of the check itself. | | SYS | System-level errors on the FrankieOne side. These may be temporary. | | CODE | Unexpected errors detected in the code. Please contact support if you see these. | | ADMIN | Admin API errors. Please contact developer support if you receive one. | *** ## Frontend Orchestration & Handling Errors A robust frontend application should interpret the HTTP status code and the errorCode to present the user with a clear and helpful message. ### 400 - Bad Request (VAL-xxxx) This is the most common error category. It means the user has provided invalid or incomplete data. Your frontend should parse the `details` array to provide specific feedback. #### Scenario: A user submits a form with an invalid date of birth and a missing family name. **Example Response:** ```json theme={null} { "errorCode": "VAL-1001", "errorMsg": "Missing required field", "httpStatusCode": 400, "details": [ { "issue": "The 'familyName' field is required but was not provided", "issueLocation": "body.individual.name.familyName" }, { "issue": "The dateOfBirth is invalid, provide a valid date", "issueLocation": "dateOfBirth" } ], "requestId": "01HMR2ERSKCYAVXKS1FKSRT2T4" } ``` **Frontend Action:** * Iterate through the `details` array. * For each issue, use the `issueLocation` to find the corresponding input field in your form. * Display the issue message directly below that field. This provides targeted, inline validation feedback to the user so they can easily correct their mistakes. *** ### 404 - Not Found (API-1010) This means the resource you requested (like an entityId or workflowExecutionId) does not exist. #### Scenario: Your application tries to fetch results for a workflow that has been deleted or whose ID is incorrect. **Example Response:** ```json theme={null} { "errorCode": "API-1010", "errorMsg": "Requested resource is not found", "httpStatusCode": 404, "details": [ { "issue": "The specified resource '01BFJA617JMJXEW6G7TDDXNSHX' of type 'entity' does not exist", "issueLocation": "path" } ], "requestId": "01BFJA617JMJXEW6G7TDDXNSHX" } ``` **Frontend Action:** * Check for the 404 status code. * Redirect the user to a "Not Found" page or display a clear message like "We could not find the record you were looking for. Please check the ID or start a new search." * Avoid showing a generic "An error occurred" message, as this is a specific and actionable state. *** ### 5xx - Server & System Errors (SYS-xxxx) These errors indicate a problem on FrankieOne's side. The issue may be temporary. #### Scenario: A service provider required for a check is temporarily unavailable. **Example Response:** ```json theme={null} { "errorCode": "SYS-0007", "errorMsg": "No service providers available/configured. Contact developer support", "httpStatusCode": 503, "details": [ { "issue": "The service is temporarily unavailable", "issueLocation": "server" } ], "requestId": "01GVEDZ0C1Q9NWQ699DBBKPE4Y" } ``` **Frontend Action:** * Check for any 5xx status code (500, 503, etc.). * Display a generic, user-friendly message, such as: "We're sorry, something went wrong on our end. Please try again in a few moments." * Do not display the technical `errorMsg` to the user. * You may implement a retry mechanism with exponential backoff for 503 errors, as these are often transient. * Log the full error response, including the `requestId`, so you can report it to support if the issue persists. *** ## Full List of Error Codes Returned by internal processes. Generally indicate a temporary issue, but please contact developer support if the issue persists. | Error Number | HTTP Error Code | Description | | :----------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------ | | 0000 | 500 | Unknown internal error. Contact developer support | | 0001 | 500 | Internal error. Contact developer support. | | 0002 | 401 | Not authorised to perform this function | | 0003 | 500 | Internal error. Contact developer support. | | 0004 | 500 | Internal error. Contact developer support. | | 0005 | 500 | Internal error. Contact developer support. | | 0006 | 500 | Internal error. Contact developer support. | | 0007 | 503 | No service providers available/configured. Contact developer support | | 0008 | 503 | No document scanning service available/configured. Contact developer support | | 0009 | 503 | No document verification service available/configured. Contact developer support | | 0010 | 503 | No comparison service available/configured. Contact developer support | | 0011 | 503 | No industry service available/configured. Contact developer support | | 0012 | 501 | Requested service (comparison) isn't supported for your current configuration. Contact developer support. | | 0013 | 501 | Requested service (scan) isn't supported for your current configuration. Contact developer support. | | 0014 | 501 | Requested service (document verify) isn't supported for your current configuration. Contact developer support. | | 0015 | 501 | Requested service (industry function) isn't supported for your current configuration. Contact developer support. | | 0016 | 501 | Requested service (entity verify) isn't supported for your current configuration. Contact developer support. | | 0017 | 501 | Requested service (specific entity check type) isn't supported for your current configuration. Contact developer support. | | 0018 | 503 | No entity verification service available/configured. Contact developer support | | 0019 | 503 | Internal error. Contact developer support. | | 0020 | 500 | Internal error. Contact developer support. | | 0021 | 500 | Internal error. Contact developer support. | | 0022 | 500 | Internal error. Contact developer support. | | 0023 | 500 | Internal error. Contact developer support. | | 0024 | 500 | Internal error. Contact developer support. | | 0025 | 500 | Internal error. Contact developer support. | | 0026 | 500 | Internal error. Contact developer support. | | 0027 | 500 | Internal error. Contact developer support. | | 0028 | 500 | Internal error. Contact developer support. | | 0029 | 500 | Internal error. Contact developer support. | | 0030 | 500 | Internal error. Contact developer support. | | 0031 | 500 | Internal error. Contact developer support. | | 0032 | 500 | Cache retrieve error. Contact developer support. | | 0033 | 500 | Internal error. Contact developer support. | | 0034 | 500 | Internal error. Contact developer support. | | 0035 | 503 | Push to mobile service not available | Returned when no distinct error code is available (usually internal framework generated). | Error Number | HTTP Error Code | Description | | :----------- | :-------------- | :------------------------------------------------ | | 400 | 400 | Generic 400 Error - See error message for details | | 401 | 401 | Generic 401 Error - See error message for details | | 404 | 404 | Generic 404 Error - See error message for details | | 405 | 405 | Generic 405 Error - See error message for details | | 415 | 415 | Generic 415 Error - See error message for details | | 422 | 422 | Generic 422 Error - See error message for details | | 429 | 429 | Generic 429 Error - See error message for details | | 500 | 500 | Generic 500 Error - See error message for details | | 501 | 501 | Generic 501 Error - See error message for details | | 503 | 503 | Generic 503 Error - See error message for details | The API returns these errors when it receives unsupported or missing header data. | Error Number | HTTP Error Code | Description | | :----------- | :-------------- | :-------------------------- | | 801 | 400 | Missing header: RequestID | | 802 | 400 | Missing header: CheckID | | 901 | 400 | Malformed header: RequestID | | 902 | 400 | Malformed header: CheckID | The API returns these errors when it encounters issues with specific requests. | Error Number | HTTP Error Code | Description | | :----------- | :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | | 1001 | 400 | Blank value supplied when one needed | | 1002 | 400 | Data supplied is incorrect/badly formatted. | | 1003 | 405 | Can't merge different documents or entities | | 1004 | 400 | Can't set document ID | | 1005 | 400 | Data conversion issue | | 1006 | 422 | Document supplied is unparsable | | 1007 | 400 | Can't set entity ID | | 1008 | 400 | Entity supplied is unparsable | | 1009 | 404 | Requested document isn't found | | 1010 | 404 | Requested entity isn't found | | 1011 | 422 | Not enough data supplied to perform requested check | | 1012 | 500 | Can't mark record as deleted | | 1013 | 400 | Utility bill not supplied | | 1014 | 400 | Document not a PDF when PDF expected | | 1015 | 400 | Scan data not supplied when scan expected | | 1016 | 501 | Error response returned from utility processor | | 1017 | 202 | Verification results incomplete - expect a notification push | | 1018 | 415 | Media type not supported | | 1019 | 400 | End date before start date | | 1020 | 400 | Bad page number | | 1021 | 400 | Bad page count request | | 1022 | 404 | Requested check ID not found | | 1023 | 404 | Can't retrieve original document | | 1024 | 404 | Cache returned a nil result | | 1025 | 400 | Geocode empty | | 1026 | 400 | Multiple geocode results or inexact address match | | 1027 | 400 | Bad geocode result - Address not found | | 1028 | 400 | Invalid country or country code | | 1029 | 401 | Attempt to access unauthorised data | | 1030 | 400 | Entity state precludes requested flag setting | | 1041 | 400 | Identity document required | | 1042 | 400 | Incorrect ID type | | 1043 | 400 | Missing mobile number | | 1044 | 400 | Missing name | | 1045 | 400 | Empty name | | 1046 | 400 | Entity ineligible for service or in unsupported jurisdiction | | 1047 | 400 | Push to Mobile service returned PTM service offline | | 1048 | 404 | PTM service couldn't find the token requested | | 1049 | 404 | Internal error. Contact developer support. | | 1050 | 503 | No business query service available at this time. | | 1051 | 503 | Failed to schedule background job | | 1052 | 500 | Business processor returned empty result set | | 1053 | 400 | Supplied entity isn't of a suitable type | | 1054 | 400 | The requested operation amounted to no work | | 1055 | 400 | A required prior result has expired | | 1056 | 500 | The background operation couldn't continue because required data was modified | | 1057 | 500 | The background operation couldn't continue because required data was missing | | 1058 | 500 | No result was obtained in a reasonable time | | 1059 | 500 | Inconsistent result from business processor | | 1060 | 400 | Mismatch between ownership request and ABR response | | 1061 | 400 | Can't change status of check result | | 1062 | 403 | Operation not permitted, entity is in inactive state | | 1063 | 500 | Report service exists but failed to generate a report or we couldn't save the result | | 1064 | 400 | Document not owned by entity requested in document/verify function | | 1065 | 400 | Named entity profile not configured | | 1066 | 400 | Entity doesn't have an assigned profile | | 1067 | 400 | Entity profiles aren't enabled for customer | | 1068 | 400 | Missing application id or referrer when requesting an IDV token | | 1069 | 400 | Invalid request to token service for a token | | 1070 | 422 | Invalid request (unprocessable) to token service for a token | | 1072 | 400 | Refresh token with mismatch applicant id | | 1073 | 500 | The expected or default policy isn't configured | | 1074 | 500 | Attempt to toggle entity monitoring failed | | 1075 | 422 | Importing past results failed | | 1076 | 400 | Unknown business reportType | | 1077 | 503 | No intl business service available | | 1078 | 400 | No intl business search/profile criteria provided | | 1079 | 400 | Intl business service rejected request | | 1080 | 400 | No shared blocklist | | 1081 | 400 | No shared blocklist reason | | 1082 | 500 | Shared blocklist internal error | | 1083 | 500 | Failed to get JWT signer or JWK key set | | 1084 | 400 | Entity not in valid state for setting a manual state | | 1085 | 404 | Requested entity isn't retrievable at this time. NOTE: This is USUALLY transient, so wait 5 seconds and then retry | | 1086 | 404 | Requested association doesn't exist | | 1087 | 400 | Requested association isn't allowed | | 1088 | 400 | Object not found from non-primary key search | | 1089 | 500 | Internal error. Contact developer support. | | 1090 | 400 | Device data supplied is either missing or incorrectly formatted | | 1091 | 500 | Internal service error - please contact technical support | | 1092 | 404 | Organisation can't be found in the requested country's registry | | 1093 | 400 | The request contains an invalid parameter or argument | | 1094 | 400 | Search criteria too broad and returned too many results. Please retry with narrower search criteria | | 1095 | 400 | Incorrectly formatted organisation number | | 1096 | 400 | The requested country registry is incorrect. Please ensure you have the right country registry code | | 1097 | 503 | Unknown response from the registry | | 1098 | 400 | No company registry for the requested country is available to query. This is often due to local regulations not making this data available | | 1099 | 400 | Search by organisation\_number not available for the jurisdiction | # Executing a workflow Source: https://docs.frankieone.com/docs/executing-workflows A step-by-step guide to executing a verification workflow and interpreting the results. ## Overview Executing a workflow is the core action in the FrankieOne platform. It takes an `entityId` and runs it through a pre-configured series of checks (e.g., KYC, AML, IDV) to return a final verification status. This is the central mechanism for assessing risk and making onboarding decisions. This guide covers the primary methods for executing a workflow and provides a high-level overview of how to handle the response. *** ## Workflow Execution Patterns There are two primary patterns for executing a workflow, depending on whether the individual already exists in your system. ### 1. Execute for an Existing Entity This is the most common pattern. If you have already created an `individual` and have their `entityId`, you can execute a workflow against them at any time. **Use Cases:** * Running an initial KYC check after a user has signed up. * Re-running a workflow after a user has updated their information. * Performing periodic or event-driven reviews. You send a `POST` request to the `/execute` endpoint for a specific entity and workflow. This tells FrankieOne to begin the verification process. Our platform contacts all the necessary third-party data sources (e.g., government databases, credit bureaus, watchlist providers) as defined in your workflow rules. The API response to your initial `POST` request contains the complete `workflowResult` object, which holds the final `status` and all detailed outcomes. ### 2. Create and Execute for a New Entity For new user onboarding, you can create the `individual` entity and execute a workflow in a single API call. This is a highly efficient pattern that streamlines the initial verification process. **Use Cases:** * Onboarding a new customer who has just filled out a registration form. * Verifying a user for the first time as part of a single, atomic transaction. *** ## Implementation Guide ### Prerequisites Before executing a workflow, ensure you have: * The `entityId` for the individual (unless using the “Create and Execute” pattern). * The `serviceName` of the Service Profile they are being assessed against (e.g., `DEFAULT`). * The `workflowName` of the specific workflow you want to run (e.g., `Standard-KYC-AU`). ### Step 1: Execute the Workflow Choose the endpoint that matches your execution pattern. #### For an Existing Entity: Make a `POST` request to the `execute` endpoint, including the `entityId`, `serviceName`, and `workflowName` in the path. ```cURL cURL theme={null} curl --location --request POST '[https://api.frankie.one/v2/individuals/](https://api.frankie.one/v2/individuals/){{entityId}}/serviceprofiles/{{serviceName}}/workflows/{{workflowName}}/execute' --header 'api_key: {{your_api_key}}' --header 'X-Frankie-CustomerID: {{your_customer_id}}' ``` #### For a New Entity: Make a `POST` request to the `new` execute endpoint, providing the `individual`’s data in the request body. ```cURL cURL theme={null} curl --location --request POST '[https://api.frankie.one/v2/individuals/new/serviceprofiles/](https://api.frankie.one/v2/individuals/new/serviceprofiles/){{serviceName}}/workflows/{{workflowName}}/execute' --header 'api_key: {{your_api_key}}' --header 'X-Frankie-CustomerID: {{your_customer_id}}' --data '{ "individual": { "name": { "givenName": "John", "familyName": "Doe" }, "dateOfBirth": { "year": "1990", "month": "01", "day": "25" }, "..." : "..." } }' ``` ### Advanced: Passing Execution Variables Some workflows accept runtime inputs that are not part of the individual entity's persistent data. You supply these through the `executionVariables` field in the request body. It is a key-value object, and the variables a workflow accepts are defined by that workflow's configuration. Today no individual (KYC) workflow uses `executionVariables`. The only workflow that uses it is the KYB [Trust Analyzer](/docs/kyb/trust-analyzer), which takes the `documentId` of an uploaded trust deed. ### Step 2: Interpret the High-Level Response The API response will contain the `workflowResult` object. For automated decision-making, you should parse these key top-level fields: * **`workflowExecutionState`** : This **`must beCOMPLETED`**. If it shows `ERROR` or `TIMEOUT`, the workflow did not finish, and the `status` should not be trusted. * **`status`** : This is the **most important field**. The most common values are `PASS`, `FAIL`, or `REVIEW`. This field incorporates any manual overrides and represents the final, authoritative state. * **`result`** : This represents the original, automated outcome of the workflow before any manual changes. It’s useful for auditing. ### Advanced: Asynchronous Execution For workflows that may take longer to complete, you can request asynchronous execution by including the `X-Frankie-Background: 1` header. * The API will immediately respond with a `202 Accepted` status and a `requestId`. * The workflow will continue to process in the background. * You will be notified of the final result via a configured webhook. This pattern is useful for preventing timeouts in client-facing applications. ### Advanced: Overriding a Result In some cases, a compliance officer may need to manually override a workflow’s automated result. This is achieved by making a `PATCH` request to the specific workflow execution. ```HTTP HTTP theme={null} PATCH /v2/individuals/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/executions/{workflowExecutionId} ``` Provide the new `status` and an optional `comment` to explain the reason for the change. This action is fully audited. ```JSON JSON Request theme={null} { "status": "PASS", "comment": { "text": "Manually approved by compliance officer John Doe after reviewing supporting documents." } } ``` *** ## Next Steps Once you have successfully executed a workflow, the next critical step is to parse the rich `workflowResult` object to understand the outcome of every check. For a complete breakdown of every field in the response, refer to our detailed guide: [**Interpreting Workflow Results**](/docs/interpreting-workflows-v2). *** ## Additional Resources * [FrankieOne API Reference](/docs/reference/whats-new) * [FrankieOne Support](/docs/contacting-developer-support) # Introduction to FrankieOne & KYC Source: https://docs.frankieone.com/docs/frankieone-introduction-to-kyc Discover the fundamentals of Know Your Customer (KYC) and see how FrankieOne’s unified platform empowers you to build trust, ensure compliance, and create seamless onboarding experiences. ## The Cornerstone of Digital Trust In today's global and digital economy, establishing trust is paramount. Know Your Customer (KYC) is the foundational process that enables businesses to verify the identity of their customers, creating a secure environment for everyone. It’s not just a regulatory hurdle; it’s a critical framework for preventing financial crime and building lasting, trusted relationships. Know Your Customer (KYC) is the mandatory process of identifying and verifying the identity of a client. It's a cornerstone of regulatory compliance for any business involved in financial services, gaming, and other regulated sectors. The core principle of KYC is to establish with confidence that a customer is who they claim to be, which is the first and most critical step in preventing identity theft, financial fraud, money laundering, and the financing of terrorism (ML/TF). A robust KYC strategy is a competitive advantage that protects your business, your customers, and your reputation. Its importance extends far beyond simple compliance. * **Prevent Financial Crime and Protect Your Reputation:** KYC processes are your first line of defense against illicit activities. By thoroughly verifying customer identities, you can detect and deter criminals, safeguarding your business from being exploited for money laundering or terrorist financing. * **Navigate Global Regulatory Complexity with Confidence:** Governments and financial authorities worldwide, guided by bodies like the Financial Action Task Force (FATF), mandate strict KYC and Anti-Money Laundering (AML) regulations. Non-compliance leads to severe fines, sanctions, and reputational ruin. * **Enable Intelligent Risk Management:** KYC allows you to build a comprehensive risk profile for each customer. Understanding who your customers are and their expected behaviour enables you to make informed decisions, tailor your security measures, and manage risk effectively. * **Build and Maintain Customer Trust:** Demonstrating a strong commitment to security and compliance shows customers that you are a professional and trustworthy organization. This builds confidence, enhances your brand reputation, and fosters long-term loyalty. The KYC process is a continuous journey, not a one-time check. It can be broken down into four essential stages that create a comprehensive compliance framework. The initial stage where you collect key identifying information from a customer. For individuals, this includes name, date of birth, and address. For businesses, it involves gathering corporate registration details and identifying the ultimate beneficial owners (UBOs). This is the verification stage. After collecting information, you perform due diligence to validate it against trusted, independent data sources. The goal is to confirm the customer's identity and assess their initial risk profile. For high-risk customers, standard due diligence is not enough. EDD involves a deeper investigation into their background, source of wealth, and business relationships to mitigate elevated risks. KYC is not a one-and-done process. Continuous monitoring of customer activity and periodic reviews ensure that any changes in risk profile are detected and managed promptly. ## How FrankieOne Delivers a Unified Solution FrankieOne replaces complexity with a single, intelligent platform. We provide the infrastructure to connect to hundreds of global data sources and compliance tools through one API and one unified back-office portal. * **Effortless Global Onboarding:** Integrate once and gain access to a world of identity verification providers. Our flexible integration options—including our low-code Onboarding Journeys, SDKs, and a powerful API—allow you to onboard customers from anywhere, efficiently and securely. * **Automated and Risk-Based Workflows:** Automate data collection and verification to eliminate manual errors, reduce operational overhead, and accelerate onboarding. Configure dynamic, risk-based workflows that automatically escalate high-risk customers for enhanced due diligence while fast-tracking legitimate users. * **Always-On Compliance:** The regulatory landscape is constantly changing. FrankieOne is a fully managed solution that stays current with the latest regulatory requirements and industry best practices, significantly reducing your compliance burden and risk. ## Our Unified Product Suite FrankieOne offers a comprehensive suite of products designed to work together, providing complete coverage across the entire KYC and fraud prevention lifecycle. Our core engine for verifying individual and business identities against hundreds of trusted global data sources. Screen customers against global PEP, Sanctions, and Adverse Media watchlists, with options for continuous monitoring. Instantly capture and verify government-issued ID documents using advanced OCR and authenticity analysis. Prevent spoofing and fraud with leading biometric technology that confirms a customer is genuinely present and matches their ID document. Assess risk during onboarding using real-time signals from device, IP, email, and phone data. Dynamically calculate a holistic risk score for each customer based on configurable risk factors and real-time data. Create and manage internal blocklists to proactively prevent engagement with known high-risk individuals or entities. Maintain a single customer view and prevent fraud by identifying and flagging linked or duplicate accounts. ### The Future of Compliance: Coming Soon We are continuously innovating to address the next generation of compliance and fraud challenges. The following capabilities are in active development for upcoming releases. Deploy beautiful, low-code, and fully-hosted onboarding flows in minutes, customized to your brand and risk policies. Monitor customer transactions in real-time to detect suspicious patterns and automate regulatory reporting. Leverage generative AI to automate the investigation of AML alerts, providing plain-language summaries and recommendations. Verify digital identities using secure and reliable methods to enhance customer trust and security. ##### Ready to Get Started? FrankieOne's team of compliance and integration experts are ready to help you design and deploy a world-class KYC and onboarding solution. or dive into our to learn more. FrankieOne's team of compliance and integration experts are ready to help you design and deploy a world-class KYC and onboarding solution. ## Understanding Your Regulatory Obligations As a business providing regulated services, you are likely considered a **“Reporting Entity”** (or “Obligated Entity”) under AML/CTF legislation. This requires you to establish and implement a robust AML/CTF Program, where Customer Identification Procedures (KYC) are a core component. The goal is to be satisfied that: * An **individual customer** is who they claim to be. * A **non-individual customer** (e.g., a company, trust, or partnership) is a real entity, and you have identified its beneficial owners. ##### Consult with Legal and Compliance Experts AML/CTF regulations are complex and vary by jurisdiction and industry. The information provided here is for educational purposes only. Always consult with a qualified legal expert or compliance officer to ensure your AML/CTF Program meets all necessary legal requirements for the regions in which you operate. #### Key Regulatory Bodies and Guidance | Jurisdiction | Regulatory Body | Key Reference / Legislation | | :----------------- | :--------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Australia** | Australian Transaction Reports and Analysis Centre (AUSTRAC) | [Customer identification and verification ](https://www.austrac.gov.au/business/core-guidance/customer-identification-and-verification) | | **Canada** | Financial Transactions and Reports Analysis Centre of Canada (FINTRAC) | [Guide to Client Identification Requirements ](https://fintrac-canafe.canada.ca/guidance-directives/client-clientele/Guide11/11-eng#annex5) | | **European Union** | European Banking Authority (EBA) | [Anti-Money Laundering Directives (AMLD) ](https://www.eba.europa.eu/regulation-and-policy/anti-money-laundering-and-countering-financing-terrorism) | | **Global** | Financial Action Task Force (FATF) | [FATF Recommendations](https://www.fatf-gafi.org/en/topics/fatf-recommendations.html) | | **New Zealand** | Financial Markets Authority (FMA) | [AML/CTF Guidance ](https://www.fma.govt.nz/business/focus-areas/amlcft/) | | **United Kingdom** | Financial Conduct Authority (FCA) | [Financial crime: a guide for firms ](https://www.fca.org.uk/firms/financial-crime) | | **United States** | Financial Crimes Enforcement Network (FinCEN) | [Customer Due Diligence Final Rule ](https://www.fincen.gov/resources/statutes-regulations/federal-register-notices/customer-due-diligence-requirements) | # Onboarding Fraud Checks Source: https://docs.frankieone.com/docs/fraud-checks-guide Learn how to implement Onboarding Fraud Checks to assess risk using device, IP, email, and phone signals. ## Introduction FrankieOne's Onboarding Fraud solution enables you to build a risk-based onboarding workflow by incorporating powerful fraud signals. By analyzing signals from an applicant's device, IP address, phone number, and email address, you can optimize your onboarding process—introducing more robust checks for high-risk applicants while ensuring a smooth journey for legitimate users. This allows you to effectively reject bad actors showing strong fraudulent indicators while safely onboarding genuine customers. ## Key Capabilities Analyze device characteristics to identify suspicious setups like emulators or jailbroken devices. Assess the risk associated with an IP address, detecting usage of VPNs or proxies. Verify email addresses to uncover potential fraud indicators. Validate phone numbers and identify associated risk signals. ## The End-to-End Fraud Check Flow The fraud verification process involves a sequence of API calls to create an entity, register a device session (if applicable), and execute a workflow to get a result. Before you can perform a fraud check, you need an `entityId` for the user. If you don't already have one, create an individual entity by making a server-side call to the API. Ensure you provide email and phone details if you intend to check those signals. ```bash theme={null} POST /v2/individuals ``` This request creates the user's profile in the FrankieOne system and returns the essential `entityId` that will be used in all subsequent steps. To obtain device and IP signals, your application must integrate our oneSDK (either hosted or embedded). The oneSDK captures device data and establishes a session. This session must be registered with FrankieOne. Make a server-side call to register the session against the entity. This step is only necessary if you require device and IP checks. ```bash theme={null} POST /v2/individuals/{entityId}/sessions ``` This ensures that when the fraud check workflow is executed, FrankieOne can retrieve and analyze the data captured during that specific user session. Once the entity is created (and a session is registered, if needed), you can execute the onboarding workflow. The workflow must be configured to include the `FRAUD` step to perform the checks. ```bash theme={null} POST /v2/individuals/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/execute ``` This triggers the Fraud step, which analyzes the available signals (Email, Phone, Device, IP) and generates the results. The workflow execution response will contain the results of the fraud checks. The overall step result will indicate a `HIT` or `CLEAR` based on the process results for each signal. You can then investigate any hits and resolve them. To learn how to analyze the detailed outcomes, please see our dedicated guide:\ Understanding Fraud Check Results ## Limitations Please be aware of the following limitations: * **oneSDK Requirement:** To get device and IP signals, you must implement oneSDK. Without it, only email and phone signals can be used. * **Single Provider per Step:** The fraud step is designed to support only one provider at a time. If you need to use different providers for different signals, you must configure separate fraud steps. * **Supported Connectors:** To find out which connectors are available for the v2 fraud step, please consult your implementation support manager. # Understanding Fraud Check Results Source: https://docs.frankieone.com/docs/fraud-checks-guide-results Learn how to locate and interpret the results from Onboarding Fraud Checks. ## Locating Fraud Check Results Once a workflow containing a `FRAUD` step has been executed, the detailed results are nested within the `workflowResult` object. To find the specific outcomes of the fraud checks, navigate the JSON response structure as follows: 1. **Start with `workflowStepResults`:** In the `workflowResult`, find the `workflowStepResults` array. 2. **Identify the FRAUD Step:** Look for the object where `stepName` is `FRAUD`. 3. **Examine `processResults`:** Inside this step result is a `processResults` array. Each object in this array is a Process Result Object (PRO) containing granular data for a specific check (e.g., one PRO for email, one for phone). 4. **Drill into `supplementaryData`:** The richest details are in the `supplementaryData` object within each PRO. The `type` field here is crucial as it defines the structure and meaning of the data. ## Decoding `supplementaryData` for Fraud Checks The structure of the `supplementaryData` object is determined by its `type`. For fraud checks, you will encounter the following types: ### Type: `FRAUD_EMAIL_ADDRESS` This object contains the results of the risk analysis for an individual's email address. ```json theme={null} "supplementaryData": { "type": "FRAUD_EMAIL_ADDRESS", "emailAddressId": "239db6d7-90be-4368-bc35-23194f13eae5", "riskLevel": "UNACCEPTABLE", "reference": { "name": "sardine", "reference": "https://dashboard.sandbox.sardine.ai/...", "type": "URL" }, "indicators": [ { "name": "emailLevel", "value": "very_high", "rules": [ { "isActive": true, "name": "Forced very high email risk", "reference": "30" } ] } ] } ``` **Key Fields:** * `emailAddressId`: The unique ID of the email address that was checked. * `riskLevel`: The risk level assessed by the provider (e.g., LOW, MEDIUM, HIGH, UNACCEPTABLE). * `indicators`: An array of specific signals or rules that were triggered during the check. * `reference`: A link or reference to the provider's system for more details. ### Type: `FRAUD_PHONE_NUMBER` This object provides the results of the risk analysis for a phone number. ```json theme={null} "supplementaryData": { "type": "FRAUD_PHONE_NUMBER", "phoneNumberId": "a6ba094e-77ec-44bc-8b1c-5152b158276a", "riskLevel": "LOW", "reference": { "name": "sardine", "reference": "https://dashboard.sandbox.sardine.ai/...", "type": "URL" }, "indicators": [ { "name": "phoneLevel", "value": "low" } ] } ``` **Key Fields:** * `phoneNumberId`: The unique ID of the phone number that was checked. * `riskLevel`: The risk level assessed by the provider. * `indicators`: An array of specific signals or rules that were triggered. ### Type: `FRAUD_DEVICE` & `FRAUD_IP_ADDRESS` These objects contain the risk analysis for the device and IP address associated with a user's session. They share a similar structure. ```json theme={null} "supplementaryData": { "type": "FRAUD_DEVICE", "riskLevel": "HIGH", "session": { "token": "40508276-14d3-4a51-b59a-343a54e39f93" }, "device": { "deviceId": "1d9566b0-9699-460f-8d25-59179155f10e", "os": "Windows", "browser": "Chrome", "isEmulated": true, "reputation": "medium_risk", "vpnLikelihood": "HIGH" }, "indicators": [ { "name": "deviceLevel", "value": "high" } ] } ``` **Key Fields:** * `riskLevel`: The risk level assessed by the provider. * `session`: Contains the provider's session token. * `device`: An object containing detailed device characteristics, such as OS, browser, and fraud indicators like `isEmulated` or `vpnLikelihood`. * `ipAddressInformation`: (For `FRAUD_IP_ADDRESS` type) An object containing IP details like `v4Address` and `connectionType`. ## Fraud Issues and Risk Factors The fraud checks directly influence the workflow's outcome by generating issues and risk factors. * **Issues:** When a check returns a `HIT` result, a corresponding issue is created. For example, a high-risk email will generate an issue with `category: FRAUD` and `issue: FRAUD_EMAIL_ADDRESS`. * **Risk Factors:** The `riskLevel` from each check is converted into a risk factor (e.g., `fraud_email`, `fraud_device`) which contributes to the entity's overall risk score. ## Resolving and Invalidating Results ### Resolving a HIT If a fraud check results in a `HIT`, an operator can manually review and resolve it. This is done by changing the `manualStatus` of the corresponding Process Result Object (PRO). Call the following endpoint with the `processResultId` of the PRO to be updated: ```bash theme={null} PATCH /v2/individuals/{entityId}/results/fraud ``` **Manual Status Options:** * `FALSE_POSITIVE`: The signal is incorrect and not a sign of fraud. * `TRUE_POSITIVE_ACCEPT`: The signal is correct, but the risk is acceptable for onboarding. * `TRUE_POSITIVE_REJECT`: The signal is correct, and the applicant should be rejected. Once resolved, re-executing the workflow will take the manual override into account, potentially resulting in a `CLEAR` or `PASS` status. ### Invalidation of Results Fraud check results are tied to specific data points and can be automatically invalidated if that data changes: * **MARKED\_INVALID:** If an email or phone number that was checked is modified or deleted, the associated result's `systemStatus` is set to `MARKED_INVALID`. * **STALE:** If a new email or phone with a higher precedence is added to the entity and the workflow is re-run, the old result is marked as `STALE`. # Fraud Prevention and Risk-Based Onboarding Overview Source: https://docs.frankieone.com/docs/fraud-prevention-risk-based-onboarding-1 Integrate FrankieOne's fraud signals and risk-based decisioning into your onboarding flow with OneSDK and our KYC API. ## Introduction A significant challenge faced by many businesses today is balancing fraudulent account opening risk with a smooth user experience during onboarding. This often leads to high friction for low-risk users and not enough scrutiny for high-risk profiles. The FrankieOne solution adapts the verification process to each user's unique risk profile, ensuring low-risk users enjoy a fast, frictionless journey while high-risk applicants undergo additional, necessary identity checks. Onboarding fraud checks apply to individual entities only. Organization entity (KYB) onboarding does not currently include fraud checks. ### How Risk-Based Onboarding Works Flowchart showing risk-based onboarding: initial fraud signal assessment, risk score determination, and dynamic verification paths for low-risk, medium/high-risk, and very high-risk users Our risk-based onboarding model assigns each user a real-time risk score, categorizing them as low, medium, high or very high risk. This allows you to apply the right level of verification at every step, blocking fraud early without adding friction for genuine customers. As a customer submits their details, our solution assesses fraud risk in the background using real-time intelligence from device, phone, and email signals. This happens instantly without disrupting the user's experience. Based on the initial signals, a risk score is calculated to determine if the user is Low, Medium/High, or Very High Risk. **Apply Dynamic Verification** The user's journey adapts based on their risk level. **Low Risk** users proceed with minimal checks and can be onboarded quickly. **Medium or High Risk** users are prompted for additional verification steps, such as KYC checks, ID validation, or biometrics. **Very High Risk** applications can be rejected immediately, stopping bad actors before they create an account. ### Key Features and Signals Our solution leverages best-in-class providers to assess risk in real-time, using a powerful combination of device intelligence and behavioral biometrics to filter out bad actors. Identifies devices through cookies and device fingerprinting to flag suspicious sessions. Signals include:
Emulator, Proxy, and VPN detection
Browser fingerprinting and Device ID
Remote desktop detection
Detects fraudsters through their intrinsic behaviors and patterns during the onboarding process. Signals include:
Typing and mouse signals
Use of copy, paste, and autofill functions
Hesitation, distraction, and context switching
Validates user-provided information against trusted data sources.
**Email Risk Assessment:** Checks email age, domain risk, and associated account behavior.
**Phone Risk Assessment:** Determines if a phone is VOIP or a landline and analyzes its behavior.
**IP Location Intelligence:** Detects proxy use and analyzes risk based on IP country, city, and timezone.
## Integration essentials Use our [**KYC API**](/docs/fraud-checks-guide) to perform email and phone checks, and retrieve combined risk scores. [**Learn more** …](/docs/fraud-checks-guide) Capture device and behavioral biometrics data with our [**OneSDK**](/docs/sdk-reference/device-module) for web and mobile platforms. [**Learn more** …](/docs/sdk-reference/device-module) Access fraud insights and manage results through our user-friendly portal. [**Learn more** …](/docs/fraud-checks) # Fraud Prevention and Risk-Based Onboarding Features Source: https://docs.frankieone.com/docs/fraud-v2-features Explore the key features and fraud signals that power FrankieOne's Risk-based Onboarding solution. The following sections outline the key features and fraud signals that power FrankieOne's Risk-based Onboarding solution. FrankieOne provides the following solutions that customers can use to prevent fraud when using Onboarding Fraud Checks. Assesses whether the email is disposable, numeric, contains similarities to the user’s name, how old it is, how risky the domain is, and its general risk in our fraud provider networks. Assesses whether the number is associated with a risky line type like VoIP (Voice over Internet Protocol), the risk of the carrier, whether the phone name matches the user’s profile with their telco, or if it’s reported as fraudulent. Uses cookies and device fingerprinting to detect suspicious devices (like emulators or scripts) and sessions (such as proxies or remote desktops). Flags devices or IPs linked to multiple users to identify potential synthetic accounts and session relationships. Analyzes mouse and typing patterns to detect fraud, such as frequent copy-pasting, rapid input, and unnatural mouse movements. Assesses whether the user is located where they say they are, is using a VPN, or is in a high-risk location. ## Rules ### Creating rules We provide a highly versatile risk rule engine that allows you to create rules using a wide range of user, phone, email, device, and location signals. Screenshot showing the rule configuration interface with signal types and conditions ### Shadow mode If a rule is in Shadow mode, that means it will run and capture metrics, but it won't update the risk level of a session. Running rules in Shadow mode initially is an easy way to start to get additional data about each session and experiment with what risk signals are most associated with fraud. ## Results in the Portal In the Portal, you can view fraud check results alongside your KYC checks in a single view. When a user is run through a workflow with onboarding fraud checks enabled, and it fails for any reason, you can see the specific risks associated with the failure on the overview page. If an email or phone number is modified or deleted after a fraud check has been completed, the associated fraud check results are marked as invalid. You can view invalidated results in the FrankieOne Portal. Screenshot of the FrankieOne Portal showing fraud check results with risk details for email and phone signals # Getting Started with Fraud Prevention and Risk-Based Onboarding Source: https://docs.frankieone.com/docs/fraud-v2-getting-started Integrate FrankieOne's fraud signals and risk-based decisioning into your onboarding flow with OneSDK and the KYC API. This guide is for developers integrating onboarding fraud checks into their application. By the end of this guide, you will have configured FrankieOne OneSDK or the KYC API to collect fraud signals, and you will be able to review fraud check results in the FrankieOne Portal. ## Getting Started with Onboarding Fraud Check out the [integration](/docs/tm/integration) page for an overview of the implementation process. ### 1: Use OneSDK To use device and behavioural biometric checks, your FrankieOne OneSDK integration must be configured to enable device data collection. Contact your Customer Success Manager to enable this. If you only want to use phone and email checks, you can skip the OneSDK integration. [Use OneSDK](/docs/quickstart-guide) if you want to capture device signals from your user session, along with email and phone checks. Follow [these steps](/docs/sdk-reference/device-module) to set up the OneSDK to collect device, email, and phone signals during your user's onboarding. ### 2: Use the KYC API If you only want to use phone and email checks, you can skip the OneSDK integration and use the FrankieOne KYC API to collect email and phone signals. The KYC API is also required for device and behavioral biometric checks. To use phone and email screening, you need to use the FrankieOne KYC API. Follow the steps to [verify customers](/docs/fraud-checks-guide) through our KYC API. When creating a verification session, include the user's email and phone number as identity documents. ### 3: Review and Manage Fraud Checks results in the Portal Review your fraud rules and check results alongside your KYC checks via the [API](/docs/fraud-checks-guide-results) or in the [FrankieOne Portal](/docs/fraud-checks). Use the information to make informed decisions about onboarding users. ##### Need Help? For technical support or to enable fraud detection features, contact your FrankieOne Customer Success representative or [visit our support portal](https://frankieone.atlassian.net/servicedesk/customer/portal/3/group/17). # Fraud and Transaction Monitoring Use Cases Source: https://docs.frankieone.com/docs/fraud-v2-use-cases Explore common use cases for FrankieOne’s Fraud and Transaction Monitoring solutions. Fraudsters use fake, stolen, or synthetic identity documents to open new accounts and exploit organizations. In some cases, they combine real and fabricated personal information to create entirely new identities that do not belong to any single real person. FrankieOne detects identity fraud during onboarding by screening email addresses and phone numbers against known fraud networks, and by analyzing device and behavioral signals for patterns associated with fraudulent identities. For example, a mismatch between email age and phone registration date, combined with a device flagged for emulator use, would raise the entity's risk score. Cross-referencing multiple signals helps identify synthetic identities that may pass individual data checks. **Relevant signals:** Email check, Phone check, Device signals, Behavioral biometrics, Location check Criminals use stolen credentials to impersonate legitimate customers and gain unauthorized control of their accounts. FrankieOne identifies account takeover attempts by comparing device fingerprints and behavioral biometrics against the entity's established patterns. Unusual typing cadence, unfamiliar devices, or sessions originating from high-risk IP addresses trigger additional verification or manual review. **Relevant signals:** Device signals, Behavioral biometrics, Location check, Activity monitoring Organized crime rings use automated scripts, bots, and coordinated human operators to rapidly create large numbers of fraudulent accounts. FrankieOne flags fraud farm activity by detecting multiple accounts linked to the same device or IP address, identifying emulator, remote desktop, and headless browser usage, and recognising automated input patterns. Behavioral biometrics detect bot-driven sessions through signals such as unnaturally consistent typing speed, absence of mouse hesitation, and rapid form completion across multiple sessions. **Relevant signals:** Device signals, Behavioral biometrics, Location check Accounts are created by recruited individuals to illegally transfer or launder money on behalf of criminals. FrankieOne helps identify potential money mule accounts by screening contact details against fraud provider networks and assessing risk signals at onboarding. High-risk phone numbers (such as VoIP lines), disposable email addresses, and device signals associated with known fraud rings contribute to elevated risk scores that trigger manual review before onboarding is completed. **Relevant signals:** Email check, Phone check, Device signals, Transaction monitoring, Activity monitoring Loan and credit application fraud occurs when fraudsters apply for loans or credit using false information or stolen identities. They may manipulate financial details or misrepresent their income and employment. FrankieOne helps detect application fraud at onboarding by validating contact details against fraud provider networks and identifying suspicious device and behavioral signals during the application session. Device intelligence flags emulators, VPN usage, and devices linked to multiple applications. **Relevant signals:** Email check, Phone check, Device signals, Behavioral biometrics Scams are a form of social engineering fraud where criminals manipulate people into sharing sensitive information or transferring funds directly to the criminal. Methods include phishing emails, fake investment schemes, and impersonation. While onboarding fraud checks do not directly detect social engineering, activity monitoring can identify unusual session behavior after a scam has been initiated — such as login from an unfamiliar device, rapid changes to account details, or atypical fund transfer patterns. **Relevant signals:** Device signals, Behavioral biometrics, Transaction monitoring, activity monitoring Individuals create multiple accounts to exploit sign-up bonuses, referral rewards, or promotional offers. This is common in gaming, wagering, and fintech platforms. FrankieOne identifies multi-accounting by detecting multiple sessions or accounts linked to the same device fingerprint or IP address. Device intelligence flags shared devices, emulators, and VPN usage that are commonly associated with promo abuse at scale. **Relevant signals:** Device signals, Location check # Getting Started: Your First API Call Source: https://docs.frankieone.com/docs/getting-started This guide will walk you through setting up your environment, authenticating, and making your first successful API call to the FrankieOne platform. Welcome to the FrankieOne API! This guide provides the essential information to get you up and running. Our goal is to help you make your first successful API call in minutes. ### Your FrankieOne Starter Pack When you partner with FrankieOne, your Customer Success Manager will provide you with a starter pack containing everything you need for each environment. You should have the following: | Resource | UAT / Sandbox | Production | | :--------------- | :------------------------------- | :--------------------------------- | | **Portal URL** | `https://portal.uat.frankie.one` | `https://portal.frankie.one` | | **API Base URL** | `https://api.uat.frankie.one/v2` | `https://api.frankie.one/v2` | | **Customer ID** | Your unique UAT Customer ID | Your unique Production Customer ID | | **API Key** | Your secret UAT API Key | Your secret Production API Key | *** ## Authentication Headers All API requests to FrankieOne must be authenticated. You'll use the credentials from your starter pack in the request headers. | Header | Required | Description | | :--------------------- | :------- | :--------------------------------------------------------------------------------------------------------------- | | `api_key` | **Yes** | Your secret API key for the specific environment (UAT or Production). | | `X-Frankie-CustomerID` | **Yes** | The unique identifier for your account. | | `X-Frankie-Username` | No | The email address or identifier of the operator performing the action. Highly recommended for auditing purposes. | | `X-Frankie-Channel` | No | The channel the request originates from (e.g., `API`, `PORTAL`, `ONESDK`). Useful for analytics and routing. | ##### Keep Your API Key Secure Your `api_key` is a secret and should be treated like a password. Store it securely on your backend and never expose it in client-side code or public repositories. If you suspect a key has been compromised, contact support immediately. *** ## Quickstart in 3 Steps Follow these steps to ensure your credentials are correct and your environment is ready for integration. The easiest way to verify that your credentials and connection are working is to call our simple health check endpoint: `/ruok`. This endpoint doesn’t require a request body and is used purely to confirm successful authentication. ```cURL theme={null} curl --location '[https://api.uat.frankie.one/v2/kyc/ruok](https://api.uat.frankie.one/v2/kyc/ruok)' --header 'api_key: {{your_uat_api_key}}' --header 'X-Frankie-CustomerID: {{your_uat_customer_id}}' ``` A successful request will return a `200 OK` status and the following JSON response, confirming your keys are valid. ```Response theme={null} { "status": "OK" } ``` Before you can start verifying customers, your account needs to be configured with at least one workflow and one service profile. Your Customer Success Manager typically sets these up for you. You can confirm your setup by calling the `GET /v2/workflows` endpoint. This will list all the executable workflows available to you. ```cURL theme={null} curl --location '[https://api.uat.frankie.one/v2/workflows](https://api.uat.frankie.one/v2/workflows)' --header 'api_key: {{your_uat_api_key}}' --header 'X-Frankie-CustomerID: {{your_uat_customer_id}}' ``` You should receive a `200 OK` response with a `workflows` array. If the array is empty, please contact your Customer Success Manager to get your workflows published. ```Response theme={null} { "requestId": "req_01J...", "workflows": [ { "serviceName": "DEFAULT", "workflowId": "wf_01J...", "workflowName": "Standard-KYC-AU", "type": "SYSTEM", "lifecyclePhase": "ONBOARDING" } ] } ``` Now you're ready to perform your first check. The most fundamental call is to create an individual and execute a workflow in a single request. This is the fastest way to verify a new customer. You will need the `serviceName` and `workflowName` from the previous step. > *For a detailed guide on this process, see our **[Electronic KYC with Government ID](/docs/electronic-kyc-checks)** guide.* *** ## Next Steps You've successfully authenticated and confirmed your setup. Now you're ready to start building. Follow our implementation guides for common use cases. Learn the complete lifecycle of an 'individual' entity, from creation and retrieval to updates and deletion. A step-by-step guide to executing a verification workflow against an existing entity. Dive deep into every endpoint, parameter, and response object in our comprehensive API Reference. # Global KYC Source: https://docs.frankieone.com/docs/global-kyc-guide Verify a wide range of international and domestic identity documents through a single, standardized API. ## Introduction FrankieOne's Global KYC feature is a core component of the V2 platform, designed to provide a unified and extensible solution for verifying identity documents from around the world. It introduces a standardized data model for handling various document types and an intelligent routing mechanism to direct verification requests to the most appropriate data provider. This solution allows you to build a comprehensive and scalable onboarding process, validating documents from dozens of countries through a single, consistent API interface. **Key Business Goals** * **Unified API for Global Documents:** Verify a wide range of government-issued identity documents using the same standardized `document` object structure, reducing integration complexity. * **Intelligent Routing:** The platform automatically inspects a document's `type` and `country` to route the verification request to the most suitable downstream data source, such as a national document verification service or transport authority. * **Extensive Country Coverage:** Leverage our expanding network of data sources across Asia-Pacific (APAC), Europe, Middle East & Africa (EMEA), and the Americas. * **Flexible & Extensible Data Model:** Our schema uses a `supplementaryData` object to handle unique, country-specific document requirements without cluttering the primary API structure. *** ## The End-to-End Verification Flow The verification process is seamlessly integrated into the standard entity and workflow execution flow. It involves creating an entity, attaching structured document data, and executing a workflow. First, create an individual entity and attach one or more `document` objects within the `documents.IDENTITY` array. Each object should contain the individual's PII and the specific identifiers for that document, conforming to the standardized schema. ```http theme={null} POST /v2/individuals ``` This single request populates the user's profile with all the necessary information for verification. Next, execute a pre-configured workflow that contains a KYC step for the relevant service profile. ```http theme={null} POST /v2/individuals/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/execute ``` The KYC workflow step automatically inspects each document's `country` and `type`. Based on these fields, it determines the correct downstream data source for verification. The system validates the data against the source's specific requirements and transforms the V2 schema into the format needed by the provider's API. The response from the data source is received and normalized into a standard V2 Process Result Object (PRO). This standardized result can then be used by your workflow's decisioning logic to determine an outcome, such as `PASS` or `REVIEW`. *** ## Core Concepts: The Document Object Understanding the standardized `document` object and the role of `supplementaryData` is key to leveraging the Global KYC feature. ### Standardized Document Fields The `Document-Information` object is the primary container for all document details. It uses a consistent structure regardless of the country of origin. | Field | Data Type | Requirement | Description | | :-------------------- | :------------ | :----------- | :------------------------------------------------------------------------------------------------------------------------------ | | `type` | String (Enum) | **Required** | The standardized type of the document (e.g., `DRIVERS_LICENSE`, `PASSPORT`). Must be a valid `Document-Type` enum value. | | `country` | String | **Required** | The ISO 3166-1 alpha-3 code of the issuing country (e.g., `AUS`, `NZL`). This is a key field for routing. | | `primaryIdentifier` | String | **Required** | The main number or identifier on the document (e.g., Licence Number, Passport Number). | | `secondaryIdentifier` | String | Optional | An additional identifier, often used for conditional requirements (e.g., the Card Number on some Australian Driver's Licences). | | `subdivision` | String | Optional | The abbreviated state, province, or territory of issue where applicable (e.g., "VIC" for Victoria, "NSW" for New South Wales). | | `issueDate` | Date Object | Optional | The document's date of issue. | | `expiryDate` | Date Object | Optional | The document's expiration date. | | `supplementaryData` | Object | Optional | A flexible object for storing document-specific data that doesn't fit into the standard fields. See details below. | | `documentId` | String (UUID) | Read-only | A unique identifier assigned by FrankieOne when a document is created. | ### Handling Country-Specific Data with `supplementaryData` The `supplementaryData` object is the key to our extensible model, allowing us to support unique data points for specific documents without altering the core schema. When you submit a document with supplementary data, the `supplementaryData.type` **must** match the main `document.type`. Here are a few key examples: * **Australian Medicare Card (`NATIONAL_HEALTH_ID`):** Requires the 1-digit `reference` number that appears to the left of the individual's name on the card. * **Chinese National ID (`NATIONAL_ID`):** Supports a `homeCountryFullName` field to capture the individual's name in native Chinese characters. * **Australian Citizenship Certificate (`CITIZENSHIP_CERTIFICATE`):** Requires the `acquisitionDate`. * **Australian Marriage Certificate (`MARRIAGE_CERT`):** Requires the `marriageDate` and the full name of the second partner (`partner2GivenName`, `partner2FamilyName`). *** ## API Request Examples ### Example 1: Simple Document (Australian Passport) This is a straightforward verification using only the common document fields. ```json theme={null} { "individual": { "name": { "givenName": "Jane", "familyName": "Citizen" }, "dateOfBirth": { "year": "1990", "month": "01", "day": "15" }, "documents": { "IDENTITY": [ { "type": "PASSPORT", "country": "AUS", "primaryIdentifier": "E1234567" } ] } } } ``` ### Example 2: Document with Conditional Fields (NSW Driver's Licence) For an Australian Driver's Licence issued in New South Wales (and all states/territories except Victoria), the `secondaryIdentifier` (Card Number) is **mandatory**. ```json theme={null} { "individual": { "name": { "givenName": "John", "familyName": "Smith" }, "dateOfBirth": { "year": "1985", "month": "05", "day": "20" }, "documents": { "IDENTITY": [ { "type": "DRIVERS_LICENSE", "country": "AUS", "subdivision": "NSW", "primaryIdentifier": "98765432", "secondaryIdentifier": "1234567890" } ] } } } ``` ### Example 3: Document with Supplementary Data (Australian Marriage Certificate) This example shows how to use the `supplementaryData` object to provide the extra information needed to verify an Australian Marriage Certificate from Victoria. ```json theme={null} { "individual": { "name": { "givenName": "Jane", "familyName": "Citizen" }, "documents": { "IDENTITY": [ { "type": "MARRIAGE_CERT", "country": "AUS", "subdivision": "VIC", "primaryIdentifier": "98765/1990", "supplementaryData": { "type": "MARRIAGE_CERT", "marriageDate": "1990-12-15", "partner2GivenName": "John", "partner2FamilyName": "Doe" } } ] } } } ``` *** ## Country and Document Coverage Our Global KYC services span across multiple regions. The tables below provide a detailed breakdown of supported documents and their API codes for each country. ### Supported Documents by Country | Country | Document | Code | | :------------- | :--------------------------------------------------------- | :------------------------------------------- | | Australia (AU) | Birth Certificate | `BIRTH_CERT` | | | Centrelink Card | `CONCESSION`, `PENSION`, `HEALTH_CONCESSION` | | | Citizenship Certificate | `CITIZENSHIP` | | | Death Certificate | `DEATH_CERT` | | | Immigration Card (ImmiCard) | `IMMIGRATION_CARD` | | | Drivers License | `DRIVERS_LICENSE` | | | Marriage Certificate | `MARRIAGE_CERT` | | | Name Change Certificate | `NAME_CHANGE` | | | National Health ID (Medicare) | `NATIONAL_HEALTH_ID` | | | National ID | `NATIONAL_ID` | | | Passport | `PASSPORT` | | Brazil | CNPJ (Cadastro Nacional de Pessoas Jurídicas) | `NATIONAL_ID` | | | CPF (Cadastro de Pessoas Físicas) | `NATIONAL_ID` | | Canada | SIN (Social Insurance Number) | `NATIONAL_ID` | | Chile | RUT (Rol Único Tributario) | `TAX_ID` | | | RUN (Rol Único Nacional) | `NATIONAL_ID` | | China | National ID (Resident Identity Card Number) | `NATIONAL_ID` | | | Passport | `PASSPORT` | | Colombia | CPIN (Colombian Personal Identification Number) | `NATIONAL_ID` | | Czech Republic | NID (Rodné číslo) | `NATIONAL_ID` | | Denmark | CPR (Central Person Register) | `NATIONAL_ID` | | Finland | Personal Identity Code | `NATIONAL_ID` | | Ghana | SSNIT (Social Security and National Insurance Trust) | `NATIONAL_ID` | | | Voter ID | `NATIONAL_ID` | | Hong Kong | HKID (Hong Kong Identification Number) | `NATIONAL_ID` | | India | Aadhar | `NATIONAL_ID` | | | EPIC - Voter ID | `NATIONAL_ID` | | | License | `DRIVERS_LICENSE` | | | PAN (Permanent Account Number) | `NATIONAL_ID` | | | Passport | `PASSPORT` | | Indonesia | NIK (Nomor Induk Kependudukan) | `NATIONAL_ID` | | Italy | Codice Fiscale | `TAX_ID` | | Japan | My number | `TAX_ID` | | Jordan | Civil Identification Number | `NATIONAL_ID` | | Kenya | Alien Card (Foreign ID) | `NATIONAL_ID` | | | License | `DRIVERS_LICENSE` | | | National ID (Huduma Namba) | `NATIONAL_ID` | | | Passport | `PASSPORT` | | Luxembourg | Social Security | `NATIONAL_ID` | | Malaysia | NRIC (National Registration Identity Card) | `NATIONAL_ID` | | Mexico | CURP (Clave Única de Registro de Población) | `NATIONAL_ID` | | | RFC (Registro Federal de Contribuyentes) | `TAX_ID` | | Nigeria | BVN (Bank Verification Number) | `NATIONAL_ID` | | | CAC (Corporate Affairs Commission) | `NATIONAL_ID` | | | License | `DRIVERS_LICENSE` | | | NIN (National Identification Number) | `NATIONAL_ID` | | | TIN (Tax Identification Number) | `TAX_ID` | | | Voter ID | `NATIONAL_ID` | | New Zealand | Birth Certificate | `BIRTH_CERT` | | | License | `DRIVERS_LICENSE` | | | Passport | `PASSPORT` | | Philippines | PCN (PhilSys Card Number) | `NATIONAL_ID` | | | Passport | `PASSPORT` | | Poland | PESEL (Powszechny Elektroniczny System Ewidencji Ludności) | `NATIONAL_ID` | | Portugal | Tax number (Número de Identificação Fiscal) | `TAX_ID` | | Romania | CNP (Cod Numeric Personal) | `NATIONAL_ID` | | Russia | Internal Passport Number | `PASSPORT` | | | Tax ID Number | `TAX_ID` | | South Africa | National ID | `NATIONAL_ID` | | Spain | DNI (Documento Nacional de Identidad) | `NATIONAL_ID` | | | NIF (Número de Identificación Fiscal) | `TAX_ID` | | | NIE (Número de Identificación de Extranjero) | `NATIONAL_ID` | | Sweden | PIN (Personal Identification Number) | `NATIONAL_ID` | | Thailand | National Identity Card | `NATIONAL_ID` | | Turkey | TIN (Turkish Identification Number) | `TAX_ID` | | USA | SSN (Social Security Number) | `NATIONAL_ID` | | International | Passport | `PASSPORT` | | | Tax ID | `TAX_ID` | This section provides a list of common abbreviations used for various identification documents across different countries. These abbreviations are often used in KYC processes and can help streamline document handling. * **Aadhar**: Unique Identification Number (India) * **ASIC/MSIC**: Aviation/Maritime Security Identification Card (Australia) * **BVN**: Bank Verification Number (Nigeria) * **CAC**: Corporate Affairs Commission (Nigeria) * **CNPJ**: Cadastro Nacional de Pessoas Jurídicas (Brazil) * **CPF**: Cadastro de Pessoas Físicas (Brazil) * **CPIN**: Colombian Personal Identification Number (Colombia) * **CNP**: Cod Numeric Personal (Romania) * **CURP**: Clave Única de Registro de Población (Mexico) * **DNI**: Documento Nacional de Identidad (Spain) * **EPIC**: Electors Photo Identity Card (India) * **HKID**: Hong Kong Identification Number (Hong Kong) * **ImmiCard**: Immigration Card (Australia) * **NID**: National Identification Number (Czech Republic) * **NIE**: Número de Identificación de Extranjero (Spain) * **NIF**: Número de Identificación Fiscal (Spain) * **NIK**: Nomor Induk Kependudukan (Indonesia) * **NRIC**: National Registration Identity Card (Malaysia) * **PAN**: Permanent Account Number (India) * **PCN**: PhilSys Card Number (Philippines) * **PESEL**: Powszechny Elektroniczny System Ewidencji Ludności (Poland) * **PIN**: Personal Identification Number (Sweden) * **RFC**: Registro Federal de Contribuyentes (Mexico) * **RUT**: Rol Único Tributario (Chile) * **RUN**: Rol Único Nacional (Chile) * **SIN**: Social Insurance Number (Canada) * **SSN**: Social Security Number (USA) * **SSNIT**: Social Security and National Insurance Trust (Ghana) * **TIN**: Tax Identification Number (Nigeria, Turkey) **For KYC checks, all tax identification documents must be submitted as document type `NATIONAL_ID` in the FrankieOne KYC v2 API to verify entity details.** ##### Important Notes The document codes above are used in the FrankieOne KYC v2 API. Ensure you use the correct code for each document type when making API requests. * **Not all document types are available in every country.** Refer to the specific country documentation for details. * **Not all document types are supported in the FrankieOne Portal.** If you need to use a document type not listed here, please contact FrankieOne support. *** ## Integration Best Practices * **Understand Local Requirements**: Each country may require different document types for KYC. Review the documentation for the countries you support. * **Use Correct Document Codes**: Always use the exact `Document Code` specified in the table above when submitting documents via the API to ensure correct routing and processing. * **Handle Supplementary Data**: For documents that require additional details (such as Australian Medicare or Marriage Certificates), ensure you populate the `supplementaryData` object correctly. * **Validation & Error Handling**: Handle API errors gracefully by interpreting error messages and providing clear feedback to users. * **Testing & Monitoring**: Test your integration thoroughly before going live. Monitor document handling workflows to quickly identify and resolve issues. For detailed field requirements and valid values for different document types, please refer to the specific country-level documentation pages. # Hosted Flow Templates Source: https://docs.frankieone.com/docs/hosted-common-use-cases ## What are Flow Templates Flow Templates are pre-configured, production-ready verification journeys built and maintained by FrankieOne. Each template contains the complete onboarding workflow — data collection, verification logic, vendor orchestration, and results delivery — so you can go live quickly without designing screens or managing vendor SDKs. All Pre-Built Flows share these qualities: * **Managed & compliant**: Always up-to-date with the latest regulatory and vendor requirements. * **Hosted by FrankieOne**: No need to deploy or maintain front-end infrastructure. * **Essential Customisation**: Add your logo, colours, and on-screen messaging. * **Scalable**: Enable different flows for different regions, risk levels, or customer types. Most customers start with one of the three standard templates below. ## IDV (VOI) Flow The **IDV Flow** is a full identity-verification experience using document scanning (OCR) and selfie capture (biometrics) to confirm the user’s identity. Best for workflows where document and biometric verification are mandatory. ### Typical Journey 1. Customer scans a government ID (e.g. passport, licence, national ID). 2. Customer takes a selfie for liveness and face matching. 3. Vendor performs OCR, ID document checks and biometric comparison. 4. Data is validated through connected sources upon submission based on your recipes and workflows. 5. Results are returned to your Portal or via API. 6. Entity information, risk scores and status are updated automatically. Creating a POST Request with following headers and request Body ```shell theme={null} curl --location 'https://api.frankie.one/v2/individuals/hostedUrl' \ --header 'X-Frankie-Customerid: CUSTOMER_ID' \ --header 'api_key: API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "customerRef": "YOUR_CUSTOMER_ID_OR_RANDOM_STRING", "consent": true, "oneSDKFlowId": "idv" }' ``` will return object: ```json theme={null} { "entityId": "998a9d13-994b-4533-8a18-95208165cc9f", "requestId": "01K1EWDQZRT7XPEGGWHJR1ZR4V", "status": "success", "url": "https://verify.uat.frankie.one/v2/?t=7MnbsKqvvXGucHxyy9p6cH", "urlExpiry": "2025-08-02T23:59:32.081184475Z" } ``` where `url` will contain the link to our Hosted OneSDK Solution. To read more, go here. ### Key Features 1. OCR extracting document information 2. Selfie comparison with portrait image on ID document 3. Built-in document fraud detection, selfie capture and liveness detection 4. Access Image of ID docs and Selfie on FrankieOne Portal or via API 5. FrankieOne provides integration with the most popular IDV vendors on the market ## OCR Only Flow The **OCR-Only Flow** focuses on quick document validation without biometric capture. It’s ideal for lower-risk onboarding, identity pre-checks, or use cases where a selfie step is unnecessary. Faster completion times and higher conversion. Creating a POST Request with following headers and request Body ```shell theme={null} curl --location 'https://api.frankie.one/v2/individuals/hostedUrl' \ --header 'X-Frankie-Customerid: CUSTOMER_ID' \ --header 'api_key: API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "customerRef": "YOUR_CUSTOMER_ID_OR_RANDOM_STRING", "consent": true, "oneSDKFlowId": "idv_review" }' ``` will return object: ```json theme={null} { "entityId": "998a9d13-994b-4533-8a18-95208165cc9f", "requestId": "01K1EWDQZRT7XPEGGWHJR1ZR4V", "status": "success", "url": "https://verify.uat.frankie.one/v2/?t=7MnbsKqvvXGucHxyy9p6cH", "urlExpiry": "2025-08-02T23:59:32.081184475Z" } ``` where`url` will contain the link to our Hosted OneSDK Solution. To read more, go here. ## eKYC Forms Flow The eKYC Forms Flow on the Hosted OneSDK allow customers to embed or send their end-users a link with a fixed set of forms that allow PII data to be captured and used for KYC. Customers will gain access to the following screens in sequence with no ability to make any modifications. ### Typical Journey 1. Customer fills in personal details (name, DOB, address). 2. Data is validated through connected sources upon submission based on your recipes and workflows. 3. Results are returned to your Portal or via API. 4. Entity information, risk scores and status are updated automatically Creating a POST Request with following headers and request Body ```shell theme={null} curl --location 'https://api.frankie.one/v2/individuals/hostedUrl' \ --header 'X-Frankie-Customerid: CUSTOMER_ID' \ --header 'api_key: API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "customerRef": "YOUR_CUSTOMER_ID_OR_RANDOM_STRING", "consent": true, "oneSDKFlowId": "manual_kyc" }' ``` will return object: ```json theme={null} { "entityId": "998a9d13-994b-4533-8a18-95208165cc9f", "requestId": "01K1EWDQZRT7XPEGGWHJR1ZR4V", "status": "success", "url": "https://verify.uat.frankie.one/v2/?t=7MnbsKqvvXGucHxyy9p6cH", "urlExpiry": "2025-08-02T23:59:32.081184475Z" } ``` where `url` will contain the link to our Hosted OneSDK Solution. To read more, go here. ### Key Features 1. Manual entry of PII (personal identity information), document information 2. One-click submission to FrankieOne KYC checks with DVS, PEP and AML options # IDV & Biometrics Source: https://docs.frankieone.com/docs/idv-biometrics-guide Learn how to implement IDV and Biometrics in your KYC processes. ## Introduction FrankieOne's Identity Verification (IDV) and Biometrics services are designed to accurately identify and onboard genuine individuals while effectively preventing fraud from falsified or stolen identification documents. By integrating advanced document analysis, Optical Character Recognition (OCR), and biometric checks like facial comparison and liveness detection, you can build a robust, secure, and compliant onboarding workflow. This guide will walk you through the end-to-end process of implementing our IDV and Biometrics solution, from creating an entity to initiating the verification workflow. **Key Features** * **Global Document Verification:** Validate a wide range of government-issued identity documents from around the world. * **Advanced Biometric Authentication:** Secure your platform with facial recognition and liveness detection to prevent spoofing and ensure the user is physically present. * **Automated Data Extraction (OCR):** Reduce manual entry and errors by automatically extracting information from identity documents. * **Configurable Workflows:** Tailor the verification steps and logic to match your specific risk appetite and compliance requirements. * **Streamlined Integration:** Use our Hosted URL for the quickest integration or leverage our SDKs for a more customized user experience. *** ## The End-to-End IDV Flow The verification process involves a sequence of API calls to create an entity, initiate a capture session, process the captured data, and finally execute a workflow to get a result. Before you can perform an IDV check, you need an `entityId` for the user. If you don't already have one, create an individual entity by making a server-side call to the API. ```BASH theme={null} POST /v2/individuals ``` This request creates the user's profile in the FrankieOne system and returns the essential `entityId` that will be used in all subsequent steps. Once you have an `entityId`, you can start the data capture process where the user will submit their document and a selfie. We offer two primary integration paths. #### Option A: Hosted Flow (Recommended) The simplest way to integrate is by using our Hosted URL. This provides a secure, FrankieOne-hosted webpage that guides the user through the entire capture process. Make a server-side call to generate a unique, single-use URL for the user's session. ```BASH theme={null} POST /v2/individuals/hostedUrl ``` You can then redirect the user to this URL. You can even configure it to send the link directly to the user via SMS by setting `sendSMS` to `true` in your request. #### Option B: Direct SDK Integration (Advanced) For a more deeply integrated, native experience within your own application, you can use an IDV provider's SDK. To initialize it, you first need to retrieve a session token from our API. ```BASH theme={null} POST /v2/individuals/{entityId}/actions/idv/token ``` This token authorizes the provider's SDK to conduct the capture session on behalf of the specified `entityId`. After the user successfully completes the document and selfie capture in the Hosted Flow or provider SDK, your backend must instruct FrankieOne to retrieve and process the captured data. ```BASH theme={null} POST /v2/individuals/{entityId}/actions/idv/process ``` This call signals that the capture is complete and triggers FrankieOne to fetch the results from the IDV vendor, including the OCR data and biometric information. Upon successful data processing, the IDV service will automatically execute the workflow configured for the entity's service profile (e.g., `DEFAULT`). This workflow runs the necessary verification steps and generates the final results. To learn how to analyze the detailed outcomes of these checks, please see our dedicated guide: **[Understanding IDV & Biometrics Results](/docs/idv-biometrics-guide-results)**. *** ## Understanding the Verification Checks The IDV workflow orchestrates several powerful checks to ensure the integrity of the verification. * **Document Authenticity**: The system analyzes the document for signs of tampering, fraud, and inconsistencies, verifying security features and comparing it against known templates. Checks include `visual_authenticity` and `image_integrity`. * **Biometric Verification**: This involves two key checks: * **Facial Liveness**: Confirms the user is a real, live person and not a spoof attempt (e.g., a photo of a photo or a deepfake). * **Facial Comparison**: Matches the user's live selfie against the photo on the identity document with a quantifiable `confidence` score. * **OCR Data Comparison**: After extracting data from the document via OCR, the system compares it against the information stored in the user's entity profile. This crucial step flags discrepancies between what the user provided and what is on their official document. FrankieOne uses fuzzy matching logic (the Levenshtein distance algorithm) to handle minor OCR errors or typos in names and numbers. This reduces false negatives from insignificant discrepancies. For example, by default, a name is allowed a Levenshtein distance of 2 before it is flagged as `SUSPECTED`. # Understanding IDV & Biometrics Source: https://docs.frankieone.com/docs/idv-biometrics-guide-results ## Locating IDV & Biometrics Results Once a workflow has been executed, the detailed results are nested within the overall `workflowResult` object. To find the specific outcomes of IDV and Biometric checks, you must navigate the JSON structure. 1. **Start with `workflowStepResults`**: In the `workflowResult`, find the `workflowStepResults` array. 2. **Identify IDV Steps**: Look for steps with names (`stepName`) like `IDV_DOCUMENT_CHECK`, `IDV_FACIAL_COMPARISON`, `IDV_FACIAL_LIVENESS`, and `IDV_OCR_COMPARISON`. 3. **Examine `processResults`**: Inside each relevant step result is a `processResults` array. Each object here is a Process Result Object (PRO) containing granular data. 4. **Drill into `supplementaryData`**: The richest details are in the `supplementaryData` object within a PRO. The `type` field here is crucial as it defines the structure and meaning of the data. ### Decoding `supplementaryData` for IDV Checks The structure of the `supplementaryData` object is determined by its `type`. For IDV and Biometrics, you will encounter several key types. *** #### Type: `IDV_DOCUMENT` This object contains the results of the automated analysis of a submitted identity document, assessing its authenticity and integrity. ```json theme={null} "supplementaryData": { "type": "IDV_DOCUMENT", "outcomeRaw": "clear", "resultMap": { "visual_authenticity": { "resultNormalized": "clear" }, "image_integrity": { "resultNormalized": "clear" }, "data_validation": { "resultNormalized": "clear" }, "compromised_document": { "resultNormalized": "clear" } }, "detectedDocumentType": "DRIVERS_LICENSE", "detectedDocumentCountry": "AUS" } ``` **Key Fields:** * `outcomeRaw`: The original, unprocessed result from the IDV service provider. * `resultMap`: A map containing the results of specific checks. Keys like `visual_authenticity`, `image_integrity`, and `data_validation` indicate the status of different verification aspects. * `detectedDocumentType`: The type of document the system identified (e.g., `DRIVERS_LICENSE`, `PASSPORT`). * `detectedDocumentCountry`: The ISO 3166-1 alpha-3 country code of the document as detected by the provider. *** #### Type: `IDV_FACIAL_COMPARISON` This object provides the results of comparing a user's selfie with the photo on their identity document to confirm they are the same person. ```json theme={null} "supplementaryData": { "type": "IDV_FACIAL_COMPARISON", "outcomeRaw": "clear", "resultMap": { "face_comparison": { "confidence": 99.99, "resultNormalized": "clear" } }, "comparedDocumentId": "92de15f6-5717-4562-b3fc-2c963f6665a7", "comparedSelfieId": "58e0a7e3-0c3f-4e20-95af-0a4a8332d383" } ``` **Key Fields:** * `resultMap`: Contains metrics from the comparison. The `face_comparison` key often includes a `confidence` score. * `comparedDocumentId`: The unique ID of the identity document used. * `comparedSelfieId`: The unique ID of the selfie document used. *** #### Type: `IDV_FACIAL_LIVENESS` This object contains the results of the liveness check, which verifies that the selfie was captured from a live person and not a spoof attempt (e.g., a photo of a photo). ```json theme={null} "supplementaryData": { "type": "IDV_FACIAL_LIVENESS", "outcomeRaw": "clear", "resultMap": { "liveness_detection": { "confidence": 98.7, "resultNormalized": "clear" } }, "comparedSelfieId": "58e0a7e3-0c3f-4e20-95af-0a4a8332d383" } ``` **Key Fields:** * `resultMap`: Contains the outcome of the liveness test. The `liveness_detection` key will often have a `confidence` score. * `comparedSelfieId`: The unique ID of the selfie document that was analyzed. *** #### Types: `IDV_OCR` & `IDV_OCR_COMPARISON` The Optical Character Recognition (OCR) process is crucial for extracting data and verifying it against user-provided information. This typically generates two distinct PROs. 1. **`IDV_OCR`**: This object holds the raw data extracted directly from the identity document image. The `resultMap` will contain key-value pairs of the fields read from the document, such as `full_name`, `document_number`, and `date_of_birth`. 2. **`IDV_OCR_COMPARISON`**: This object compares the data extracted via OCR with the data already present on the entity. It is used to flag discrepancies. ```json theme={null} "supplementaryData": { "type": "IDV_OCR_COMPARISON", "outcomeRaw": "suspected", "resultMap": { "last_name_match": { "resultNormalized": "clear" }, "date_of_birth_match": { "resultNormalized": "clear" } }, "mismatchMap": { "first_name_match": { "originalData": "Jon", "reviewedData": "John", "resultNormalized": "suspected" } }, "comparisonSource": "ENTITY" } ``` **Key `IDV_OCR_COMPARISON` Fields:** * `resultMap`: Indicates which fields matched successfully. * `mismatchMap`: **Crucially**, this highlights any fields that did not align, showing the original vs. the OCR-extracted data. * `comparisonSource`: Specifies what the OCR data was compared against, either `ENTITY` data or `OCR_UPDATE` data. FrankieOne employs fuzzy matching logic (Levenshtein distance) for OCR comparison to account for minor typos or OCR errors. For example, a Levenshtein distance of 1 or 2 might be allowed for names before a mismatch is flagged as `SUSPECTED`. ## IDV Issues and Risk Factors The results from the `supplementaryData` objects are used to generate specific **issues** and **risk factors** that help in decision-making. * **Issues**: When a check result is `SUSPECTED` or `REJECTED`, a corresponding issue is typically created. For example, a `REJECTED` `IDV_FACIAL_LIVENESS` result will generate a `LIVENESS_DETECTION` issue with a `WARNING` severity. * **Risk Factors**: The status of each check (`CLEAR`, `SUSPECTED`, `REJECTED`) is also converted into a risk factor (e.g., `idv_document_result`, `idv_facial_comparison_result`) which contributes to the entity's overall risk score. ## Overriding and Invalidating Results * **Overriding**: If you disagree with an automated result (e.g., a `SUSPECTED` OCR mismatch), you can manually override it. By calling `PATCH /v2/individuals/{entityId}/results/idv` and providing the `processResultId` of the relevant PRO, you can change its `manualStatus` to `CLEAR`. * **Invalidation**: IDV results can be automatically invalidated. For example, if an entity's name or date of birth is updated *after* a successful OCR check, the original OCR PRO's `systemStatus` will be changed from `VALID` to `STALE` or `MARKED_INVALID` to indicate that the result is no longer based on the most current entity data. # IDV & Biometrics: OCR Comparison Source: https://docs.frankieone.com/docs/idv-biometrics-ocr-comparison A deep dive into how FrankieOne compares OCR data with user-provided information to ensure data consistency and prevent fraud. ## What is OCR Comparison? Optical Character Recognition (OCR) is the process of extracting text data from an image, such as a driver's license or passport. The **OCR Comparison** is a critical security step within the IDV workflow where FrankieOne verifies that the data extracted from the document matches the information provided by the user or already stored on their entity profile. The primary objective is to ensure the details on the government-issued ID match the entity profile being submitted for verification, preventing "bait-and-switch" fraud scenarios. ## How OCR Comparison Works The comparison logic is triggered in two primary scenarios: 1. **Manual Input First**: If a user manually enters their details (e.g., name, DOB) *before* the document scan, the OCR comparison is triggered immediately after the scan to check for discrepancies. 2. **Biometrics First / Post-Verification Updates**: If the IDV process happens first, an entity is created using the initial OCR data. If the user later updates key fields (name, DOB, ID number) on their profile, the system re-runs the OCR comparison logic to check if the changes invalidate the original verification. ### The `IDV_OCR_COMPARISON` Supplementary Data The result of this check is found within a Process Result Object (PRO) where the `supplementaryData` object has a `type` of `IDV_OCR_COMPARISON`. ```json theme={null} "supplementaryData": { "type": "IDV_OCR_COMPARISON", "outcomeRaw": "suspected", "resultMap": { "last_name_match": { "resultNormalized": "clear" }, "date_of_birth_match": { "resultNormalized": "clear" } }, "mismatchMap": { "first_name_match": { "originalData": "Jon", "reviewedData": "John", "resultNormalized": "suspected" } }, "ocrResultId": "pro_01J...", "comparisonSource": "ENTITY" } ``` **Key Fields:** * `resultMap`: An object showing which fields **matched successfully**. * `mismatchMap`: An object that highlights the specific fields that **did not match**. This is crucial for debugging `SUSPECTED` results, as it shows the discrepancy (e.g., original "Jon" vs. OCR "John"). * `comparisonSource`: Indicates what the OCR data was compared against. This will be `ENTITY` (for existing entity data) or `OCR_UPDATE` (for data updated post-scan). \[cite: 2975-2979] * `ocrResultId`: The ID of the `IDV_OCR` Process Result Object that this comparison is based on. *** ## Matching Logic and Fuzziness To account for minor OCR inaccuracies or common typos, the comparison does not always require an exact match. FrankieOne uses the **Levenshtein distance** algorithm to measure the difference between the user-provided string and the OCR-extracted string. This "fuzziness" is configurable. The default configuration allows for small discrepancies before a field is flagged as `SUSPECTED`. | Field | Default Levenshtein Distance | | :----------------- | :--------------------------- | | First Name | 2 | | Last Name | 2 | | Date of Birth | 1 | | Document ID Number | 2 | There is also a `compare_ocr_max_mismatch_levenshtein_distance` which, by default, allows for up to 2 characters to be mismatched across all fields before the overall result is marked as `SUSPECTED`. *** ## Result Invalidation A key security feature of the OCR comparison is the re-check that occurs if a user updates their profile information *after* the initial IDV process. This is to protect against a scenario where a fraudster: 1. Uses their real ID and face to pass an IDV check. 2. Later, changes the name, DOB, or ID number on their profile to match the details of a stolen identity. 3. Attempts to use this fraudulent profile to pass other checks like KYC or AML. If the system detects that a change to a key field exceeds the configured Levenshtein distance (e.g., `fuzzy_logic_idv_allowed_distance_family_name`), the original OCR and IDV results will be invalidated by having their `systemStatus` changed to `STALE` or `MARKED_INVALID`. ## Best Practices * **Check the `mismatchMap`**: When you receive an OCR comparison result of `SUSPECTED`, always inspect the `mismatchMap` to understand exactly which field caused the issue. * **Understand Configuration**: Be aware that the definition of a "mismatch" is configurable. A `SUSPECTED` result does not necessarily mean fraud; it could be a minor OCR error that falls within your organization's acceptable risk tolerance. * **Secure Profile Updates**: Be mindful of the result invalidation logic. If you allow users to freely edit their profile details after a successful IDV check, it may trigger an invalidation, requiring them to re-verify. ## Additional Resources * [Interpreting Workflow Results](/docs/interpreting-workflows-v2) * [Understanding IDV & Biometrics Results](/docs/idv-biometrics-guide-results) * [FrankieOne API Reference](/docs/reference/whats-new) # Indian Documents Source: https://docs.frankieone.com/docs/indian-documents-v2 The FrankieOne KYC v2 API supports Indian documents for identity verification. This guide outlines the requirements and best practices for handling these documents. ## Supported Indian Documents The FrankieOne KYC v2 API currently supports the following Indian documents for identity verification: | Document | Code | | :----------------------------- | :---------------- | | Aadhaar | `NATIONAL_ID` | | PAN (Permanent Account Number) | `NATIONAL_ID` | | Voter ID (EPIC) | `NATIONAL_ID` | | Driver's License | `DRIVERS_LICENSE` | | Passport | `PASSPORT` | *** ### Passports Indian passports are official travel documents issued by the Indian government that confirm an individual's identity and citizenship. They include personal details such as the individual's name, date of birth, passport number, and file number. | Field Name | Field | Notes | | :------------ | :------------ | :-------------------------------------------------------------------------------------------------------------- | | Document Type | `type` | Must be `PASSPORT` for Indian passports. | | Country | `country` | Must be `IND` (India). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth as shown on the passport. | | Name | `name` | Enter the full name exactly as shown on the passport, including capitalization, special characters, and spaces. | | Field Name | Field | Notes | | :-------------- | :-------------------- | :--------------------------------------------------------------------------------------------------------------------- | | Passport Number | `primaryIdentifier` | Enter exactly as shown on the passport. Format: One uppercase letter followed by 7 digits (e.g., `J1234567`). | | File Number | `secondaryIdentifier` | Enter exactly as shown on the passport. Format: Two uppercase letters followed by 13 digits (e.g., `DL1234567890123`). | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class must be 'IDENTITY' for KYC verification "primaryIdentifier": "J1234567", // Passport Number: One uppercase letter followed by 7 digits (e.g., 'J1234567') "secondaryIdentifier": "DL1234567890123", // File Number: Two uppercase letters followed by 13 digits (e.g., 'DL1234567890123') "type": "PASSPORT", // Document type must be 'PASSPORT' for Indian passports "country": "IND" // Country code must be 'IND' for India } } ``` ### Field Requirements * Must consist of one uppercase letter followed by 7 digits * Example: `J1234567` * Case sensitive: only uppercase letters are accepted * Enter exactly as shown on the passport * Must consist of two uppercase letters (typically the state code) followed by 13 digits * Example: `DL1234567890123` * Should be provided in the `secondaryIdentifier` field * Enter exactly as it appears on the passport * Given name and family name are required; middle name is optional * Names must match the passport exactly, including capitalization, special characters, and spaces * Include the display name exactly as shown on the passport *** ### Aadhaar (National ID) Aadhaar is a 12-digit unique identification number issued by the Unique Identification Authority of India (UIDAI). It serves as a proof of identity and address for Indian residents and is widely used for identity verification purposes. | Field Name | Field | Notes | | :------------ | :------------ | :------------------------------------------------------------------------------------------------------------------ | | Document Type | `type` | Must be `NATIONAL_ID` for Aadhaar. | | Country | `country` | Must be `IND` (India). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth as shown on the Aadhaar card. | | Name | `name` | Enter the full name exactly as shown on the Aadhaar card, including capitalization, special characters, and spaces. | | Field Name | Field | Notes | | :------------- | :------------------ | :--------------------------------------------------------------------------------------------------- | | Aadhaar Number | `primaryIdentifier` | Enter exactly as shown on the Aadhaar card. Format: 12 digits without dashes (e.g., `304365000000`). | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class must be 'IDENTITY' for KYC verification "primaryIdentifier": "304365000000", // Aadhaar Number: 12 digits without dashes "type": "NATIONAL_ID", // Document type must be 'NATIONAL_ID' for Aadhaar "country": "IND" // Country code must be 'IND' for India } } ``` **Sandbox Testing:** To test Aadhaar verification in the sandbox environment, use the number `304365000000`, which will return a successful (pass) result. ### Field Requirements * Must consist of exactly 12 digits * Example: `304365000000` * Do not include dashes or spaces * Enter exactly as shown on the Aadhaar card * Given name and family name are required; middle name is optional * Names must match the Aadhaar card exactly, including capitalization, special characters, and spaces * Include the display name exactly as shown on the Aadhaar card *** ### PAN (Permanent Account Number) PAN is a ten-character alphanumeric identifier issued by the Indian Income Tax Department. It is used for tracking financial transactions and serves as an important identity document. | Field Name | Field | Notes | | :------------ | :------------ | :------------------------------------------------------------------------------------------------------- | | Document Type | `type` | Must be `NATIONAL_ID` for PAN. | | Country | `country` | Must be `IND` (India). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth associated with the PAN. | | Name | `name` | Enter the full name exactly as registered with the PAN, including capitalization and special characters. | | Field Name | Field | Notes | | :--------- | :------------------ | :----------------------------------------------------------------------------------------------------- | | PAN Number | `primaryIdentifier` | Format: 5 uppercase letters + 4 digits + 1 uppercase letter (e.g., `AAAPL1234C`). Total 10 characters. | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class must be 'IDENTITY' for KYC verification "primaryIdentifier": "AAAPL1234C", // PAN Number: 5 letters + 4 digits + 1 letter (10 characters) "type": "NATIONAL_ID", // Document type must be 'NATIONAL_ID' for PAN "country": "IND" // Country code must be 'IND' for India } } ``` ### Field Requirements * Must be exactly 10 characters * First 5 characters are uppercase letters * Next 4 characters are digits * Last character is an uppercase letter * Example: `AAAPL1234C` * Enter exactly as shown on the PAN card * Given name and family name are required; middle name is optional * Names must match the PAN registration exactly, including capitalization and special characters *** ### Voter ID (EPIC) The Electors Photo Identity Card (EPIC) is issued by the Election Commission of India. It serves as a primary proof of identity and is widely accepted for identity verification. | Field Name | Field | Notes | | :------------ | :------------ | :----------------------------------------------------------------------------------------------------- | | Document Type | `type` | Must be `NATIONAL_ID` for Voter ID. | | Country | `country` | Must be `IND` (India). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth as shown on the Voter ID. | | Name | `name` | Enter the full name exactly as shown on the Voter ID, including capitalization and special characters. | | Field Name | Field | Notes | | :---------- | :------------------ | :------------------------------------------------------------------------------------------ | | EPIC Number | `primaryIdentifier` | Format: 3 uppercase letters followed by 7 digits (e.g., `ABC0000000`). Total 10 characters. | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class must be 'IDENTITY' for KYC verification "primaryIdentifier": "ABC0000000", // EPIC Number: 3 letters + 7 digits (10 characters) "type": "NATIONAL_ID", // Document type must be 'NATIONAL_ID' for Voter ID "country": "IND" // Country code must be 'IND' for India } } ``` ### Field Requirements * Must be exactly 10 characters * First 3 characters are uppercase letters * Last 7 characters are digits * Example: `ABC0000000` * Enter exactly as shown on the Voter ID card * Given name and family name are required; middle name is optional * Names must match the Voter ID exactly, including capitalization and special characters *** ### Driver's License Indian driver's licenses are issued by the Regional Transport Office (RTO) in each state. They contain a unique license number that encodes the state, RTO, and year of issue. | Field Name | Field | Notes | | :------------ | :------------ | :------------------------------------------------------------------------------------------------------------- | | Document Type | `type` | Must be `DRIVERS_LICENSE` for Indian driver's licenses. | | Country | `country` | Must be `IND` (India). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth as shown on the license. | | Name | `name` | Enter the full name exactly as shown on the license, including capitalization, special characters, and spaces. | | Field Name | Field | Notes | | :------------- | :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | License Number | `primaryIdentifier` | Format: 16 characters total. 2 letters (state code) + 2 digits (RTO code) + 4 digits (year) + 7 digits. May include a hyphen or space (e.g., `HR-0619850034761` or `HR06 19850034761`). | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class must be 'IDENTITY' for KYC verification "primaryIdentifier": "HR-0619850034761", // License Number: 16 characters (including hyphen or space) "type": "DRIVERS_LICENSE", // Document type must be 'DRIVERS_LICENSE' for Indian licenses "country": "IND" // Country code must be 'IND' for India } } ``` ### Field Requirements * Must be 16 characters long (including space or hyphen) * First 2 characters: uppercase letters representing the state code (e.g., `HR` for Haryana, `DL` for Delhi) * Next 2 characters: digits representing the RTO code * Next 4 characters: digits representing the year the license was issued * Last 7 characters: digits (0-9) * May include a hyphen or space separator (e.g., `HR-0619850034761` or `HR06 19850034761`) * Enter exactly as shown on the license * Given name and family name are required; middle name is optional * Names must match the driver's license exactly, including capitalization, special characters, and spaces *** ##### Key Guidelines for Indian Document Verification **Name Matching** * Ensure the name matches the document exactly, including capitalization, special characters, spaces, and diacritical marks. * Enter the full name as displayed on the document. **Country Code** * For all Indian documents, set the country code to `IND`. **Document Numbers** * **Aadhaar:** 12 digits without dashes or spaces (e.g., `304365000000`). * **PAN:** 5 uppercase letters + 4 digits + 1 uppercase letter (e.g., `AAAPL1234C`). * **Voter ID (EPIC):** 3 uppercase letters + 7 digits (e.g., `ABC0000000`). * **Driver's License:** 16 characters — state code + RTO code + year + 7 digits (e.g., `HR-0619850034761`). * **Passport:** 1 uppercase letter + 7 digits (e.g., `R1234567`). File number in `secondaryIdentifier`. * Incorrect or expired document numbers will result in verification failure. **Date of Birth** * Use the ISO date format (`YYYY-MM-DD`) for the date of birth. **Best Practices** * Provide all available optional fields to improve verification accuracy. * Always include `class: "IDENTITY"` on all identity documents. # International Documents Source: https://docs.frankieone.com/docs/international-documents-v2 The FrankieOne KYC v2 API supports some International documents for identity verification. This guide provides details on how to handle these documents effectively. ## Supported International Documents The FrankieOne KYC v2 API supports the following International documents: | Document | Code | | :---------- | :------------ | | National ID | `NATIONAL_ID` | | Passport | `PASSPORT` | *** ### International National ID Card (INE/IFE) International National ID Cards are official identification documents issued by the government that confirm an individual's identity. They include personal details such as the individual's name, date of birth and ID card number. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :---------------------------------------------------------------------------------------- | | Country | `country` | Must be set to the ISO-3166-alpha3 country code (e.g. `CHN`, `MEX`) | | Date of Birth | `dateOfBirth` | Format must be `YYYY-MM-DD` | | Document Type | `type` | Must be `NATIONAL_ID` | | Name | `name` | Must match the National ID exactly (Given name, Middle name, Family name, and any others) | | Field Name | Field | Notes | | :------------------- | :-------------------- | :------------------------------------------------------------------------------------------------------------------ | | Primary Identifier | `primaryIdentifier` | Enter the full ID number exactly as it appears on the document, including all leading zeros and special characters. | | Secondary Identifier | `secondaryIdentifier` | Optional. If provided, include any additional identifiers such as a laser code or file number. | **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", "documentId": "92de15f64-5717-4562-b3fc-2c963f6665a7", "primaryIdentifier": "000734130", // ID Number "secondaryIdentifier": "q12313124", // Laser Code or File Number when applicable "type": "NATIONAL_ID", "country": "CHN", }, "supplementaryData": { "type": "NATIONAL_ID", "homeCountryFullName": "张伟明", // Full name in Foreign characters when applicable "paternalFamilyName": "MENDOZA", // LATAM IDs when applicable "maternalFamilyName": "GARCIA" // LATAM IDs when applicable } } ``` **Name Handling Guidelines:** ```json theme={null} { "familyName": "ZHANG", // Family name in CAPS "givenName": "WEIMING" // Given and middle name can be combined } ``` ```json theme={null} { "document": { "supplementaryData": { "homeCountryFullName": "张伟明", // Full name in Chinese characters } } } ``` ```json theme={null} { "document": { "supplementaryData": { "paternalFamilyName": "MENDOZA", // Paternal family name "maternalFamilyName": "GARCIA" // Maternal family name } } } ``` ##### Important Considerations for National ID Please ensure the following: * Names must match exactly as they appear on the ID, including all components and order * Date of birth must be in the `YYYY-MM-DD` format * Country code must use the ISO-3166-alpha3 standard (e.g., `CHN`, `MEX`) * ID number must include all leading zeros and special characters exactly as shown on the document *** ### International Passports International passports are official travel documents issued by the government that confirm an individual's identity and citizenship. They include personal details such as the individual's name, date of birth and passport number. **Required Fields** | Field Name | Field | Notes | | :------------ | :------------ | :-------------------------------------------------------------------------------------------------------- | | Country | `country` | Must be the ISO-3166-alpha3 country code of passport issuance (e.g., `AUS`, `GBR`). | | Date of Birth | `dateOfBirth` | Format: `YYYY-MM-DD`. Must match the date of birth on the passport. | | Document Type | `type` | Must be `PASSPORT`. | | Name | `name` | Enter the full name exactly as it appears on the passport, including all given, middle, and family names. | | Field Name | Field | Notes | | :------------------- | :-------------------- | :----------------------------------------------------------------------------------------------------------- | | Primary Identifier | `primaryIdentifier` | Enter the complete passport number exactly as shown, including all leading zeros. | | Secondary Identifier | `secondaryIdentifier` | Optional. Include any additional identifiers such as a file number or laser code if present on the passport. | | Expiry Date | `expiryDate` | Must be in `YYYY-MM-DD` format if available. Ensure the passport is valid and not expired. | International passport numbers vary significantly by country in length and format. Our system supports alphanumeric characters with a length of up to 14 characters to accommodate a wide range of international standards. * **Length:** 1 to 14 characters. * **Format:** Alphanumeric (`[A-Za-z0-9]*`). No special characters are supported. * **Guideline:** Always enter the passport number exactly as it appears on the document, including any leading zeros. \[cite: 3459] **Example Document Structure** ```json theme={null} { "document": { "class": "IDENTITY", // Document class, always "IDENTITY" for passports "expiryDate": { "year": "1990", // Expiry year as four digits "month": "03", // Expiry month as two digits "day": "27", // Expiry day as two digits "unstructured": "1990-03-27", // Expiry date in ISO format (YYYY-MM-DD) "type": "GREGORIAN" // Calendar type, typically "GREGORIAN" }, "primaryIdentifier": "000734130", // Passport number, include all leading zeros exactly as shown "secondaryIdentifier": "q12313124", // Optional. File number, laser code, or other secondary identifier if present "type": "PASSPORT", // Document type, must be "PASSPORT" "country": "AUS", // Country of issuance, ISO-3166-alpha3 code (e.g., "AUS" for Australia) "supplementaryData": { "type": "PASSPORT", // Repeats document type for supplementary data "homeCountryFullName": "张伟明" // Full name in native script, if applicable (e.g., Chinese characters) } } } ``` ##### Passport Number Guidelines * Passport numbers are typically alphanumeric and 8–9 characters long, but formats vary by country. * Most do not include special characters, though some legacy documents may. * Always enter the passport number exactly as shown, including all leading zeros. ##### Common Validation Issues * Expired passports or invalid expiry dates * Incorrect country codes (must be ISO-3166-alpha3, e.g., `AUS`, `GBR`) * Name does not match the passport exactly (including all components and order) * Incorrect date formats (must be `YYYY-MM-DD`) ##### Best Practices for Name Handling * Use the Machine Readable Zone (MRZ) spelling if available. * Remove diacritical marks and convert names to uppercase. * Follow ICAO transliteration rules for special characters. * Enter all name components exactly as they appear on the passport. # Interpreting Workflows Source: https://docs.frankieone.com/docs/interpreting-workflows-v2 A developer's guide to parsing the workflowResult object, from the overall status down to the granular details of each check. ## Understanding the Workflow Response After executing a workflow, the API returns a comprehensive `workflowResult` object. This object is the key to understanding the outcome of every check performed. This guide provides a structured, top-down walkthrough of how to parse this response, explaining each key object from the final verdict down to the granular evidence. The examples in this guide refer to the following API response for workflow execution `01JZHEX5FQA4DJB0MMJFZR26JS`. Click to expand and see the full structure ```JSON theme={null} { "individual": { "entityId": "99f16410-2613-4181-8cf1-048625900013", "name": { "displayName": "MARY TESTFOURTEEN", "...": "..." }, "...": "..." }, "requestId": "01JZHEX0WX2QEM6EY139D5NNP1", "workflowResult": { "workflowExecutionId": "01JZHEX5FQA4DJB0MMJFZR26JS", "workflowExecutionState": "COMPLETED", "status": "PASS", "result": "PASS", "riskAssessment": { "riskLevel": "LOW", "riskScore": 12, "riskFactors": [ { "factor": "entity_type", "value": "INDIVIDUAL", "score": 2 }, { "factor": "entity_age", "value": "62", "score": 10 } ] }, "steps": { "passed": [ "START", "MATCHLIST", "KYC", "AML", "DECISION", "FINISH" ], "failed": [ "IDV" ], "order": [ "START", "MATCHLIST", "KYC", "IDV", "AML", "TOGGLE_MONITORING", "DECISION", "FINISH" ], "...": "..." }, "issues": [], "workflowStepResults": [ { "stepName": "KYC", "result": "MATCH", "processResults": [ { "processResultId": "01JZ4H0P59KGQR9DZCWZ6JQRY0", "class": "KYC", "objectType": "NAME", "result": "MATCH", "state": "COMPLETED", "systemStatus": "VALID", "providerResult": { "name": "con_testbed-docs", "source": "au-govid1-pp" }, "supplementaryData": { "type": "KYC_NAME", "matchStrengths": { "fullName": 75, "familyName": 75, "givenName": 75 } } } ], "summary": { "matchedRules": [ { "ruleName": "gov_id_only", "isVerified": true, "matchDetails": [ { "provider": "con_testbed-docs", "source": "au-govid1-pp", "attributesMatched": [ "dateOfBirth", "govId", "name" ] } ] } ] }, "...": "..." } ] } } ``` *** ## Part 1: The Overall Outcome (The Final Verdict) Start by examining the top-level fields of the `workflowResult` object. These provide the final, authoritative outcome of the entire workflow execution. | Field Name | Importance | Description | | :----------------------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `status` | ‼️ | **This is the most important field.** It represents the conclusive recommendation and accounts for any manual overrides. **Base your primary business logic on this value.** | | `workflowExecutionState` | ‼️ | This confirms the workflow’s technical status. It **`must beCOMPLETED`** for the `status` to be considered final. | | `result` | ⚠️ | This field holds the original, automated outcome of the workflow *before* any manual changes. It is useful for auditing. | | `issues` | ⚠️ | An array of problems that may require manual review. If the `status` is `REVIEW`, this array will contain the specific reasons why. | ### Workflow Execution States (`workflowExecutionState`) This field tells you if the workflow ran to completion. | State | Description | | :------------ | :-------------------------------------------------------------------- | | `COMPLETED` | The workflow executed successfully from start to finish. | | `IN_PROGRESS` | The workflow is still running. | | `ERROR` | The workflow encountered an unrecoverable error and could not finish. | | `TIMEOUT` | The workflow exceeded its maximum execution time. | | `CANCELED` | The workflow was manually canceled before completion. | | `TERMINATED` | The workflow was terminated by the system before completion. | ### When Each Execution State Occurs #### COMPLETED The workflow ran to completion. This is the expected state for most synchronous workflows. * **Next step:** Check `workflowResult.status` for the verification outcome (PASS, FAIL, REVIEW, etc.) #### IN\_PROGRESS The workflow is still executing and has not yet reached a terminal state. This occurs when: | Scenario | Example | | ------------------------------------ | ---------------------------------------------------- | | Workflow includes asynchronous steps | IDV document verification, biometric/liveness checks | | External provider is processing | Third-party identity verification pending | | Waiting for user action | Document upload or selfie capture in progress | **Handling IN\_PROGRESS responses:** 1. **Configure webhooks** (recommended) - Listen for completion events: * `RESULTS_RETRIEVED` - Verification results are ready * `FF_EXTERNAL_IDV_CHECK_COMPLETED` - IDV/biometric submission complete 2. **Poll for results** - Call `GET /v2/individuals/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}` to retrieve updated results 3. **Use the retrieve endpoint** - Call `/retrieve/{requestID}` with the `requestID` from the original response > **Note:** Biometric checks are asynchronous and can take up to 5 minutes to complete. Do not treat `IN_PROGRESS`\ > as a failure. #### ERROR An unrecoverable error occurred during workflow execution. Common causes: * Internal system error * Invalid workflow configuration * Data source connector failure **Recommended action:** Log the `workflowExecutionId` and retry the request. If persistent, contact\ [support@frankieone.com](mailto:support@frankieone.com). #### TIMEOUT The workflow exceeded the maximum allowed execution time. Common causes: * External data source unavailable or slow * Network connectivity issues * High system load **Recommended action:** Retry with exponential backoff. Check [FrankieOne Status](https://status.frankieone.com) for service availability. #### CANCELED The workflow was manually canceled before completion. This can occur when: * The request was explicitly canceled via API * A dependent process was terminated #### TERMINATED The workflow was forcefully stopped by the system. This may indicate: * System-level intervention * Resource limits exceeded * Security policy triggered **Recommended action:** Contact [help@frankieone.com](mailto:support@frankieone.com) with the `workflowExecutionId` to investigate. ### Workflow Statuses (`status` and `result`) This is the final recommendation of the workflow. | Status | Description | | :------------------------ | :--------------------------------------------------------------------------------------------- | | `PASS` | The entity successfully met the workflow’s criteria. | | `FAIL` | The entity did not meet the workflow’s criteria. | | `REVIEW` | The workflow produced results that require manual review. | | `CLEAR` | Often used for monitoring, indicates no negative information was found. | | `HIT` | Often used for monitoring, indicates negative information (e.g., a watchlist match) was found. | | `URGENT` | A critical issue was found (e.g., a sanctions match) that requires immediate attention. | | `COMPLETE` / `INCOMPLETE` | The workflow finished, but a pass/fail determination was not applicable. | ### Detecting Manual Overrides It’s crucial to know if a workflow’s result was changed by a person. When an operator manually changes the `status` (e.g., from `FAIL` to `PASS`), the following fields are populated: * `statusOverrideRequestId`: The unique ID of the override request. * `statusOverrideBy`: The user who performed the override. * `statusOverrideAt`: The timestamp of the override. **`To detect an override, check ifstatusOverrideRequestId exists and is not empty.`** *** ## Part 2: The Step-by-Step Breakdown (`workflowStepResults`) The `workflowStepResults` array is a log of each individual check, explaining *how* the overall `status` was reached. Each object in this array corresponds to a step configured in your workflow (e.g., KYC, AML, IDV). | Field Name | Description | | :--------------- | :-------------------------------------------------------------------------------------------------------------------- | | `stepName` | The name of the step (e.g., `KYC`, `AML`). | | `result` | The outcome of this specific step. See the table below for all possible values. | | `summary` | A concise, human-readable summary of the step’s outcome. For a KYC step, this includes which matching rules were met. | | `processResults` | An array of Process Result Objects (PROs) providing the granular evidence for this step’s result. | | `risk` | The risk assessment specific to this step, including the score it contributed to the overall risk. | ### Workflow Step Results (`result`) | Result | Applicable Steps | Description | | :-------------------------- | :------------------------ | :------------------------------------------------------------------------------------------------------------------ | | MATCH / NO\_MATCH / PARTIAL | KYC, IDV, VISA | The step produced a successful, unsuccessful, or partially successful match against data sources. | | CLEAR / HIT | AML, MATCHLIST, DUPLICATE | The step checked against a negative list (e.g., AML watchlist) and found no matches (CLEAR) or found a match (HIT). | | PASS / FAIL | DECISION, Manual KYC | The step completed and met (PASS) or did not meet (FAIL) its required binary criteria. | | COMPLETE / INCOMPLETE | START, FINISH, RISK | The step finished, but a pass/fail scenario was not applicable. | | SKIPPED | Any Step | The step was skipped because it was not required to run. | | MISSING\_DATA | Any Step | The step could not run because it requires additional data. | | ERROR | Any Step | The step encountered an unrecoverable technical error. | *** ## Part 3: The Granular Evidence (`processResults`) For the deepest level of detail, look inside a `workflowStepResult` at its `processResults` array. A **Process Result Object (PRO)** is the raw evidence from a single check against a single data source. | Field Name | Description | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `processResultId` | A unique identifier for this specific piece of evidence. | | `class` | The high-level category of the check. See the table below for details. | | `objectType` | The specific data element that was checked (e.g., `NAME`, `ADDRESS`, `DOCUMENT`). | | `result` | The outcome of this specific check (e.g., `MATCH`, `HIT`, `CLEAR`). | | `providerResult` | An object containing details from the downstream data provider, including the `source` of the data. | | `systemStatus` | The lifecycle status of this PRO (e.g., `VALID`, `STALE`, `MARKED_INVALID`). A `STALE` status means the underlying entity data has changed since this check was performed. | | `manualStatus` | If an operator has manually reviewed this specific PRO, their conclusion (e.g., `TRUE_POSITIVE`, `FALSE_POSITIVE`) is recorded here. | | `supplementaryData` | A rich, context-specific object containing detailed metrics, like match scores or extracted OCR data. | ### Process Result Classes (`class`) | Class | Description | | :---------- | :------------------------------------------------------------------------------------ | | `KYC` | An electronic Know Your Customer check against a data source. | | `IDV` | An Identity Verification check, typically involving biometrics and document analysis. | | `AML` | An Anti-Money Laundering screening against watchlists, sanctions, and PEP lists. | | `MATCHLIST` | A check against a custom internal or shared blocklist/allowlist. | | `DUPLICATE` | A check to see if the entity is a duplicate of an existing entity. | | `FRAUD` | A fraud check, often related to device, IP, or behavioral signals. | ## Best Practices for Integration * **`CheckworkflowExecutionState first`**: Always confirm the workflow is `COMPLETED` before trusting the `status`. * **`Automate based onstatus`**: Use the top-level `status` field for your primary business logic (e.g., approve account, flag for review). * **`Debug withworkflowStepResults`**: When you get an unexpected `FAIL` or `REVIEW`, loop through the `workflowStepResults` to find which `stepName` has a non-passing `result`. The `summary` and `processResults` within that step will tell you why. * **`Log theworkflowExecutionId`**: This ID is your key for auditing, support queries, and correlating results. ## Synchronous vs Asynchronous Workflows Workflow behavior depends on the types of checks configured in your workflow. ### Synchronous Workflows Workflows containing only synchronous steps return `COMPLETED` immediately with the final result. **Synchronous step types:** * KYC data source checks (government databases, credit bureaus) * AML/PEP/Sanctions screening * Watchlist checks * Duplicate detection **Example response:** ```json theme={null} { "workflowResult": { "workflowExecutionState": "COMPLETED", "workflowExecutionId": "wfe_abc123", "status": "PASS", "result": "PASS" } } Asynchronous Workflows Workflows containing asynchronous steps may return IN_PROGRESS initially. Asynchronous step types: - IDV (Identity Document Verification) - Biometric verification / Liveness detection - Manual review steps - Some third-party provider integrations Example response: { "workflowResult": { "workflowExecutionState": "IN_PROGRESS", "workflowExecutionId": "wfe_xyz789", "status": null } } Determining Your Workflow Type To check if your workflow includes asynchronous steps: 1. Call GET /v2/workflows to list your configured workflows 2. Review the step configuration with your Customer Success Manager 3. Test in sandbox environment to observe response behavior ``` # Introduction to FrankieOne & KYB Source: https://docs.frankieone.com/docs/introduction-to-kyb Discover the fundamentals of Know Your Business (KYB) and see how FrankieOne's unified platform empowers you to build trust, ensure compliance, and create seamless onboarding experiences for your business customers. ## The Cornerstone of Digital Trust In today's global and digital economy, establishing trust is paramount. Know Your Business (KYB) is the foundational process that enables organizations to verify the legitimacy of the companies they engage with, ensuring they are dealing with real, trustworthy entities. It is a critical framework for preventing corporate fraud, reducing exposure to financial crime, and creating lasting, trusted business relationships. Know Your Business (KYB) is the process of verifying and validating a business entity before entering into a financial or commercial relationship. It involves confirming the company’s registration, ownership structure, and overall legitimacy. A crucial part of KYB also includes identifying and verifying the key individuals who own or control the business, known as beneficial owners, ensuring full visibility of both the entity and the people behind it. A robust KYB strategy is a competitive advantage that protects your business, your customers, and your reputation. Its importance extends far beyond simple compliance. * **Mitigate Corporate Fraud:** Uncover shell companies and fraudulent structures to protect your organization from financial and reputational harm. * **Navigate Global Regulations:** Confidently meet requirements from AUSTRAC, FATF, FINCEN, and other global regulators. * **Meet AML/CTF Obligations:** Ensure the businesses you engage with are not used as conduits for illegal activity. * **Build and Maintain Customer Trust:** Demonstrating a strong commitment to security and compliance shows customers that you are a professional and trustworthy organization. The KYB process can be broken down into three essential stages that create a comprehensive compliance framework. Confirm core entity information, such as registered name, incorporation details, and business identifiers (e.g., ABN/ACN in Australia). Identify and verify ultimate beneficial owners (UBOs) to ensure real ownership is disclosed, eliminating the risk of hidden or proxy structures. Evaluate the business based on jurisdiction, industry, and structure. Screen both the entity and its associated individuals against sanctions, PEP lists, and adverse media. ## How FrankieOne Delivers a Unified Solution FrankieOne replaces complexity with a single, intelligent platform. We provide the infrastructure to connect to global business registries and compliance tools through one API and one unified back-office portal. * **Effortless Global Onboarding:** Integrate once and gain access to business registries and corporate data across multiple jurisdictions. * **Automated and Risk-Based Workflows:** Automate data collection and verification to eliminate manual errors and accelerate onboarding. Configure dynamic, risk-based workflows that automatically escalate high-risk entities for enhanced due diligence. * **Always-On Compliance:** FrankieOne is a fully managed solution that stays current with the latest regulatory requirements, significantly reducing your compliance burden. ## Our Unified KYB Product Suite FrankieOne offers a comprehensive suite of products designed to work together, providing complete coverage across the entire KYB and fraud prevention lifecycle. Rapidly validate entity details against authoritative sources worldwide. Identify directors, shareholders, and ultimate beneficial owners to ensure complete visibility. Screen businesses and associated individuals against global watchlists, PEP lists, and adverse media. Evaluate risk holistically by considering jurisdiction, industry, and ownership structure. Ready to Get Started? FrankieOne's team of compliance and integration experts are ready to help you design and deploy a world-class KYB solution. [Contact us today](https://www.frankieone.com/contactus) or dive into our [Core Product Deep Dive](/docs/core-product-deep-dive) to learn more. # AML Screening & Monitoring Source: https://docs.frankieone.com/docs/kyb/anti-money-laundering Learn how FrankieOne's AML solution helps you screen against global watchlists, manage risk, and maintain ongoing compliance. ## What is AML Screening? Anti-Money Laundering (AML) screening is a critical compliance process for identifying individuals and organizations with connections to financial crime. It involves checking customer data against global watchlists to detect risks related to money laundering, terrorism financing, sanctions violations, and political exposure. FrankieOne's solution streamlines this process, from initial real-time screening at onboarding to continuous, automated monitoring throughout the customer lifecycle. *** ## How AML Screening Works Our AML capabilities are integrated directly into the FrankieOne workflow engine. First, you [/create](/api-reference/organizations/create-an-organization-entity) an `organization` entity with an `organizationToken` recorded from a lookup of the organization or you can use and `entityId` of an existing entity on which a data-fetch workflow like `ownership` or `profile` has been run using the [/execute](/api-reference/organization-workflows/execute-a-workflow-with-organization-details) endpoint. You then execute a workflow that has been configured with an **AML Step**. Our platform takes the entity's details and screens them against our connected data sources. The workflow returns a clear result for the AML step—typically **`CLEAR`** or **`HIT`**. A `HIT` generates detailed Process Result Objects (PROs) and `issues` for any potential matches, allowing your team to investigate and classify the results. *** ## What We Screen For Our AML solution checks against a wide array of global sources to provide a comprehensive risk profile. * **Politically Exposed Persons (PEPs):** Identify individuals who hold prominent public functions and may present a higher risk for bribery or corruption. * **Sanctions Lists:** Screen against lists of individuals, entities, and countries subject to economic or trade sanctions by governments and international bodies. * **Adverse Media:** Scan global news sources for negative information linked to an individual that may indicate an elevated risk. * **Other Regulatory & Law Enforcement Watchlists:** Check against a wide range of official lists to identify potential bad actors. ### Intelligent Matching To increase accuracy and reduce false positives, our system uses sophisticated matching logic: * **Name Matching**: Checks against the entity's full name, as well as known aliases. * **Contextual Filtering**: Uses the entity's **date of birth**, **nationality**, and **country of residence** to filter out irrelevant matches from the screening results. *** ## Classifying AML Hits When an AML screening results in a `HIT`, your compliance team needs to review the potential matches and classify them. This is a critical step in managing your AML risk. You can update the status of one or more AML-related Process Result Objects (PROs) using the update [/results/aml](/api-reference/organization-results/update-the-status-of-aml-process-results) API. **Request:** ```http theme={null} PATCH /v2/organizations/{entityId}/results/aml ``` **Request Body:** ```json theme={null} { "processResults": [ "pro_01J285FC7DH5G113KF109RJHSD", "pro_01J285FC6MDNE7SZPVS8D3GC7S" ], "manualStatus": "FALSE_POSITIVE", "comment": { "text": "Reviewed by compliance officer. Matches are for a different individual with a similar name." } } ``` ### Manual Status Options (`manualStatus`) When classifying a hit, you can set one of the following statuses: | Status | Description | | :--------------------- | :-------------------------------------------------------------------------------------------------------------------- | | `FALSE_POSITIVE` | The match is not the same person you are onboarding. | | `TRUE_POSITIVE` | The match is the same person, but a final decision has not been made. The hit remains unresolved. | | `TRUE_POSITIVE_ACCEPT` | The match is the same person, and your organization has decided to accept the risk and proceed with the relationship. | | `TRUE_POSITIVE_REJECT` | The match is the same person, and your organization has decided to reject the relationship. | | `UNKNOWN` | It is unclear if the match is the same person. The hit remains unresolved. | | `UNKNOWN_ACCEPT` | It is unclear if the match is the same person, but your organization has decided to accept the risk. | | `UNKNOWN_REJECT` | It is unclear if the match is the same person, and your organization has decided to reject the relationship. | ### Updating the Workflow Result After Classification After classifying hits, the workflow needs to be updated so the entity's compliance status reflects the classifications. For example, a workflow that initially resulted in a `REVIEW` status due to unresolved hits may change to `PASS` if all hits are classified as `FALSE_POSITIVE`. There are two ways to do this: #### Re-evaluate the Workflow Call the **evaluate** endpoint. This re-runs the decision and risk assessment steps using existing check results. It does **not** trigger new calls to external AML providers, so there is no additional provider cost. ```http theme={null} POST /v2/organizations/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/evaluate ``` #### Re-run the Workflow Call the **execute** endpoint to re-run the full workflow. This will contact external providers again (e.g., run a new AML search), which incurs additional cost and resets the aging window. ```http theme={null} POST /v2/organizations/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/execute ``` Use `/evaluate` when only the decision needs updating based on changed classifications — it is faster, cheaper, and does not call external providers. Use `/execute` if the entity's underlying data has changed and fresh provider results are needed, or if existing check results have expired beyond the aging window. *** ## Additional Resources * [Interpreting Workflow Results](/docs/kyb/interpreting-workflows-v2) * [Handling AML Results](/docs/kyb/anti-money-laundering-results) # Interpreting AML Screening Results Source: https://docs.frankieone.com/docs/kyb/anti-money-laundering-results A detailed guide to understanding the results of an AML check, from the high-level summary down to the details of each watchlist match. ## How to Read an AML Result When you execute a workflow containing an AML step, the API response provides a rich set of data to help you understand the outcome. This guide provides a structured, "top-down" walkthrough of how to parse the `workflowResult` object. The examples in this guide refer to a workflow execution response where Adverse Media matches were found. Click to expand and see the full structure. ```json theme={null} { "requestId": "01HN9XHZN6MGXM9JXG50K59Q85", "workflowResult": { "workflowExecutionId": "01K55F466SQBT41KMQ7PWGEEN3", "workflowExecutionState": "COMPLETED", "status": "REVIEW", "result": "REVIEW", "riskAssessment": { "riskLevel": "HIGH", "riskScore": 100, "riskFactors": [ { "createdAt": "2025-09-15T01:16:45.849033Z", "description": "Has adverse media hits", "factor": "has_adverse_media", "riskFactorId": "b26d1a21-57f9-46ed-afc9-f7025980ad9c", "score": 10, "status": "VALID", "updatedAt": "2025-09-15T01:16:45.849033Z", "updatedRequestId": "01HN9XHZN6MGXM9JXG50K59Q85" } ] }, "issues": [ { "category": "AML", "createdAt": "2025-09-15T01:16:45.949556Z", "issue": "MEDIA", "issueId": "9e3b73c3-5050-4f42-bc4b-aa6c05a711b8", "severity": "WARNING", "workflowExecutionId": "01K55F466SQBT41KMQ7PWGEEN3" } ], "workflowStepResults": [ { "stepName": "AML", "result": "HIT", "summary": { "numUnresolvedAdverseMedia": 2, "numUnresolvedPEP": 0, "numUnresolvedSanction": 0, "numUnresolvedWatchlist": 0, "providerSummaries": [ ... ], "stepName": "AML", "totalFalsePositives": 0, "totalHits": 2, "totalTruePositives": 0, "totalUnknown": 0, "totalUnresolved": 2 }, "processResults": [ { "processResultId": "pro_01J...", "result": "HIT", "class": "AML", "supplementaryData": { "type": "AML", "matchData": { "name": "Test Org" }, "mediaData": [ { "additionalData": [ { "key": "aml.case_id", "value": "..." }, { "key": "aml.search_entity_id", "value": "..." } ], "isCurrent": true, "snippet": "...", "source": "...", "sourceDate": "...", "title": "...", "url": "..." } ], "manualStatus": "UNRESOLVED" } } ] } ] } } ``` *** ## Part 1: The Overall Outcome (Final Verdict) Always start by checking the top-level fields of the `workflowResult` object. These give you the final, authoritative outcome. | Field | Importance | Description | | :--------------------------- | :--------- | :---------------------------------------------------------------------------------------------------------------------- | | **`status`** | ‼️ | The conclusive recommendation (e.g., `PASS`, `FAIL`, `REVIEW`). **Base your primary business logic on this value.** | | **`workflowExecutionState`** | ‼️ | Confirms the workflow's technical status. **Must be `COMPLETED`**. | | **`issues`** | ⚠️ | An array of problems that require manual review. If `status` is `REVIEW`, this array contains the specific reasons why. | | **`riskAssessment`** | ⚠️ | The final risk profile of the entity, including the `riskLevel` and `riskScore`. | In the example, the `status` is `REVIEW`, which is directly caused by the `issues` array containing a `MEDIA` issue. ### Understanding AML Issues When the AML step finds a potential match, it generates an `issue` object. This is what typically drives the overall workflow `status` to `REVIEW`. | Category | Issue | Severity | Trigger Condition | | :------- | :---------- | :-------- | :---------------------------------------------------------- | | `AML` | `PEP` | `WARNING` | At least one valid Process Result contains `pepData`. | | `AML` | `SANCTIONS` | `WARNING` | At least one valid Process Result contains `sanctionData`. | | `AML` | `MEDIA` | `WARNING` | At least one valid Process Result contains `mediaData`. | | `AML` | `WATCHLIST` | `WARNING` | At least one valid Process Result contains `watchlistData`. | *** ## Part 2: The AML Step Result (`workflowStepResults`) Next, drill down into the `workflowStepResults` array and find the object where `stepName` is **`AML`**. This object contains the specific results of the screening. | Key Field | Description | | :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`result`** | The most important field for the step. A `result` of **`HIT`** means at least one potential match was found and requires review. A `result` of **`CLEAR`** means no matches were found. | | **`summary`** | An aggregated summary of the screening results, broken down by match type. | | **`processResults`** | An array containing the detailed evidence for each individual watchlist match. | ### The AML Summary Object The `summary` object gives you a quick, quantitative overview of the screening results. ```json theme={null} "summary": { "numUnresolvedAdverseMedia": 2, "numUnresolvedPEP": 0, "numUnresolvedSanction": 0, "numUnresolvedWatchlist": 0, "providerSummaries": [ { ... } ], "stepName": "AML", "totalFalsePositives": 0, "totalHits": 2, "totalTruePositives": 0, "totalUnknown": 0, "totalUnresolved": 2 } ``` This summary immediately tells you the scale and severity of the results. For example, `numUnresolvedSanction` highlights if a high-risk sanctions match is present and needs immediate attention. *** ## Part 3: The Process Results (The Raw Evidence) When an AML step returns a `HIT`, the `processResults` array will contain one or more Process Result Objects (PROs), each with `class: "AML"`. Each PRO represents a single potential match from a watchlist and contains all the data you need for your investigation. ### Anatomy of an AML PRO The most critical part of an AML PRO is the **`supplementaryData`** object. This is where you will find the details of the matched entity. | `supplementaryData` Field | Description | | :------------------------ | :------------------------------------------------------------------------------------------------------------------ | | **`matchData`** | Core information about the matched profile (name, date of birth, countries of association). | | **`pepData`** | If the match is a Politically Exposed Person, this array contains details about their position, level, and country. | | **`sanctionData`** | If the match is on a Sanctions list, this array contains details about the sanction, its source, and the reason. | | **`watchlistData`** | This array contains details for matches on other regulatory or law enforcement watchlists. | | **`mediaData`** | If the match is from Adverse Media, this array provides snippets and links to relevant news articles. | | **`referenceDocs`** | An array of URLs to source documents for further evidence. | This example shows a `processResult` for a `HIT` where the organization has adverse media hits. The `mediaData` array is populated with the specific details of the adverse media matches. ```json theme={null} { "processResultId": "pro_01J...", "result": "HIT", "class": "AML", "supplementaryData": { "type": "AML", "matchData": { "name": "Test Org" }, "mediaData": [ { "additionalData": [ { "key": "aml.case_id", "value": "..." }, { "key": "aml.search_entity_id", "value": "..." } ], "isCurrent": true, "snippet": "...", "source": "...", "sourceDate": "...", "title": "...", "url": "..." } ], "manualStatus": "UNRESOLVED" } } ``` *** ## Part 4: Next Steps - Classifying Hits and Re-evaluating After your compliance team reviews the evidence in the `processResults`, they must classify each hit (e.g., as a `FALSE_POSITIVE`). This is done by updating the `manualStatus` of each PRO. > **For a detailed guide on how to perform this action via the API, please see our **[AML Screening & Monitoring Documentation](/docs/kyb/anti-money-laundering)**.** ### Updating the Workflow Result Once all hits have been classified, the workflow needs to be reevaluated so the entity's risk and workflow status reflect the classifications. This is critical for two reasons: 1. **To Update the `status`**: The overall `workflowResult.status` will only change from `REVIEW` to `PASS` or `CLEAR` after the workflow is re-evaluated or re-run and the AML step confirms that no unresolved hits remain. 2. **To Clear `issues`**: The AML step will reassess the issues. If all PROs that previously caused a `MEDIA` issue are now classified as `FALSE_POSITIVE`, the issue will be cleared from the workflow result. There are two ways to trigger this update: #### Re-evaluate the Workflow Call the **evaluate** endpoint. This re-runs the decision and risk assessment steps using existing check results, without triggering new calls to external providers. This ensures the entity's risk and workflow status are updated and the audit trail is accurate. ```http theme={null} POST /v2/organizations/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/evaluate ``` #### Re-run the Workflow Call the **execute** endpoint to re-run the full workflow. Unless existing results are within the aging window, this will contact external providers again (e.g., run a new AML search), which incurs additional cost and resets the aging window. ```http theme={null} POST /v2/organizations/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/execute ``` Use `/evaluate` when only the decision needs updating based on changed classifications — it is faster, cheaper, and does not call external providers. It re-assesses risk using the entity's existing check results, but does not refresh them. Use `/execute` when the entity's underlying data has changed, or when you need fresh provider results because existing checks have expired beyond the aging window. ### Error Handling | Scenario | Response | Recommended Action | | :--------------------------------- | :------------------------------------------ | :------------------------------------------------------- | | No prior workflow execution exists | `400` - "No prior workflow execution found" | Call `/execute` first to run the initial workflow | | Entity state is `DUPLICATE` | `400` | Call evaluate on the surviving entity, not the duplicate | | Entity state is `BLOCKLISTED` | `403` | Resolve the blocklist status first | # Business Onboarding Source: https://docs.frankieone.com/docs/kyb/business-onboarding Business Onboarding is a hosted flow that guides applicants through providing the information needed to verify an organisation. You generate a time‑limited URL and redirect your user to complete the steps. Business Onboarding is not enabled by default. Contact FrankieOne to enable it for your tenant and to provision your onboarding flow configuration (`flowId`). *** ## How it works * **Generate a hosted URL** using your `flowId`. * **Redirect** the applicant’s browser to the returned URL. * The applicant completes the onboarding pages and submits. * Verification URL for identified owners can be sent from the flow. * **Redirect after completion** can be configured (CTA target on the End page). *** ## Generate a hosted URL Use the Hosted URL endpoint to create a URL for a new onboarding session. ```http HTTP theme={null} POST /v2/organizations/hostedUrl Host: api.uat.frankie.one ``` ### Headers * `api_key`: Your FrankieOne API key * `X-Frankie-CustomerID`: Your Customer ID * `X-Frankie-CustomerChildID`: Child tenant identifier ### Request body ```json JSON theme={null} { "flowId": "example-flow-id" } ``` ### Sample request (UAT) ```bash theme={null} curl --request POST \ --url https://api.uat.frankie.one/v2/organizations/hostedUrl \ --header 'api_key: ' \ --header 'X-Frankie-CustomerID: ' \ --header 'Content-Type: application/json' \ --data '{ "flowId": "" }' ``` ### Sample response ```json JSON theme={null} { "url": "https://verify.uat.frankie.one/v2/?t=shortToken", "urlExpiry": "2025-01-01T00:00:00.000Z", "requestId": "01HN9XHZN6MGXM9JXG50K59Q85" } ``` *** ## Pages in the flow Below are the standard pages included in the hosted flow. Availability and fields depend on your configured `flowId` and the selected organisation type. * **Start page** Intro screen to begin a new application. Business onboarding start page * **Applicant details** Captures the applicant’s name, role, contact details, and consent. The Terms & Conditions checkbox message can be customised. Applicant details page * **Lookup** Search by organisation name, ABN or ACN. On submission, the flow runs an **Ownership** query on the selected organisation to determine structure and required next steps. Organisation lookup page * **Additional details** Fully customisable fields (labels, required/optional) for business context, e.g. source of wealth/capital, industry, purpose, contact details. Additional details page * **Organisation details** Prefilled from registry/profile data where available. Address fields may require confirmation/editing depending on data availability. Applicable to: sole trader, company, and trust organisations. Organisation details page * **Document upload** Fully customisable document groups and requirements. For trust organisations, the flow adds defaults for Trust Deed, Deeds of Variation, and Register of Unit Holders. Applicable to: company and trust organisations. Sole trader does not include this step. Document upload page * **Owners** Displays identified significant owners and directors for confirmation and contact details capture. Applicable to: sole trader and company. Owners page * **Review** Summary of all captured details and documents prior to submission. Review page * **End page** Confirmation page. The primary CTA can redirect to a configurable URL (e.g. return to your product). End page ## Branding and UI customisation * **Logo**: Replace with your brand logo. * **Buttons**: Configure colour and border radius. * **Copy**: Customise explanatory text and T\&C/consent copy. * **Fields**: Add, remove, or reorder fields on Additional Details and Document Upload pages, including validations and optionality. * **Redirects**: Configure the destination for the End page CTA. Work with FrankieOne to define these in your flow configuration. # Core Product Deep Dive Source: https://docs.frankieone.com/docs/kyb/core-product-deep-dive A detailed exploration of the powerful features within the FrankieOne KYB platform. Understand how each component maps to our API to create a secure, efficient, and compliant business verification workflow. ## Available Features These features are available today in the FrankieOne KYB platform. **What it is:** This is our core business verification engine. It validates a company’s details directly against authoritative registries worldwide, including ABN/ACN in Australia. It confirms the business name, incorporation status, and registration identifiers. **Key Benefits:** * **Ensure Counterparties are Legitimate:** Validate data against official sources to reduce the risk of fraud. * **Simplify Compliance Checks:** Automate registry lookups to streamline your due diligence process. **Mapped to API:** This information is found within the `organization.details` object, specifically in the `registrationDetails` array, which includes fields like `registeredName`, `registrationNumber`, and `status`. **What it is:** This feature identifies directors, shareholders, and Ultimate Beneficial Owners (UBOs) to uncover who truly controls a business. It allows you to build transparent ownership structures across jurisdictions. **Key Benefits:** * **Reveal Hidden Ownership:** Reduce exposure to shell companies and complex ownership structures. * **Strengthen AML/CTF Compliance:** Meet FATF requirements for identifying beneficial owners. * **Gain Visibility for Due Diligence:** Identify key individuals who may require further screening (e.g., PEP or sanctions checks). **Mapped to API:** Ownership data is structured within the `organization` object: `officials`: An array listing directors and other key roles. `shareholders`: An array detailing direct shareholders. `ultimateBeneficialOwners`: An array identifying the UBOs as determined by the configured ownership policy. `linkedIndividuals`: Contains the full entity details for individuals linked to the organization. **What it is:** This feature screens businesses and their associated individuals against thousands of global watchlists, including Sanctions lists, Politically Exposed Persons (PEPs), and Adverse Media from reputable global sources. **Key Benefits:** * **Detect High-Risk Counterparties:** Identify potential risks before entering into a business relationship. * **Support Global Compliance:** Ensure you meet screening requirements across multiple jurisdictions. * **Automate Alerts:** Configure ongoing monitoring to be alerted to any changes in a customer's status. **Mapped to API:** This is performed during workflow execution. Results are returned as Process-Result-Object instances with class: AML. The supplementaryData object for these results contains detailed match information, including pepData, sanctionData, and mediaData. **What it is:** The Risk Assessment engine assigns a customisable risk score to each business entity. It analyses multiple data points in real-time, such as the business's jurisdiction, industry, and ownership complexity, to produce a holistic risk profile based on your configured rules. **Key Benefits:** * **Focus Resources on High-Risk Entities:** Build workflows that align with your risk appetite. * **Improve Decision-Making:** Use structured, comparable scoring to automate and streamline your review process. * **Auditable Compliance:** Provides a clear, data-driven trail explaining why an entity was assigned a specific risk level. **Mapped to API:** The `workflowResult` of an execution contains a `riskAssessment` object. This includes the overall `riskScore` and `riskLevel` (e.g., `LOW`, `MEDIUM`, `HIGH`), as well as a breakdown of the `riskFactors` that contributed to the score. **What it is:** The Trust Analyzer extracts and analyses trust structures from trust deeds during KYB. It ingests a trust deed PDF, classifies the trust type, extracts the named parties (trustees, settlors, beneficiaries, appointors, protectors, SMSF members), normalises their roles, and returns structured, audit-ready output with references back to the source document. Available through both the Portal and the API, for Australian trust deeds; international coverage is not yet supported. **Key Benefits:** * **Faster Reviews:** Convert unstructured deeds into structured data to cut manual review time and training effort. * **Enable Automation:** Consistent, structured output lets you automate more of a complex KYB process. * **Complete Picture:** Resolve complex entity types alongside standard KYB verification, AML, and KYC in one place. **Common Use Cases:** Onboarding trusts, or businesses that hold assets through trusts, at scale without adding compliance headcount. **Mapped to API:** Runs as the `GLB-Trust-Analysis` workflow. Pass the trust deed's `documentId` via `executionVariables` on execute, then retrieve the extracted trust structure and confirm it. See the [Trust Analyzer guide](/docs/kyb/trust-analyzer). ## Coming Soon: The Future of Compliance We are continuously innovating to address the next generation of compliance and fraud challenges. The following capabilities are in active development and will be available in upcoming releases. **What it is:** This feature allows you to continuously track changes related to a business's registration status, ownership structure, or other key risk indicators over time. You receive alerts when key details shift, ensuring continuous compliance throughout the business lifecycle. **Key Benefits:** * **Maintain Up-to-Date Due Diligence:** Reduce the risk of missing critical changes that impact compliance. * **Support Regulatory Obligations:** Fulfill requirements for ongoing monitoring without manual effort. * **Proactive Risk Management:** Be alerted when a supplier or customer changes ownership to a sanctioned or high-risk entity. **Common Use Cases:** For businesses that want to stay up to date with changes to their customers, or who want to eliminate costly refresh processes and introduce a real-time, as needed, customer maintenance cycle. # Error Handling Source: https://docs.frankieone.com/docs/kyb/error-handling The FrankieOne API uses a standardized error format to ensure that you can reliably handle issues that arise from bad requests, server problems, or invalid data. All non-2xx responses will return a consistent JSON error object. This guide explains the structure of the error object, provides a full list of error codes, and offers practical advice on how to handle these errors in your frontend application. *** ## The Error Object All errors returned from the FrankieOne API are wrapped in a standard `ErrorObject`. | Attribute | Type | Description | | :-------------------- | :----- | :------------------------------------------------------------------------------------------------------------------- | | errorCode | string | A unique code in the format `PREFIX-NUMBER` that identifies the error. | | errorMsg | string | A human-readable message summarizing the error. | | details | array | An array of issue objects providing specific context about what went wrong. | | details.issue | string | A detailed description of the specific issue. | | details.issueLocation | string | The location in the request payload, path, or header where the issue occurred (e.g., `body.individual.dateOfBirth`). | | requestId | string | The unique ID for the API request, which should be logged and provided to support if you need assistance. | *** ### Example Error Object Here is an example of an error returned when an invalid entity ID is provided in the request path. ```json theme={null} { "details": [ { "issue": "entity with ID '019930f5-6d09-739e-82ca-e597bf0ed98c' does not exist" } ], "errorCode": "VAL-404", "errorMsg": "Not Found", "requestId": "01K4VRM3WDE0X6MMP83HCDEWHC" } ``` *** ## Understanding Error Codes The `errorCode` is a combination of a prefix (the Issue Location) and a number. This structure helps you quickly identify the source of the problem. ### Issue Location Codes (Prefix) | Prefix | Description | | :----- | :------------------------------------------------------------------------------------------------------------------------- | | API | Errors in your API message, such as an incorrectly constructed URL or method. | | AUTH | Authorization or security-related errors, like a missing or invalid API key. | | VAL | API data validation errors. The details array will specify which fields are invalid. | | ENT | Errors related directly to Entity functions (e.g., an entity not found). | | DOC | Errors related directly to Document functions. | | CHECK | Errors related to Check/Verify functions. Indicates a problem with performing a check, not the result of the check itself. | | SYS | System-level errors on the FrankieOne side. These may be temporary. | | CODE | Unexpected errors detected in the code. Please contact support if you see these. | | ADMIN | Admin API errors. Please contact developer support if you receive one. | *** ## Frontend Orchestration & Handling Errors A robust frontend application should interpret the HTTP status code and the errorCode to present the user with a clear and helpful message. ### 400 - Bad Request (VAL-xxxx) This is the most common error category. It means the user has provided invalid or incomplete data. You should validate the request parameters and body and retry the API. Your frontend should parse the `details` array to provide specific feedback. **Example Response:** ```json theme={null} { "details": [ { "issue": "request body has an error: registrationDetails value must be an array", "issueLocation": "Request", "issueType": "Bad Request" } ], "errorCode": "VAL-400", "errorMsg": "Bad Request", "requestId": "01K4VSB88WT4QG03MYCZJ9AEC4" } ``` **Frontend Action:** * Iterate through the `details` array. * For each issue, use the `issueLocation` to find the corresponding input field in your form. * Display the issue message directly below that field. This provides targeted, inline validation feedback to the user so they can easily correct their mistakes. *** ### 404 - Not Found (API-1010) This means the resource you requested (like an entityId or workflowExecutionId) does not exist. You should validate the request parameters and retry the API. #### Scenario: Your application tries to fetch results for a workflow that has been deleted or whose ID is incorrect. **Example Response:** ```json theme={null} { "errorCode": "API-1010", "errorMsg": "Requested resource is not found", "details": [ { "issue": "The specified resource '01BFJA617JMJXEW6G7TDDXNSHX' of type 'entity' does not exist", "issueLocation": "path" } ], "requestId": "01BFJA617JMJXEW6G7TDDXNSHX" } ``` **Frontend Action:** * Check for the 404 status code. * Redirect the user to a "Not Found" page or display a clear message like "We could not find the record you were looking for. Please check the ID or start a new search." * Avoid showing a generic "An error occurred" message, as this is a specific and actionable state. *** ### 5xx - Server & System Errors (SYS-xxxx) These errors indicate a problem on FrankieOne's side. The issue may be temporary. You can retry the API after a short delay. #### Scenario: A service provider required for a check is temporarily unavailable. **Example Response:** ```json theme={null} { "errorCode": "SYS-0007", "errorMsg": "No service providers available/configured. Contact developer support", "httpStatusCode": 503, "details": [ { "issue": "The service is temporarily unavailable", "issueLocation": "server" } ], "requestId": "01GVEDZ0C1Q9NWQ699DBBKPE4Y" } ``` **Frontend Action:** * Check for any 5xx status code (500, 503, etc.). * Display a generic, user-friendly message, such as: "We're sorry, something went wrong on our end. Please try again in a few moments." * Do not display the technical `errorMsg` to the user. * You may implement a retry mechanism with exponential backoff for 503 errors, as these are often transient. * Log the full error response, including the `requestId`, so you can report it to support if the issue persists. # Executing a Workflow Source: https://docs.frankieone.com/docs/kyb/executing-workflows A step-by-step guide to executing workflows and interpreting the results. ## Overview Executing a workflow is the core action in the FrankieOne platform. It takes an `entityId` and runs it through a pre-configured series of steps (e.g., organization data collection, ownership insights, etc.) to return a result. This is the central mechanism for fetching organization details, assessing risk and making onboarding decisions. This guide covers the primary methods for executing a workflow and provides a high-level overview of how to handle the response. *** ## Workflow Execution Patterns There are two primary patterns for executing a workflow, depending on whether the organization already exists in your system. ### 1. Execute a workflow using organizationToken or organization registration details If you have searched for a business and retrieved its `organizationToken`, you can execute a workflow using that token. Alternatively, if you already know the business's registration number and type, you can execute a workflow directly with those details. This approach removes the need for a separate “create organization” step and, if an organization entity with the same registration number and type already exists in our system, we run the workflow against the existing entity—preventing the creation of duplicate entities. **Use Cases:** * Onboarding a new business for the first time. ### 2. Execute for an Existing Entity If you have already created an `organization` and have their `entityId`, or have run a workflow and have the `entityId` of the organization, you can execute a workflow against them at any time. **Use Cases:** * Re-running a workflow to re-assess risks. * Running a workflow for an existing entity post onboarding. * Performing periodic or event-driven reviews. You send a `POST` request to the `/execute` endpoint for a specific entity and workflow. This tells FrankieOne to initiate the workflow. The API response will have a status of `202 Accepted` and contain the `workflowExecutionId` which can then be used to get the results of the workflow. You can retrieve the workflow result by making a `GET` request to the `/executions/{workflowExecutionId}` endpoint. The API response will have a status of `200 OK` and contain the `workflowResult` object. ### 3. Re-evaluate an Existing Entity If an entity has already been through a workflow and you need to update its risk and workflow status, for example, after classifying AML hits or resolving duplicates, you should call the **evaluate** endpoint instead of executing the workflow again. The evaluate endpoint re-runs the decision and risk assessment steps using existing check results. It does **not** call external providers (e.g., CreditorWatch), which means: * **No additional provider cost** - external data fetches are skipped entirely. * **Faster processing** - only local computation steps are run. **Use Cases:** * Updating the workflow result after classifying AML hits. * Re-assessing risk after resolving duplicate entities. * Recalculating the decision after a risk factor override. **When to use Execute instead:** If the entity's underlying data has changed and you need fresh provider data, or if existing check results have expired beyond the ageing window, use `/execute`. *** ## Implementation Guide ### Prerequisites Before executing a workflow, ensure you have: * The `organizationToken` or `registrationNumber` and `registrationType` of the organization. * If the organization already exists in the system, the `entityId` for the organization. * The `serviceName` of the Service Profile they are being assessed against (e.g., `DEFAULT`). * The `workflowName` of the specific workflow you want to run (e.g., `GLB-Organization-Profile`). ### Step 1: Initiate the Workflow #### Request Choose the endpoint that matches your execution pattern. ##### With Organization details: Make a `POST` request to the endpoint, providing the `organizationToken` from the search response or `registrationNumber`, `registrationType` and `country` in the request body. ```bash Request - Execute Workflow with registration details theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/workflows/GLB-Organization-Profile/execute' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "organization": { "details": { "registrationDetails": [ { "number": "61623506892", "type": "ABN", "country": "AUS" } ] } } }' ``` ```bash Request - Execute Workflow with organizationToken theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/workflows/organization_profile/execute' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "organizationToken": "eyJ2ZXIiOiIxLjAiLCJ0cyI6IjIwMjUtMDgtMDdUMDY6NTk6NTQuNDAzMzcxNDZaIiwib24iOlt7InJuIjoiNjE2MjM1MDY4OTIiLCJyYSI6IkFCTiJ9LHsicm4iOiI2MjM1MDY4OTIiLCJyYSI6IkFDTiJ9XSwicHJvdiI6ImNyZWRpdG9yd2F0Y2giLCJjbyI6IkFVUyJ9", "serviceName": "DEFAULT" }' ``` You can pass a `comment` in the request body to provide additional context about the workflow execution. The comment will be added to the audit trail of the workflow execution. You can also pass `serviceName` in the request body to override the default configured service profile. #### Request Body Fields | Field | Type | Required | Description | | -------------------- | -------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `organizationToken` | `string` | Conditional | Token returned by a business lookup. Use this **or** `organization`, not both. | | `organization` | `object` | Conditional | Organization registration details. Use this **or** `organizationToken`, not both. | | `serviceName` | `string` | No | Override the default service profile. | | `comment` | `object` | No | Audit trail comment. Pass `{ "text": "..." }`. | | `executionVariables` | `object` | No | Runtime variables consumed by workflow tasks. Keys and types are defined per workflow. See [Execution Variables](#execution-variables) below. | #### Execution Variables `executionVariables` is a key-value object that passes runtime inputs into a workflow's tasks without changing the entity's persistent data. The variables a workflow accepts are defined by that workflow's configuration. Today the only workflow that uses `executionVariables` is the [Trust Analyzer](/docs/kyb/trust-analyzer) (`GLB-Trust-Analysis`), which takes the `documentId` of an uploaded trust deed. ```json Example - executionVariables for Trust Analysis theme={null} { "executionVariables": { "documentId": "92de15f6-5717-4562-b3fc-2c963f6665a7" } } ``` See the [Trust Analyzer](/docs/kyb/trust-analyzer) guide for the full flow. ##### With EntityId: This endpoint is used to execute a workflow for an existing entity. Make a `POST` request to the `execute` endpoint, including the `entityId`, `serviceName`, and `workflowName` in the path. ```bash Request - Execute Workflow with entityId theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/serviceprofiles/{{serviceName}}/workflows/{{workflowName}}/execute' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "comment": { "text": "Invoking Profile workflow" } }' ``` ##### Evaluate for an Existing Entity: If the entity has already been through a workflow execution and you need to re-assess its risk and workflow status (e.g., after classifying AML hits), use the `evaluate` endpoint. ```bash Request - Evaluate Workflow with entityId theme={null} curl --location --request POST 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/serviceprofiles/{{serviceName}}/workflows/{{workflowName}}/evaluate' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "comment": { "text": "Re-evaluating after AML hit classification" } }' ``` The evaluate endpoint requires a prior completed workflow execution. If no prior execution exists, the API returns `400`. If the entity's underlying data has changed and existing check results have been invalidated, the evaluation may produce an incomplete assessment. In this case, use `/execute` to fetch fresh data. #### Response ```json Response - Execute or Evaluate Workflow with entityId theme={null} { "entityId": "01993733-cfd5-7594-9e90-ec3ad06dd490", "requestId": "01K4VK7KWN6HEA43AQ0F13JZPT", "serviceName": "DEFAULT", "serviceProfileId": "64ec50f2-5e69-4fee-8d97-7db77f2b71cd", "workflowExecutionId": "01K4VK7QDJG631AWFKWYVE85Z5" } ``` KYB workflows are asynchronous. The API response will have a status of `202 Accepted` and contain the `workflowExecutionId` which can then be used to get the results of the workflow. The workflow will continue to process in the background. ### Step 2: Retrieve the Workflow Result You can retrieve the workflow result by using the `workflowExecutionId` returned in the previous step. #### Request ```bash Request - Retrieve Workflow Result theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/serviceprofiles/{{serviceName}}/workflows/{{workflowName}}/executions/{{workflowExecutionId}}' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' ``` `workflowResult.workflowExecutionState` indicates the execution state of the workflow. If it is `IN_PROGRESS`, the workflow is still running. You can poll the endpoint again to check the status. When the workflow is completed, the `workflowResult.workflowExecutionState` will be `COMPLETED`. At this point, you can parse the `workflowResult` object to understand the outcome of every step. Response will also contain the complete `organization` object with all the information about the business. *** ## Next Steps Once you have successfully executed a workflow, the next critical step is to parse the rich `workflowResult` object to understand the outcome of every check. For a complete breakdown of every field in the response, refer to our detailed guide: **[Interpreting Workflow Results](/docs/kyb/interpreting-workflows-v2)**. *** ## Additional Resources * [FrankieOne API Reference](/docs/reference/whats-new) * [FrankieOne Support](/docs/contacting-developer-support) # Getting Started: Your First API Call Source: https://docs.frankieone.com/docs/kyb/getting-started This guide will walk you through setting up your environment, authenticating, and making your first successful API call to the FrankieOne platform. Welcome to the FrankieOne API! This guide provides the essential information to get you up and running. Our goal is to help you make your first successful API call in minutes. ### Your FrankieOne Starter Pack When you partner with FrankieOne, your Customer Success Manager will provide you with a starter pack containing everything you need for each environment. You should have the following: | Resource | UAT / Sandbox | Production | | :------------------- | :--------------------------------------------- | :----------------------------------------- | | **Portal URL** | `https://portal.uat.frankie.one` | `https://portal.frankie.one` | | **API Base URL** | `https://api.uat.frankie.one/v2` | `https://api.frankie.one/v2` | | **KYB API Base URL** | `https://api.uat.frankie.one/v2/organizations` | `https://api.frankie.one/v2/organizations` | | **Customer ID** | Your unique UAT Customer ID | Your unique Production Customer ID | | **API Key** | Your secret UAT API Key | Your secret Production API Key | *** ## Authentication Headers All API requests to FrankieOne must be authenticated. You'll use the credentials from your starter pack in the request headers. | Header | Required | Description | | :-------------------------- | :------- | :--------------------------------------------------------------------------------------------------------------- | | `api_key` | **Yes** | Your secret API key for the specific environment (UAT or Production). | | `X-Frankie-CustomerId` | **Yes** | The unique identifier for your account. | | `X-Frankie-CustomerChildId` | No | The unique identifier for your child account. | | `X-Frankie-Username` | No | The email address or identifier of the operator performing the action. Highly recommended for auditing purposes. | | `X-Frankie-Channel` | No | The channel the request originates from (e.g., `API`, `PORTAL`, `ONESDK`). Useful for analytics and routing. | ##### Keep Your API Key Secure Your `api_key` is a secret and should be treated like a password. Store it securely on your backend and never expose it in client-side code or public repositories. If you suspect a key has been compromised, contact support immediately. *** ## Quickstart in 3 Steps Follow these steps to ensure your credentials are correct and your environment is ready for integration. The easiest way to verify that your credentials and connection are working is to call our simple health check endpoint: `/ruok`. This endpoint doesn't require a request body and is used purely to confirm successful authentication. ```bash Request - Health Check theme={null} curl --location '[https://api.uat.frankie.one/v2/kyc/ruok](https://api.uat.frankie.one/v2/kyc/ruok)' \ --header 'api_key: {{your_uat_api_key}}' \ --header 'X-Frankie-CustomerId: {{your_uat_customer_id}}' ``` A successful request will return a `200 OK` status and the following JSON response, confirming your keys are valid. ```json Response theme={null} { "status": "OK" } ``` If you receive an error, double-check that your API key and Customer ID are correct and that you are using the correct base URL for the environment. Before you can start verifying customers, your account needs to be configured with at least one workflow and one service profile. Your Customer Success Manager typically sets these up for you. You can confirm your setup by calling the `GET /v2/workflows` endpoint. This will list all the executable workflows available to you. ```curl Request - Get Workflows theme={null} curl --location '[https://api.uat.frankie.one/v2/workflows](https://api.uat.frankie.one/v2/workflows)' \ --header 'api_key: {{your_uat_api_key}}' \ --header 'X-Frankie-CustomerId: {{your_uat_customer_id}}' ``` You should receive a `200 OK` response with a `workflows` array. If the array is empty, please contact your Customer Success Manager to get your workflows published. ```json Response - Get Workflows theme={null} { "requestId": "req_01J...", "workflows": [ { "serviceName": "DEFAULT", "workflowId": "wf_01J...", "workflowName": "GLB-Organization-Profile", "type": "SYSTEM", "lifecyclePhase": "ONBOARDING" } ] } ``` Now you're ready to onboard a business. You can start by looking up for a business and creating an `organization` entity and then execute a workflow on it. You will need the `serviceName` and `workflowName` from the previous step. *** ## Next Steps You've successfully authenticated and confirmed your setup. Now you're ready to start building. Follow our implementation guides for common use cases. Learn how to search for a business. Learn the complete lifecycle of an 'organization' entity, from creation and retrieval to deletion. A step-by-step guide to executing a verification workflow against an existing entity. Dive deep into every endpoint, parameter, and response object in our comprehensive API Reference. # Interpreting Workflows Source: https://docs.frankieone.com/docs/kyb/interpreting-workflows-v2 A developer's guide to parsing the workflowResult object, from the overall status down to the granular details of each step. ## Understanding the Workflow Response After executing a workflow, the API returns a comprehensive `workflowResult` object. This object is the key to understanding the outcome of every step performed. This guide provides a structured, top-down walkthrough of how to parse this response, explaining each key object from the final verdict down to the granular evidence. The examples in this guide refer to the following API response for workflow execution `01K4XQGV10NY0Q3SE0F73H9TJX`. Click to expand and see the full structure. ```json theme={null} { "organization": { "entityId": "99f16410-2613-4181-8cf1-048625900013", "details": { "name": "Frankie One", "registrationDetails": [ ... ] }, "...": "..." }, "requestId": "01JZHEX0WX2QEM6EY139D5NNP1", "workflowResult": { "createdAt": "2025-09-12T01:09:31.804846Z", "endedAt": "2025-09-12T01:09:36.912755Z", "entityId": "01993700-edfb-766f-98d2-9fe470d78825", "entityType": "ORGANIZATION", "issues": [], "lifecyclePhase": "ONBOARDING", "monitoringTypes": [], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "riskAssessment": { "createdAt": "2025-09-12T01:09:31.857427Z", "entityId": "01993700-edfb-766f-98d2-9fe470d78825", "riskAssessmentId": "56adfe52-cdcb-414e-9819-a541953a5858", "riskFactors": [ { "createdAt": "2025-09-11T04:20:59.47008Z", "description": "Organization Type", "factor": "organization_type", "riskFactorId": "be53f30a-d1fe-4264-aec7-c798444c391d", "score": 30, "status": "VALID", "updatedAt": "2025-09-11T04:20:59.47008Z", "updatedRequestId": "01K4VG2EVV6YJEQFEWZNR4RRY7" } ], "riskScore": 30, "serviceProfileId": "081f345f-0919-4a60-8f23-e84cdd8bcf11", "updatedAt": "2025-09-12T01:09:37.095762Z", "updatedRequestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX", "workflowId": "62758fca-6e95-424e-85ae-2d246bb45d92", "workflowRiskLevel": "LOW", "workflowRiskScore": 30 }, "schemaVersion": 2, "serviceProfileId": "081f345f-0919-4a60-8f23-e84cdd8bcf11", "startedAt": "2025-09-12T01:09:31.804846Z", "status": "COMPLETE", "statusOverrideAt": "0001-01-01T00:00:00Z", "statusOverrideBy": "", "statusOverrideRequestId": "", "steps": { "failed": [], "incomplete": [], "notApplicable": [], "order": [ "START", "ORGANIZATION_DATA_FETCH", "ORGANIZATIONPERSIST", "DECISION", "FINISH" ], "passed": [ "START", "ORGANIZATION_DATA_FETCH", "ORGANIZATIONPERSIST", "DECISION", "FINISH" ] }, "updatedAt": "2025-09-12T01:09:37.258784Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX", "workflowExecutionState": "COMPLETED", "workflowId": "62758fca-6e95-424e-85ae-2d246bb45d92", "workflowName": "GLB-Organization-Ownership", "workflowStepResults": [ { "createdAt": "2025-09-12T01:09:36.891039Z", "endedAt": "2025-09-12T01:09:36.912755Z", "objectId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResults": [], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "risk": { "contributedScore": 0, "level": "LOW", "overallScore": 30 }, "schemaVersion": 2, "startedAt": "2025-09-12T01:09:36.884705Z", "stepName": "FINISH", "stepResultId": "01K4XQGZZV1HK6RRYRPEK9HH1X", "summary": { "stepName": "FINISH", "workflowContextId": "2e7b0cc9-0545-4399-a89a-303c63243fde" }, "updatedAt": "2025-09-12T01:09:37.233237Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" }, { "createdAt": "2025-09-12T01:09:36.560444Z", "endedAt": "2025-09-12T01:09:36.584254Z", "objectId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResults": [], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "schemaVersion": 2, "startedAt": "2025-09-12T01:09:36.54998Z", "stepName": "DECISION", "stepResultId": "01K4XQGZNGJC9KSH3BJ5GWHDZ2", "summary": { "stepName": "DECISION", "workflowExecutionResult": "COMPLETE" }, "updatedAt": "2025-09-12T01:09:36.732859Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" }, { "createdAt": "2025-09-12T01:09:34.533563Z", "endedAt": "2025-09-12T01:09:36.125729Z", "objectId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResults": [], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "risk": { "contributedScore": 30, "level": "LOW", "overallScore": 30 }, "schemaVersion": 2, "startedAt": "2025-09-12T01:09:34.527693Z", "stepName": "ORGANIZATIONPERSIST", "stepResultId": "01K4XQGXP5505XGKTZKJWQZAPQ", "summary": { "stepName": "ORGANIZATION_PERSIST" }, "updatedAt": "2025-09-12T01:09:36.381606Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" }, { "createdAt": "2025-09-12T01:09:32.467337Z", "endedAt": "2025-09-12T01:09:33.724934Z", "objectId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResults": [ { "class": "ORGANIZATION_PROFILE", "createdAt": "2025-09-11T04:20:56.176612Z", "entityId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResultId": "01K4VG2K7GQ0FPQE1FSNRPWM53", "providerResult": { "name": "ABR", "source": "ABR", "sourceNormalized": "ABR" }, "requestId": "01K4VG2EVV6YJEQFEWZNR4RRY7", "result": "CREATED", "schemaVersion": 2, "state": "COMPLETED", "stepName": "ORGANIZATION_DATA_FETCH", "stepType": "ORGANIZATION_PROFILE", "supplementaryData": { "organization": { ... }, "type": "KYB_ORGANIZATION" }, "systemStatus": "VALID", "updatedAt": "2025-09-11T04:20:56.176612Z" }, { "class": "ORGANIZATION_OWNERSHIP", "createdAt": "2025-09-12T01:09:33.705433Z", "entityId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResultId": "01K4XQGWW9DN9H4YZF6XKK7T44", "providerResult": { "name": "CREDITOR_WATCH", "reference": "2f3b7f30-ca8d-11eb-816f-0242ac11001b", "source": "ASIC", "sourceNormalized": "ASIC" }, "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "CREATED", "schemaVersion": 2, "state": "COMPLETED", "stepName": "ORGANIZATION_DATA_FETCH", "stepType": "ORGANIZATION_OWNERSHIP", "supplementaryData": { "organization": { ... }, "type": "KYB_ORGANIZATION" }, "systemStatus": "VALID", "updatedAt": "2025-09-12T01:09:33.705433Z" } ], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "schemaVersion": 2, "startedAt": "2025-09-12T01:09:32.457875Z", "stepName": "ORGANIZATION_DATA_FETCH", "stepResultId": "01K4XQGVNKJBAKMCSQ3RFE2358", "summary": { "provider": "CREDITORWATCH", "stepName": "ORGANIZATION_DATA_FETCH" }, "updatedAt": "2025-09-12T01:09:33.850884Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" }, { "createdAt": "2025-09-12T01:09:31.937737Z", "endedAt": "2025-09-12T01:09:31.979769Z", "objectId": "01993700-edfb-766f-98d2-9fe470d78825", "objectType": "ORGANIZATION", "processResults": [], "requestId": "01K4XQGPNYVR9PDCZ5ESW264V3", "result": "COMPLETE", "risk": { "contributedScore": 30, "level": "LOW", "overallScore": 30 }, "schemaVersion": 2, "startedAt": "2025-09-12T01:09:31.927456Z", "stepName": "START", "stepResultId": "01K4XQGV515Y9RMX9G9T85AGR3", "summary": { "stepName": "START", "workflowContextId": "2e7b0cc9-0545-4399-a89a-303c63243fde", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" }, "updatedAt": "2025-09-12T01:09:32.197792Z", "workflowExecutionId": "01K4XQGV10NY0Q3SE0F73H9TJX" } ] } } ``` *** ## Part 1: The Overall Outcome (The Final Verdict) Start by examining the top-level fields of the `workflowResult` object. These provide the final, authoritative outcome of the entire workflow execution. | Field Name | Importance | Description | | :----------------------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | | `status` | ‼️ | It represents the conclusive recommendation and accounts for any manual overrides. | | `workflowExecutionState` | ‼️ | This confirms the workflow's technical status. It **must be `COMPLETED`** for the `status` to be considered final and to review the `organization` object. | | `result` | ⚠️ | This field holds the original, automated outcome of the workflow *before* any manual changes. It is useful for auditing. | | `issues` | ⚠️ | An array of problems that may require manual review. If the `status` is `REVIEW`, this array will contain the specific reasons why. | ### Workflow Execution States (`workflowExecutionState`) This field tells you if the workflow ran to completion. | State | Description | | :------------ | :-------------------------------------------------------------------- | | `COMPLETED` | The workflow executed successfully from start to finish. | | `IN_PROGRESS` | The workflow is still running. | | `ERROR` | The workflow encountered an unrecoverable error and could not finish. | | `TIMEOUT` | The workflow exceeded its maximum execution time. | | `CANCELED` | The workflow was manually canceled before completion. | | `TERMINATED` | The workflow was terminated by the system before completion. | ### Workflow Statuses (`status` and `result`) This is the final recommendation of the workflow. | Status | Description | | :------------------------ | :--------------------------------------------------------------------------------------------- | | `PASS` | The entity successfully met the workflow's criteria. | | `FAIL` | The entity did not meet the workflow's criteria. | | `REVIEW` | The workflow produced results that require manual review. | | `CLEAR` | Often used for monitoring, indicates no negative information was found. | | `HIT` | Often used for monitoring, indicates negative information (e.g., a watchlist match) was found. | | `URGENT` | A critical issue was found (e.g., a sanctions match) that requires immediate attention. | | `COMPLETE` / `INCOMPLETE` | The workflow finished, but a pass/fail determination was not applicable. | ### Detecting Manual Overrides It's crucial to know if a workflow's result was changed by a person. When an operator manually changes the `status` (e.g., from `FAIL` to `PASS`), the following fields are populated: * `statusOverrideRequestId`: The unique ID of the override request. * `statusOverrideBy`: The user who performed the override. * `statusOverrideAt`: The timestamp of the override. **To detect an override, check if `statusOverrideRequestId` exists and is not empty.** *** ## Part 2: The Step-by-Step Breakdown (`workflowStepResults`) The `workflowStepResults` array is a log of each step in the workflow, explaining *how* the overall `status` was reached. Each object in this array corresponds to a step configured in your workflow (e.g., KYC, AML, IDV). | Field Name | Description | | :--------------- | :------------------------------------------------------------------------------------------------- | | `stepName` | The name of the step (e.g., `ORGANIZATION_DATA_FETCH`, `AML`). | | `result` | The outcome of this specific step. See the table below for all possible values. | | `summary` | A concise, human-readable summary of the step's outcome. | | `processResults` | An array of Process Result Objects (PROs) providing the granular evidence for this step's result. | | `risk` | The risk assessment specific to this step, including the score it contributed to the overall risk. | ### Workflow Step Results (`result`) | Result | Description | | :-------------------- | :------------------------------------------------------------------------------------------------------------ | | PARTIAL | The step produced a successful, unsuccessful, or partially successful match against data sources. | | CLEAR / HIT | Indicates no negative information found (CLEAR) or negative information found (HIT), e.g., a watchlist match. | | PASS / FAIL | The step completed and met (PASS) or did not meet (FAIL) its required criteria. | | COMPLETE / INCOMPLETE | The step finished, but a pass/fail scenario was not applicable. | | SKIPPED | The step was skipped because it was not required to run. | | MISSING\_DATA | The step could not run because it requires additional data. | | ERROR | The step encountered an unrecoverable technical error. | *** ## Part 3: The Granular Evidence (`processResults`) For the deepest level of detail, look inside a `workflowStepResult` at its `processResults` array. A **Process Result Object (PRO)** is the raw evidence from a single check against a single data source. | Field Name | Description | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `processResultId` | A unique identifier for this specific piece of evidence. | | `class` | The high-level category of the step. See the table below for details. | | `objectType` | The specific data element that was checked. | | `result` | The outcome of this specific step (e.g., `MATCH`, `HIT`, `CLEAR`). | | `providerResult` | An object containing details from the downstream data provider, including the `source` of the data. | | `systemStatus` | The lifecycle status of this PRO (e.g., `VALID`, `STALE`, `MARKED_INVALID`). A `STALE` status means the underlying entity data has changed since this check was performed. | | `manualStatus` | If an operator has manually reviewed this specific PRO, their conclusion (e.g., `TRUE_POSITIVE`, `FALSE_POSITIVE`) is recorded here. | | `supplementaryData` | A rich, context-specific object containing detailed metrics, like AML hits or extracted organization data. | ### Process Result Classes (`class`) | Class | Description | | :----------------------- | :------------------------------------------------------------------------------- | | `ORGANIZATION_OWNERSHIP` | Organization ownership data fetched from a data source. | | `ORGANIZATION_PROFILE` | Organization profile data fetched from a data source. | | `AML` | An Anti-Money Laundering screening against watchlists, sanctions, and PEP lists. | ## Best Practices for Integration * **Check `workflowExecutionState` first**: Always confirm the workflow is `COMPLETED` before trusting the `status` and the returned `organization` object. * **Debug with `workflowStepResults`**: When you get an unexpected `FAIL` or `REVIEW`, loop through the `workflowStepResults` to find which `stepName` has a non-passing `result`. The `summary` and `processResults` within that step will tell you why. * **Log the `workflowExecutionId`**: This ID is your key for auditing, support queries, and correlating results. ## References For more details on specific `workflowResult` objects, please refer to our Features section. * [Interpreting AML Results](/docs/kyb/anti-money-laundering-results) # Lookup a Business Source: https://docs.frankieone.com/docs/kyb/lookup-a-business Find a business in a specific jurisdiction You can lookup a business in authoritative registries for a given region by supplying either their name or the registration number relevant to the jurisdiction (eg: ACN in Australia). This allows you to confirm that the organization exists, and we also fetch additional details such as their current legal status in supported regions. The name need not be the full legal name; partial name search is supported by many regional registries. Perform a business lookup with a partial name or number using the [/lookup](/api-reference/organizations/lookup-organizations) endpoint. 1. In the example below, replace `YOUR_CUSTOMER_ID` with your Customer ID and `YOUR_API_KEY` with your API key provided by FrankieOne. 2. Copy the resulting code into your command line, and run the command. #### Request ```bash Request - Name theme={null} curl --request POST \ --url https://api.uat.frankie.one/v2/organizations/lookup \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'api_key: YOUR_API_KEY' --header 'content-type: application/json' \ --data '{ "organizationName": "FrankieOne", "region": { "country": "AUS" } }' ``` ```bash Request - Number theme={null} curl --request POST \ --url https://api.uat.frankie.one/v2/organizations/lookup \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'api_key: YOUR_API_KEY' --header 'content-type: application/json' \ --data '{ "organizationNumber": { "registrationNumber": "61623506892", "registryCode": "ABN" }, "region": { "country": "AUS" } }' ``` #### Response The response will contain a list of businesses that matched against the lookup criteria supplied ```json Response - Name theme={null} { "matchedOrganizations": [ { "addresses": [ { "country": "AUS", "postalCode": "3000", "subdivision": "VIC", "type": "OFFICE_LOCALITY", "unstructuredLongForm": "VIC 3000" } ], "alternateNames": [ { "name": "FRANKIE FINANCIAL PTY LTD", "type": "Trading name" }, { "name": "FRANKIEONE", "type": "Trading name" } ], "country": "AUS", "name": { "name": "FRANKIE FINANCIAL PTY LTD" }, "organizationToken": "eyJ2ZXIiOiIxLjAiLCJ0cyI6IjIwMjUtMDktMTBUMDQ6Mzc6MDIuMDg3MDU3MzMzWiIsIm9uIjpbeyJybiI6IjYxNjIzNTA2ODkyIiwicmEiOiJBQk4ifSx7InJuIjoiNjIzNTA2ODkyIiwicmEiOiJBQ04ifV0sInByb3YiOiJjcmVkaXRvcndhdGNoIiwiY28iOiJBVVMifQ==", "registrationDetails": [ { "registrationNumber": "61623506892", "registrationNumberType": "ABN" }, { "registrationNumber": "623506892", "registrationNumberType": "ACN" } ], "status": { "normalized": { "code": "ACTV" }, "unstructured": { "description": "Registered" } }, "type": { "code": "PRV", "description": "Australian Private Company" } } ], "queryDetails": { "organizationName": "FrankieOne", "region": { "country": "AUS" } }, "requestId": "01K4RYKAYFKYY7JJVEX234B0FN" } ``` ```json Response - Number theme={null} { "matchedOrganizations": [ { "addresses": [ { "country": "AUS", "postalCode": "3000", "subdivision": "VIC", "type": "OFFICE_LOCALITY", "unstructuredLongForm": "VIC 3000" } ], "alternateNames": [ { "name": "FRANKIE FINANCIAL PTY LTD", "type": "Trading name" }, { "name": "FRANKIEONE", "type": "Trading name" } ], "country": "AUS", "name": { "name": "FRANKIE FINANCIAL PTY LTD" }, "organizationToken": "eyJ2ZXIiOiIxLjAiLCJ0cyI6IjIwMjUtMDktMTBUMDQ6MzU6NDYuNTE0MTI2NzE0WiIsIm9uIjpbeyJybiI6IjYxNjIzNTA2ODkyIiwicmEiOiJBQk4ifSx7InJuIjoiNjIzNTA2ODkyIiwicmEiOiJBQ04ifV0sInByb3YiOiJjcmVkaXRvcndhdGNoIiwiY28iOiJBVVMifQ==", "registrationDetails": [ { "registrationNumber": "61623506892", "registrationNumberType": "ABN" }, { "registrationNumber": "623506892", "registrationNumberType": "ACN" } ], "status": { "normalized": { "code": "ACTV" }, "unstructured": { "description": "Registered" } }, "type": { "code": "PRV", "description": "Australian Private Company" } } ], "queryDetails": { "organizationNumber": { "registrationNumber": "61623506892", "registryCode": "ABN" }, "region": { "country": "AUS" } }, "requestId": "01K4RYH14PQYB7V5BD0MGAQWSS" } ``` ## Extract the organizationToken ##### What's it used for? The organizationToken is used in subsequent steps to create an organization entity or to run a workflow. Lookup may return multiple matches. Each match will have some business details and a unique organizationToken. Be sure to extract the organizationToken matching the details of the organization you intend to process. For example, extract the organizationToken for the first matched result: ```javascript Retrieving a Company code theme={null} const organizationToken = response["matchedOrganizations"][0]["organizationToken"]; ``` # Creating & Managing Organizations Source: https://docs.frankieone.com/docs/kyb/managing-organizations A guide to the complete lifecycle of an 'organization' entity, from creation and retrieval to deletion. The `organization` is a core object in the FrankieOne platform, representing a business. This guide covers the complete lifecycle of creating and managing these entities via the API. ## 1. Creating an Organization To create an `organization` entity, send a `POST` request with the organizationToken retrieved from the [/lookup](/api-reference/organizations/lookup-organizations) endpoint. A successful request will return a `201 Created` status and the `organization` object, including a unique `entityId`. The `entityId` returned in the response can be used for subsequent operations, such as executing a workflow. ###### Warning: organizationToken Expiry The `organizationToken` retrieved from the lookup endpoint does not last forever. If your request fails indicating invalid organizationToken, you will need to perform a new lookup to retrieve a new organizationToken. ###### Warning: A new entity is created for each request A new entity is created for each request. We do not de-duplicate entities based on organizationToken in this request. ### Example: Creating an Organization This example shows a standard request to create an organization with organizationToken retrieved from the [/lookup](/api-reference/organizations/lookup-organizations) endpoint. 1. In the example below, replace `YOUR_CUSTOMER_ID` with your Customer ID and `YOUR_API_KEY` with your API key provided by FrankieOne. 2. Copy the resulting code into your command line, and run the command. #### Request ```bash Request - Create Organization theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "organizationToken": "eyJ2ZXIiOiIxLjAiLCJ0cyI6IjIwMjUtMDktMTBUMDQ6Mzc6MDIuMDg3MDU3MzMzWiIsIm9uIjpbeyJybiI6IjYxNjIzNTA2ODkyIiwicmEiOiJBQk4ifSx7InJuIjoiNjIzNTA2ODkyIiwicmEiOiJBQ04ifV0sInByb3YiOiJjcmVkaXRvcndhdGNoIiwiY28iOiJBVVMifQ==" }' ``` #### Response ```json Response - Create Organization theme={null} { "organization": { "createdAt": "2025-09-10T04:53:46Z", "details": { "registrationDetails": [ { "registrationNumber": "61623506892", "registrationNumberType": "ABN", "sourceId": "ec13d19f-c725-4397-a575-92c65c070f23" }, { "registrationNumber": "623506892", "registrationNumberType": "ACN", "sourceId": "ec13d19f-c725-4397-a575-92c65c070f23" } ] }, "entityId": "019931f9-02a2-7c87-816c-c9e6743eaae5", "entityType": "ORGANIZATION", "informationSources": { "ec13d19f-c725-4397-a575-92c65c070f23": { "createdAt": "2025-09-10T04:53:46.674358Z", "isAuthoritative": true, "provider": "CREDITOR_WATCH", "requestedAt": "2025-09-10T04:37:02Z", "source": "ASIC", "sourceId": "ec13d19f-c725-4397-a575-92c65c070f23" } }, "schemaVersion": 2, "sourceId": "ec13d19f-c725-4397-a575-92c65c070f23", "updatedAt": "2025-09-10T04:53:46Z" }, "requestId": "01K4RZJ0CGM3PWCRS5NRH4WXMA", "serviceProfiles": [ { "createdAt": "2025-09-10T04:53:46.9539Z", "createdRequestId": "01K4RZJ0CGM3PWCRS5NRH4WXMA", "entityId": "019931f9-02a2-7c87-816c-c9e6743eaae5", "entityName": "FRANKIE FINANCIAL PTY LTD", "entityType": "ORGANIZATION", "serviceName": "DEFAULT", "serviceProfileId": "86cf3db8-a9f5-433d-b446-35927096d327", "state": "INIT", "subscriptions": [], "updatedAt": "2025-09-10T04:53:46.9539Z" } ] } ``` ### The `organization` Object The `organization` object holds all the information about the business. Organization `details` holds the organization details including registration details, organization name etc. For more details on the fields in the organization object, please refer to our [retrieve organization](/api-reference/organizations/get-an-organization-entity) API documentation. To understand ownership structure of the organization, please refer to [understanding organization ownership](/docs/kyb/organization-ownership) documentation. #### Information Sources `organization` object also includes `informationSources` which is a map of information source Ids to information source objects. These objects indicate the vendor and registry from which information was retrieved, and when it was requested. Data points in the organization object are then tagged with this sourceId. #### Service Profiles If a `serviceName` is passed in the Create Organization request, a service profile of that service gets created as part of the entity creation. If no `serviceName` is passed, a default service profile is created. `serviceProfiles` is an array of service profile objects associated with the organization. *** ## 2. Retrieving an Organization To fetch the current state of an organization entity, use a `GET` request with their unique `entityId`. #### Request ```bash Request - Retrieve Organization theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/019931f9-02a2-7c87-816c-c9e6743eaae5' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` The response will contain the full `organization` object, similar to the response from the creation request. If you've retrieved additional data points for the entity, by running the profile/ownership workflows, they will also be included in the response. *** ## 3. Deleting an Organization You can delete an organization entity using the `DELETE` endpoint with their `entityId`. Deletion is Permanent Deleting an entity is an irreversible action. This data cannot be recovered. Only perform deletions when you are certain the data is no longer required for any operational, audit, or compliance purpose. ### Deleting an Organization To permanently remove an organization and all their associated data, use the `DELETE` endpoint with their `entityId`. #### Request ```bash Request - Delete Organization theme={null} curl --location --request DELETE 'https://api.uat.frankie.one/v2/organizations/019931f9-02a2-7c87-816c-c9e6743eaae5' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` # Understanding Organization Ownership Source: https://docs.frankieone.com/docs/kyb/organization-ownership Learn what fields within the Organization object mean, specifically in the context of Organization Ownership. ## Summary The `organization` object has rich details regarding the organization and its ownership structure. You can either create an organization through our [create organization](/api-reference/organizations/create-an-organization-entity) API or by [executing a data-fetch workflow](/api-reference/organization-workflows/execute-a-workflow-with-organization-details) like `GLB-Organization-Profile` or `GLB-Organization-Ownership`. Once you have the `entityId` of the created organization, you can fetch its details using the [retrieve organization](/api-reference/organizations/get-an-organization-entity) API. The organization object mainly consists of: * Details of the organization - This includes name, registration details, addresses, phone numbers, web URLs, etc. For more details on these fields, please refer to our [retrieve organization](/api-reference/organizations/get-an-organization-entity) API documentation. * Organization ownership - This includes the ownership details of the organization, including shareholdings and ultimate beneficial owners. This page focuses on organization ownership. ## Organization Ownership These fields are of interest to you if you want to understand the ownership details of the organization. #### `shareCapital` The total value of shares issued by the company to its holders. It typically includes both the nominal value of the shares as well as any premium paid by the shareholders. #### `shareInterests` Represents the specific equity interests held by shareholders (for example, ordinary shares, preference shares, or options) and their associated holders. Each `shareInterest` includes: * Members who hold the interest (supports joint holdings) * Whether the interest is beneficial or non-beneficial * The ownership percentage ### Associated Entities The following are the associated entities of the organization. Each object in the array has a unique `entityId`. You can then use this to get more information about the entity in the `linkedIndividuals` or `linkedOrganizations` maps of the `organization` object. #### `shareholders` The shareholders of a company. It includes details such as the number of shares held by each shareholder and their ownership percentages. Look up the `entityId` in the `linkedIndividuals` or `linkedOrganizations` maps of the `organization` object to get more information about the shareholder. #### `officials` The entities that hold official positions or roles within a company, such as directors or company secretaries. It includes details such as their positions, appointment dates, and other relevant information. Look up the `entityId` in the `linkedIndividuals` or `linkedOrganizations` maps of the `organization` object to get more information about the official. ### Ownership Insights We provide the following fields to draw insights into the ownership of the organization. Ownership Insights are calculated based on the ownership policy configured according to your requirements. #### `ownershipPolicy` Defines the configuration and specific threshold values used to identify blocking entities, UBOs, and other owners. #### `ultimateBeneficialOwners` UBO stands for “Ultimate Beneficial Owner.” UBO(s) are the natural person(s) who ultimately own or control a company. This provides information about the individuals who have a significant level of control or ownership in a company, either directly or indirectly. #### `blockingEntities` Entities linked to the parent entity that currently prevent a complete ownership picture (for example, missing filings or opaque structures) and may require further investigation. #### `otherOwners` The other owners of the company, who aren't necessarily UBOs. ## Traversing Ownership Tree Use the combination of associated-entity arrays and linked-entity maps to navigate the structure: * Associated entity arrays (on the focus organization): `officials`, `shareholders` * Contain summary items, each with an `entityId` * Linked entity maps (siblings on the same object): `linkedIndividuals`, `linkedOrganizations` * Provide full records keyed by `entityId` Step-by-step: 1. Start at the focus organization. Inspect its `officials` and `shareholders` arrays. 2. For each item, note the `entityId` and whether it represents an individual or organization. 3. Resolve details via: * Individuals → `linkedIndividuals[entityId]` * Organizations → `linkedOrganizations[entityId]` 4. If you land on a linked organization and need to go deeper, repeat the same process using that organization’s `officials` and `shareholders` (the details for these should be present in the top level `linkedIndividuals`/`linkedOrganizations`). 5. Stop when you reach your analysis depth, there are no more organizations to follow, or you’ve visited an entity already (to avoid cycles). Example (simplified, based on an actual organization response): ```json theme={null} { "officials": [ { "entityId": "dc5e27f9-1952-408a-9f99-082926539e69", "entityType": "INDIVIDUAL", "role": { "code": "DR", "description": "Director" } } ], "shareholders": [ { "entityId": "019d6837-26bd-7639-88fc-d629519acb9a", "entityType": "ORGANIZATION" }, { "entityId": "08916f09-fc05-4778-9899-f147d9d61071", "entityType": "INDIVIDUAL" } ], "linkedIndividuals": { "dc5e27f9-1952-408a-9f99-082926539e69": { "entityId": "dc5e27f9-1952-408a-9f99-082926539e69", "entityType": "INDIVIDUAL", "name": { "displayName": "DANIELE CATALANO" } }, "08916f09-fc05-4778-9899-f147d9d61071": { "entityId": "08916f09-fc05-4778-9899-f147d9d61071", "entityType": "INDIVIDUAL", "name": { "displayName": "CHLOE MARIE CATALANO" } }, "c0cda324-e77f-47fa-b30e-bcf4b38fd971": { "entityId": "c0cda324-e77f-47fa-b30e-bcf4b38fd971", "entityType": "INDIVIDUAL", "name": { "displayName": "MICHELLE ANNE CATALANO" } } }, "linkedOrganizations": { "019d6837-26bd-7639-88fc-d629519acb9a": { "entityId": "019d6837-26bd-7639-88fc-d629519acb9a", "entityType": "ORGANIZATION", "details": { "name": { "name": "DYLCLO PTY LTD" } }, "officials": [ { "entityId": "dc5e27f9-1952-408a-9f99-082926539e69", "entityType": "INDIVIDUAL", "role": { "code": "DR", "description": "Director" } } ], "shareholders": [ { "entityId": "c0cda324-e77f-47fa-b30e-bcf4b38fd971", "entityType": "INDIVIDUAL" }, { "entityId": "dc5e27f9-1952-408a-9f99-082926539e69", "entityType": "INDIVIDUAL" } ] } } } ``` In this example, the focus organization has one official (`dc5e27f9-...`, Daniele Catalano, Director) and two shareholders: an organization (`019d6837-...`, DYLCLO PTY LTD) and an individual (`08916f09-...`, Chloe Catalano). You can resolve each entity's full details from the linked maps, and then follow DYLCLO PTY LTD's `shareholders`. This leads you to `c0cda324-...` (Michelle Catalano) and back to `dc5e27f9-...` (Daniele Catalano) — the same individual already seen as a top-level official. Since `dc5e27f9-...` has already been visited, stop traversing that branch to avoid a cycle. You can continue this process to traverse the ownership tree. Note: * The `linkedIndividuals` and `linkedOrganizations` maps are flat and live at the top level of the response for the focus organization. There are no nested linked maps per linked organization—use the same top-level maps to resolve any `entityId` you encounter while traversing. * If an `entityId` is not present in the corresponding linked map, treat it as incomplete data. You can fetch details on-demand via the API or surface a "details unavailable" state. * To avoid cycles and overly deep traversals (for example, cross-holdings), keep a set of visited `entityId`s and consider a maximum traversal depth. # Standard Workflows Source: https://docs.frankieone.com/docs/kyb/standard-kyb-bundles Explore our out-of-the-box KYB workflow solutions designed to get you started with best-practice business verification quickly. ## Out-of-the-Box Workflow Solutions FrankieOne offers a suite of standard KYB workflows that address the most common business onboarding and compliance monitoring needs. These pre-configured workflows allow for rapid integration, enabling you to implement a best-practice business verification process without the need for custom configuration. To run one, simply reference its **Workflow Name** when [executing a workflow](/docs/kyb/executing-workflows) via the API. ### Choosing Your Workflow Type Our KYB workflows are categorized by the depth of the ownership picture you need: * **Profile Workflows:** Retrieve the organization's registration details and direct ownership (immediate shareholders and officers), then run compliance checks. Suited to lower-risk onboarding where a single level of ownership is sufficient. * **Ownership Workflows:** Retrieve the complete ownership tree, including nested entities, and derive Ultimate Beneficial Owners (UBOs). Required where you need to identify and verify the individuals who ultimately control the business. Each type is available in a standard variant and a **Force-Refresh** variant. Standard variants reuse recently fetched provider data within a configurable ageing window; Force-Refresh variants always retrieve the latest data directly from providers. *** ## Onboarding Workflows These workflows are executed against an organization to fetch its data and run compliance checks. ### Profile Workflows Retrieves the organization's registration details, addresses, trading names and status, along with direct shareholders and officers. Runs AML screening and risk assessment. * **Workflow Name:** `GLB-Organization-Profile` * **Use Case:** Standard business onboarding where direct ownership is sufficient. * **Core Checks:** Registration Lookup, Data Enrichment, AML (Sanctions & Watchlist) Screening, Associated Entities Risk. * **Primary Data Sources:** Business registry and data providers appropriate to the organization's jurisdiction, covering Australia, the US and international markets, plus an AML screening provider. * **Outputs:** A downloadable PDF Profile Report. * **Possible Outcomes:** `COMPLETE`, `IN_PROGRESS`, `REVIEW`, `FAIL`. * **Data Freshness:** Reuses recently fetched provider data within a configurable ageing window. Identical to Organization Profile, but always fetches the latest data directly from providers rather than reusing recently fetched data. * **Workflow Name:** `GLB-Organization-Profile-Force-Refresh` * **Use Case:** Re-verification where up-to-date information is critical — for example after a known change to the business, or where previously retrieved data may be stale or incomplete. * **Core Checks:** Registration Lookup, Data Enrichment, AML (Sanctions & Watchlist) Screening, Associated Entities Risk. * **Primary Data Sources:** Business registry and data providers appropriate to the organization's jurisdiction, covering Australia, the US and international markets, plus an AML screening provider. * **Outputs:** A downloadable PDF Profile Report. * **Possible Outcomes:** `COMPLETE`, `IN_PROGRESS`, `REVIEW`, `FAIL`. * **Data Freshness:** Always retrieves fresh data from providers. ### Ownership Workflows Retrieves the full ownership structure of an organization, including the complete shareholder and officer tree with nested entities. Derives UBOs and identifies blocking entities based on your configured ownership policy (for example, a 25% threshold). * **Workflow Name:** `GLB-Organization-Ownership` * **Use Case:** Onboarding where you must identify and verify the individuals who ultimately own or control the business. * **Core Checks:** Registration Lookup, Full Ownership Tree Retrieval, Ownership Insights (UBO Derivation), AML (Sanctions & Watchlist) Screening, Associated Entities Risk. * **Primary Data Sources:** Business registry and data providers appropriate to the organization's jurisdiction, covering Australia, the US and international markets, plus an AML screening provider. * **Outputs:** A downloadable PDF Ownership Report, including a UBO tree diagram. * **Possible Outcomes:** `COMPLETE`, `IN_PROGRESS`, `REVIEW`, `FAIL`. * **Data Freshness:** Reuses recently fetched provider data within a configurable ageing window. Identical to Organization Ownership, but always fetches the latest ownership data directly from providers. * **Workflow Name:** `GLB-Organization-Ownership-Force-Refresh` * **Use Case:** When the ownership structure may have recently changed (new shareholders, resignations), after a regulatory event requiring fresh verification, or when a previous ownership fetch returned incomplete data. * **Core Checks:** Registration Lookup, Full Ownership Tree Retrieval, Ownership Insights (UBO Derivation), AML (Sanctions & Watchlist) Screening, Associated Entities Risk. * **Primary Data Sources:** Business registry and data providers appropriate to the organization's jurisdiction, covering Australia, the US and international markets, plus an AML screening provider. * **Outputs:** A downloadable PDF Ownership Report, including a UBO tree diagram. * **Possible Outcomes:** `COMPLETE`, `IN_PROGRESS`, `REVIEW`, `FAIL`. * **Data Freshness:** Always retrieves fresh data from providers. **AML screening defaults to sanctions and watchlist checks.** By default, the AML step in these workflows screens the focus organization against sanctions and watchlists only. **Adverse media is not included by default.** If you require adverse media screening, it must be configured — contact your account manager to have it enabled for your account. These workflows also manage ongoing AML monitoring for you: monitoring is enabled automatically when the AML check finds no issues, and disabled when it returns a failure. No manual intervention is required. *** ## Understanding Your Workflow Result Onboarding workflows return one of four outcomes: | Result | What It Means | What To Do | | ------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | | `COMPLETE` | The organization passed all checks, and all associated entities (UBOs) have completed their individual KYC checks. | Proceed with onboarding. | | `IN_PROGRESS` | The organization itself passed, but one or more UBOs have not yet completed their individual KYC checks. | Complete the outstanding UBO verifications, then re-evaluate. | | `REVIEW` | The AML screening returned a potential match. | Review the AML result and make a decision. | | `FAIL` | The AML screening returned a confirmed match. | Do not proceed; follow your escalation process. | When AML screening returns a potential or confirmed match, the workflow goes straight to `REVIEW` or `FAIL` and skips the associated entities risk check. The AML outcome takes priority. For a full walkthrough of reading a workflow result, see [Interpreting workflow results](/docs/kyb/interpreting-workflows-v2). *** ## Workflow Comparison | Feature | Profile | Profile Force-Refresh | Ownership | Ownership Force-Refresh | | ---------------------------- | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | | **Registration lookup** | Yes (cached) | Yes (fresh) | Yes (cached) | Yes (fresh) | | **Provider data** | Direct ownership (cached) | Direct ownership (fresh) | Full tree (cached) | Full tree (fresh) | | **UBO derivation** | No | No | Yes | Yes | | **PDF report** | Profile Report | Profile Report | Ownership Report | Ownership Report | | **AML screening** | Sanctions & watchlist | Sanctions & watchlist | Sanctions & watchlist | Sanctions & watchlist | | **Toggles AML monitoring** | Yes | Yes | Yes | Yes | | **Associated entities risk** | Yes (UBOs) | Yes (UBOs) | Yes (UBOs) | Yes (UBOs) | | **Possible outcomes** | COMPLETE, IN\_PROGRESS, REVIEW, FAIL | COMPLETE, IN\_PROGRESS, REVIEW, FAIL | COMPLETE, IN\_PROGRESS, REVIEW, FAIL | COMPLETE, IN\_PROGRESS, REVIEW, FAIL | *** ## Data Freshness and Provider Calls Understanding when a workflow calls an external provider helps you manage cost. * **Standard workflows** reuse previously retrieved provider data when it falls within the configurable ageing window. No new provider call is made, and no charge is incurred for that step. This is the cost-efficient default. * **Force-Refresh workflows** always make a fresh provider call, regardless of what data is already held. A charge is incurred for each provider step on every run. *** ## Next Steps * [Executing workflows](/docs/kyb/executing-workflows) — how to run a workflow against an organization * [Interpreting workflow results](/docs/kyb/interpreting-workflows-v2) — reading and acting on the response * [Organization ownership](/docs/kyb/organization-ownership) — working with UBOs and the ownership tree # Trust Analyzer Source: https://docs.frankieone.com/docs/kyb/trust-analyzer Extract trust structures from trust deeds and produce audit-ready, structured output for complex KYB onboarding using the FrankieOne Trust Analyzer, through the Portal or the API. ##### Access The Trust Analyzer runs as the `GLB-Trust-Analysis` workflow on the V2 platform. Contact your FrankieOne representative to have it enabled for your environment. ## Overview Trusts are one of the harder entity types to onboard. The information you need lives in a trust deed, a long, free-form legal document that varies in layout from one trust to the next, and reading it by hand is slow and easy to get wrong. The Trust Analyzer does that reading for you. It ingests a trust deed PDF, classifies the trust type, extracts the named parties (trustees, settlors, beneficiaries, appointors, protectors, SMSF members), and normalises their roles into a consistent structure. Every extracted value carries a reference back to the page of the deed it came from, so your compliance team can trace and verify each field. The result is structured, audit-ready data you can review, correct, and feed into your KYB and KYC workflows. It lets you onboard trusts, and businesses that hold assets through trusts, at scale without adding the manual review effort that deeds normally demand. Trust Analyzer currently supports Australian trust deeds only; international coverage is not yet supported. *** ## How it Works You can run a trust analysis either through the Portal or directly through the API. Both follow the same underlying analyse, review, confirm pattern, with a human confirmation step so a person signs off on the extracted structure before it is used for compliance. ### Via the Portal From the organization's Overview page, select the **Trust Analyser** tab. Trust Analyser tab on the organization Overview page Select **Upload trust deed** and add the PDF (up to 20MB). Add Document dialog for uploading a trust deed The uploaded deed appears in the Trust deeds table with its status — starting at analysis, then **To be reviewed** once ready. Trust deeds table showing a deed with status To be reviewed Once analysis completes, the extracted structure opens in a split view: the deed on the left, extracted fields on the right. Each field carries a small reference marker (e.g. `1a`, `2a`) linking it back to its source page, so you can verify quickly without re-reading the whole document. Correct anything that needs it inline, select **I have reviewed and accept the data in this trust deed**, then select **Save**. Confirmed parties appear on the same screen, marked as an **Associated party**, and are linked to the organization's ownership and control structure. ### Via the API Upload the trust deed PDF as a `TRUST_DEED` document against the organization entity and keep the returned `documentId`. This is the document the workflow will analyse. Execute `GLB-Trust-Analysis` for the organization, passing the `documentId` via `executionVariables`. The trust type is detected from the document, so you do not supply it. The workflow runs asynchronously. Track the execution result until it reaches `REVIEW`, which signals that analysis has completed and the extracted data is ready to look at. Fetch the analyses for the document. Each analysis includes the detected trust type and the extracted parties, with `references` that point back to the page in the deed each value came from. Review the extracted data, correct any field that needs it, then confirm. Confirmation records your accepted version while keeping the original analysis as an audit trail. Link the extracted parties to the focus organization so they form part of its ownership and control structure. Ready to integrate? The [Trust Analyzer Implementation Guide](/docs/kyb/trust-analyzer-implementation) walks the full Portal and API flow step by step, with request and response examples for each stage. *** ## Supported Trust Types | Trust Type | Detected value | | --------------------------------------- | ------------------------- | | Discretionary (family) trust | `DISCRETIONARY` | | Unit trust | `UNIT` | | Self-managed superannuation fund (SMSF) | `SELF_MANAGED_SUPER_FUND` | | Could not be classified | `UNKNOWN` | Every analysis returns the details common to any trust (name, establishment, certification, and execution dates, trustees, and settlors). On top of that, the shape of `typeInformation` depends on the detected type: * **Discretionary** (`discretionary`): specified beneficiaries, general beneficiaries, appointors, and protectors. * **Unit** (`unit`): unit holders with their holdings (as a percentage or a unit count) and the total units on issue. * **SMSF** (`selfManagedSuperFund`): the fund's members. * **Unknown** (`unknown`): the reasons the trust could not be classified. A trust type must be identified before you can confirm. General beneficiaries are a class of persons defined in the deed who may receive funds; specified beneficiaries are named individuals. *** ## Frequently Asked Questions The trust deed must be a PDF, up to 100 pages and 20MB. Use a text-based (machine-readable) PDF: extraction reads the document text directly, so scanned or image-only deeds may not extract reliably. Analysis is asynchronous and usually takes a couple of minutes; complex multi-schedule deeds can take a little longer. No. The trust type is detected automatically from the deed. It's returned in `type.detected` via the API and shown directly in the Portal's review screen. It's returned as `UNKNOWN` (API) or shown as unclassified (Portal), with the reasons why. Trust type is inferred by the analyzer and isn't something you can manually set or override, in the Portal or via the API — a trust type must be successfully identified before the analysis can be confirmed. Yes. In the Portal, correct fields inline on the review screen before selecting **Save**. Via the API, send the corrected `documentInformation` to the [analysis confirm endpoint](/api-reference/organization/document-analysis-result-confirmation). The original analysis is always retained as an audit trail. Re-running analysis on an unchanged trust deed reuses the existing valid analysis rather than running a new one, and you're not charged again. If the deed's attachment is later updated or deleted, prior analyses for that document are marked stale. *** ## Next Steps * [Trust Analyzer Implementation Guide](/docs/kyb/trust-analyzer-implementation) — the full Portal and API walkthrough: upload, execute, retrieve, confirm, and associate parties. * [Executing Workflows](/docs/kyb/executing-workflows) — how `executionVariables` are passed when executing a workflow. * [Interpreting Workflow Results](/docs/kyb/interpreting-workflows-v2) — parse the full `workflowResult` object. * [Managing Organizations](/docs/kyb/managing-organizations) — create and manage the organization entity before running the workflow. * [Anti-Money Laundering](/docs/kyb/anti-money-laundering) — screen the parties extracted from the trust deed. # Trust Analyzer Implementation Source: https://docs.frankieone.com/docs/kyb/trust-analyzer-implementation Step-by-step walkthrough for running a trust analysis via the Portal or the API: upload the deed, run the analysis, retrieve and confirm the extracted structure, and associate the parties. New to the Trust Analyzer? Start with the [Trust Analyzer overview](/docs/kyb/trust-analyzer) for what it does and how the flow fits together, then come back here for the full walkthrough. This guide covers both the Portal walkthrough and the API walkthrough. Use whichever fits your team — they produce the same result. Currently supports Australian trust deeds only. *** ## Portal Walkthrough ### Prerequisites * **An organization entity** already created in the Portal. * **Trust Analyzer enabled** for your environment, with the workflow assigned and turned on in Ops Centre. Contact your FrankieOne representative if you don't see it yet. * Available for Australian trust deeds only. From the organization's Overview page, select the **Trust Analyser** tab. Trust Analyser tab on the organization Overview page Select **Upload trust deed**, then either drag and drop the file or select **Browse File** to choose the PDF (max 20MB). Add Document dialog for uploading a trust deed The deed appears in the Trust deeds table on the same tab, with its status shown in the Status column — through analysis, then **To be reviewed** once the extracted data is ready. Re-uploading and re-analysing an unchanged trust deed reuses the existing valid analysis rather than running a fresh one. If the attachment is later updated or deleted, prior analyses for that document are marked stale. Trust deeds table showing a deed with status To be reviewed Select the deed to open the review screen: the deed itself on the left, extracted fields on the right. Each field carries a small reference marker (e.g. `1a`, `1b`, `2a`) — these link back to the exact location in the deed the value was extracted from, so you can verify quickly without re-reading the whole document. Correct any field that needs it directly in the form. When you're satisfied, select **I have reviewed and accept the data in this trust deed** and select **Save** — review and confirmation happen on this one screen, there's no separate confirm step. If the trust type could not be detected, it's shown as unclassified with the reasons why. Trust type is inferred automatically and isn't something you can set or override from the Portal — the analysis can't be confirmed until the deed is successfully classified. Once saved, confirmed parties are marked as an **Associated party** directly on the same screen, and appear as part of the organization's ownership and control structure. *** ## API Walkthrough The examples use the UAT base URL (`https://api.uat.frankie.one`); swap in your production base URL when you go live. ### Prerequisites Before running a trust analysis via API, make sure the following are in place: * **The Trust Analyzer enabled.** The `GLB-Trust-Analysis` workflow has to be enabled for your environment on the V2 platform. If you don't see it yet, contact your FrankieOne representative to have it turned on. * **An organization entity.** Trust analysis runs against an existing `organization`, the focus entity that holds or is associated with the trust. Create it first and keep its `entityId`. See [Managing Organizations](/docs/kyb/managing-organizations) for how to create one. * **The trust deed uploaded.** The deed must already be attached to that organization as a `TRUST_DEED` document. You upload it in Step 1 below and keep the returned `documentId`, which is what the workflow analyses. * **A service profile.** The `serviceName` of the Service Profile the organization is assessed against, for example `DEFAULT`. Your FrankieOne representative provides this when the workflow is set up. ### Step 1: Upload the Trust Deed The Trust Analyzer works on a deed that is already attached to the organization, so upload it first. Send the PDF as a base64-encoded attachment on a `TRUST_DEED` document, and keep the `documentId` from the response. You pass that `documentId` to the workflow in the next step. ```bash Request - Upload Trust Deed theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/documents' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "document": { "type": "TRUST_DEED", "attachments": [ { "data": "JVBERi0xLjQ...base64-encoded PDF..." } ] } }' ``` ### Step 2: Execute the Trust Analysis Workflow Execute `GLB-Trust-Analysis` against the organization's `entityId`. Pass the `documentId` of the uploaded trust deed in `executionVariables`. This is the only execution variable the workflow needs; the trust type is detected from the document, so you don't supply it. The optional `comment` is recorded on the workflow's audit trail. The response returns a `workflowExecutionId`. Keep it: you use it in the next step to track the execution. ```bash Request - Execute Trust Analysis Workflow theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/serviceprofiles/{{serviceName}}/workflows/GLB-Trust-Analysis/execute' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "executionVariables": { "documentId": "92de15f6-5717-4562-b3fc-2c963f6665a7" }, "comment": { "text": "Initiating trust deed analysis for onboarding" } }' ``` ```json Response - Execute Trust Analysis Workflow theme={null} { "entityId": "01993733-cfd5-7594-9e90-ec3ad06dd490", "requestId": "01K4VK7KWN6HEA43AQ0F13JZPT", "serviceName": "DEFAULT", "workflowExecutionId": "01K4VK7QDJG631AWFKWYVE85Z5" } ``` Re-executing on an unchanged trust deed reuses the existing valid analysis. No new analysis is run and you are not charged again. If the deed's attachment is later updated or deleted, prior analyses for that document are marked stale. ### Step 3: Track the Workflow Execution Trust analysis is asynchronous. The execute endpoint returns `202 Accepted` with a `workflowExecutionId`. Retrieve the execution result and poll until `workflowResult.workflowExecutionState` is no longer `IN_PROGRESS`. When analysis completes, the workflow result moves to `REVIEW`, indicating the extracted data is ready for you to review and confirm. Poll every 5 to 10 seconds. ```bash Request - Retrieve Workflow Execution Result theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/serviceprofiles/{{serviceName}}/workflows/GLB-Trust-Analysis/executions/{{workflowExecutionId}}' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` ### Step 4: Retrieve the Analysis Results Fetch the analyses for the document. Use the `showResults` query parameter to control which analyses are returned: `LATEST` (default), `COMPLETE`, or `CONFIRMED`. Each analysis carries a `status` (`PROCESSING`, `FAILED`, `COMPLETE`, or `CONFIRMED`), the detected trust `type`, the extracted parties, and a `references` map that points each extracted value back to its location in the deed. ```bash Request - Get Document Analyses theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/documents/{{documentId}}/analyses?showResults=LATEST' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` ```json Response - Document Analyses (Discretionary trust) theme={null} { "entityId": "01993733-cfd5-7594-9e90-ec3ad06dd490", "requestId": "01HN9XHZN6MGXM9JXG50K59Q85", "analyses": [ { "documentId": "92de15f6-5717-4562-b3fc-2c963f6665a7", "analysisId": "01K4VK7QDJG631AWFKWYVE85Z5", "status": "COMPLETE", "documentInformation": { "type": "TRUST_DOCUMENT", "trust": { "name": { "value": "The Doe Family Trust", "referenceIds": ["r1"] }, "type": { "detected": "DISCRETIONARY" }, "trustees": [ { "entityId": "org-1", "entityType": "ORGANIZATION", "referenceIds": ["r2"] } ], "settlors": [ { "entityId": "ind-1", "entityType": "INDIVIDUAL", "referenceIds": ["r3"] } ], "linkedOrganizations": { "org-1": { "entityType": "ORGANIZATION", "details": { "name": { "value": "Doe Nominees Pty Ltd" } } } }, "linkedIndividuals": { "ind-1": { "entityType": "INDIVIDUAL", "name": { "givenName": "Jane", "familyName": "Doe" } } }, "typeInformation": { "type": "DISCRETIONARY", "discretionary": { "appointors": [ { "entityId": "ind-1", "entityType": "INDIVIDUAL", "referenceIds": ["r3"] } ], "generalBeneficiaries": [ { "value": "The children of the settlor", "referenceIds": ["r4"] } ] } } } }, "references": { "r1": { "referenceId": "r1", "sourceId": "trust-deed", "location": { "page": 1 } }, "r2": { "referenceId": "r2", "sourceId": "trust-deed", "location": { "page": 1 } } } } ] } ``` If the trust type cannot be classified, `type.detected` is `UNKNOWN` and the trust details include the reasons under `typeInformation.unknown`. A trust type must be identified before the analysis can be confirmed. #### Understanding the result | Field | What it tells you | | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `status` | The state of this analysis: `PROCESSING`, `FAILED`, `COMPLETE` (ready to review), or `CONFIRMED` (reviewed and accepted). | | `documentInformation.trust.type` | The trust type. `detected` is what the analyzer classified from the deed; `provided` reflects a type you supplied ahead of time, if any. | | `trustees`, `settlors` | The core trust roles. Each entry points to an entity in one of the `linked*` maps by its `entityId`. | | `linkedIndividuals`, `linkedOrganizations`, `linkedUnknownEntities` | The extracted parties, keyed by id. A party that holds more than one role (for example, a settlor who is also an appointor) appears once here and is referenced from each role. | | `typeInformation` | Type-specific detail, keyed by the trust type. See [Supported Trust Types](/docs/kyb/trust-analyzer#supported-trust-types) on the overview page. | | `references` | Maps each extracted value back to where it was found in the deed, including the page number, so every field is traceable to its source. | ### Step 5: Confirm the Analysis Confirmation is the human sign-off gate: it is how a reviewer accepts the extracted structure for compliance use. To correct any extracted field, send the corrected `documentInformation` (and any updated `references`) in the request body; to accept the analysis as-is, send it back unchanged. Confirmation records your accepted version while keeping the original analysis as an audit trail, so you always retain what the analyzer originally produced alongside what was approved. You can confirm again later if something needs to change: the latest confirmation becomes the valid one and earlier confirmations are superseded, while the original analysis stays in place. Confirm against the original analysis (the entry with `status: COMPLETE`) returned by Step 4. ```bash Request - Confirm Analysis theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{{entityId}}/documents/{{documentId}}/analyses/{{analysisId}}/confirm' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "documentInformation": { "type": "TRUST_DOCUMENT", "trust": { "name": { "value": "The Doe Family Trust" }, "type": { "detected": "DISCRETIONARY" }, "trustees": [ { "entityId": "org-1", "entityType": "ORGANIZATION" } ], "settlors": [ { "entityId": "ind-1", "entityType": "INDIVIDUAL" } ] } } }' ``` ```json Response - Confirm Analysis theme={null} { "requestId": "01HN9XHZN6MGXM9JXG50K59Q85" } ``` Once confirmed, the workflow execution's result moves from `REVIEW` to `COMPLETE` — the organization no longer reads as work in progress once a reviewer has signed off. ### Step 6: Associate the Parties With a confirmed analysis in hand, link the extracted parties to the focus organization through the [relationships API](/api-reference/organization-relationships/add-or-update-relationships-for-an-organization). This attaches the trustees, settlors, beneficiaries, and other parties to the organization as `individual` and `organization` relationships, so the trust's structure is represented on the entity and available to the rest of your KYB process. *** ## Next Steps * [Trust Analyzer overview](/docs/kyb/trust-analyzer) — what the Trust Analyzer does, supported trust types, and FAQs. * [Executing Workflows](/docs/kyb/executing-workflows) — how `executionVariables` are passed when executing a workflow. * [Interpreting Workflow Results](/docs/kyb/interpreting-workflows-v2) — parse the full `workflowResult` object. * [Managing Organizations](/docs/kyb/managing-organizations) — create and manage the organization entity before running the workflow. * [Anti-Money Laundering](/docs/kyb/anti-money-laundering) — screen the parties extracted from the trust deed. # US Business Verification Source: https://docs.frankieone.com/docs/kyb/us-business-verification A step-by-step guide to verifying US-registered businesses, including Secretary of State filing records and business officers. ## Overview FrankieOne verifies US-registered businesses against authoritative US sources, returning Secretary of State filing records, the business's registered jurisdiction, and its officers. US verification is triggered automatically by the address country — you do not need to select a different workflow or endpoint. When you create an organization with a US address, the platform routes the verification to the appropriate US data source, and the enriched data is written back onto the same organization entity. The flow is the same four steps used for any KYB verification: Submit the business's name, address and EIN to create the entity. Run `GLB-Organization-Profile` against the returned `entityId`. Workflows run asynchronously — poll until the execution completes. Retrieve the organization to see the verified registration data. *** ## Implementation Guide ### Prerequisites Before you begin, ensure you have: * An account configured with a US-enabled KYB workflow. * API credentials — your `api_key` and `X-Frankie-CustomerId`. * Your `X-Frankie-CustomerChildID`, if your account is structured with child customer accounts. This header is optional; include it on every request when you need to act on behalf of a specific child account, and omit it otherwise. * Confirmation from your Customer Success Manager that US jurisdiction support is enabled on your account. The examples in this guide show the `api_key` and `X-Frankie-CustomerId` headers only. If you use child customer accounts, add `X-Frankie-CustomerChildID` to each request as well. ### Step 1: Create a US organization To create a US-based organization, submit at least one address with `country: "USA"` in your `POST /v2/organizations` request. US verification is triggered automatically based on the address country. #### Request Body Fields | Field | Required | Description | Example | | --------------------------------------------------------------------------- | -------- | ----------------------------------------------------------- | ----------------------------------------------------------------- | | `organization.addresses[]` | Yes | At least one business address, with `country` set to `USA`. | `{"country":"USA","longForm":"1100 Maple Dr, Phoenix, AZ 85001"}` | | `organization.details.name.name` | Yes | Legal registered business name. | `"Acme Corp"` | | `organization.jurisdictionalInformation.taxpayerIdentificationNumber.value` | Yes | The business's EIN. | `"55-5666777"` | | `serviceName` | Yes | Selects the service profile to assess against. | `"DEFAULT"` | #### Request ```bash Request - Create US Organization theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "organization": { "addresses": [ { "country": "USA", "longForm": "1100 Maple Dr, Phoenix, AZ 85001" } ], "details": { "name": { "name": "Acme Corp" } }, "jurisdictionalInformation": { "taxpayerIdentificationNumber": { "value": "55-5666777" } } }, "serviceName": "DEFAULT" }' ``` #### Response A successful request returns `201 Created`. ```json Response - 201 Created theme={null} { "organization": { "addresses": [ { "addressId": "019f3ba1-6b80-7b40-996d-a9ae88292a1b", "country": "USA", "longForm": "1100 Maple Dr, Phoenix, AZ 85001", "sourceId": "725e6311-4b23-4be2-924a-c350bd004d03", "status": "CURRENT", "type": "BUSINESS" } ], "createdAt": "2026-07-07T08:11:02Z", "details": { "name": { "name": "Acme Corp", "sourceId": "725e6311-4b23-4be2-924a-c350bd004d03", "type": "PRIMARY" } }, "entityId": "019f3ba1-6b80-7b29-8d39-b9f1fdc28db7", "entityType": "ORGANIZATION", "informationSources": { "725e6311-4b23-4be2-924a-c350bd004d03": { "provider": "MANUAL", "source": "Unknown", "isAuthoritative": false } }, "jurisdictionalInformation": { "taxpayerIdentificationNumber": { "value": "55-5666777", "sourceId": "725e6311-4b23-4be2-924a-c350bd004d03" } }, "schemaVersion": 2 }, "requestId": "01KWXT2THHWJ2EWPY7G6KQKRMY", "serviceProfiles": [ { "entityId": "019f3ba1-6b80-7b29-8d39-b9f1fdc28db7", "serviceName": "DEFAULT", "serviceProfileId": "5cfdade0-71c7-4c7a-b348-2a53959a9caa", "state": "INIT" } ] } ``` At this point, `informationSources` reflects only what you submitted — `provider` is `MANUAL` and `isAuthoritative` is `false`. Each entry is keyed by a generated `sourceId`, one per data source contributing to the record. Verified registration data is added once you run the workflow in Step 2. Retain the `entityId` from the response — you need it for every subsequent call. ### Step 2: Execute the workflow Run the `GLB-Organization-Profile` workflow against the organization's `entityId`. #### Request ```bash Request - Execute Workflow theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/workflows/GLB-Organization-Profile/execute' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' \ --header 'Content-Type: application/json' \ --data '{ "entityId": "019f3ba1-6b80-7b29-8d39-b9f1fdc28db7", "serviceName": "DEFAULT" }' ``` #### Response ```json Response - Workflow Started theme={null} { "entityId": "019f3ba1-6b80-7b29-8d39-b9f1fdc28db7", "requestId": "01KWXT2VG40KSG1X0RKBJHPKZF", "serviceName": "DEFAULT", "serviceProfileId": "5cfdade0-71c7-4c7a-b348-2a53959a9caa", "workflowExecutionId": "01KWXT2WH7TZEZ6987AE9VB1TN" } ``` Retain the `workflowExecutionId` — you need it to poll for the result. ### Step 3: Poll for results Workflow executions run asynchronously. Poll for the execution status using the `workflowExecutionId` returned in Step 2. #### Request ```bash Request - Get Workflow Execution theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{entityId}/serviceprofiles/DEFAULT/workflows/GLB-Organization-Profile/executions/{workflowExecutionId}' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` #### Response ```json Response - Execution Complete theme={null} { "workflowResult": { "workflowExecutionId": "01KWXT2WH7TZEZ6987AE9VB1TN", "workflowExecutionState": "COMPLETED", "status": "COMPLETE" } } ``` `workflowResult.workflowExecutionState` tells you whether the execution has finished: | State | Meaning | | ------------- | ---------------------------------------------------------------------- | | `IN_PROGRESS` | Still running — keep polling every few seconds. | | `COMPLETED` | Finished. Retrieve the enriched organization and verification results. | | `CANCELED` | Canceled before completion. | | `TERMINATED` | Terminated before completion. | | `ERROR` | Encountered an error. | | `TIMEOUT` | Timed out. | Check both fields. `workflowExecutionState` reports whether the execution finished; `workflowResult.status` carries the verification outcome (`COMPLETE`, `REVIEW`, `PASS`, `FAIL`, and others). A `COMPLETED` execution can still return an outcome such as `REVIEW` that requires a closer look. ### Step 4: Get the enriched organization Once the workflow completes, retrieve the organization to see the verified data that has been added to it. #### Request ```bash Request - Get Organization theme={null} curl --location 'https://api.uat.frankie.one/v2/organizations/{entityId}' \ --header 'api_key: YOUR_API_KEY' \ --header 'X-Frankie-CustomerId: YOUR_CUSTOMER_ID' ``` #### Response ```json Response - Enriched Organization theme={null} { "organization": { "addresses": [ { "addressId": "019f3ba1-6b80-7b40-996d-a9ae88292a1b", "country": "USA", "longForm": "1100 Maple Dr, Phoenix, AZ 85001", "status": "CURRENT", "type": "BUSINESS" }, { "addressId": "019f3ba1-7c0a-76ec-bafc-25dcf3e12294", "country": "USA", "longForm": "1000 Elm St, Atlanta, GA 30301", "subdivision": "GA", "type": "OTHER" } ], "details": { "jurisdiction": { "country": "USA", "subdivision": "GA" }, "name": { "name": "Acme Corp", "type": "PRIMARY" }, "registrationDetails": [ { "registeredName": { "name": "Acme Corp" }, "registeredSubdivision": "GA", "registrationNumber": "FN-XXXXXXX", "registrationStatus": { "unstructured": { "code": "GOOD_STANDING", "description": "Active-Good Standing" } }, "registry": "SOS", "registryDescription": "https://ecorp.sos.ga.gov/BusinessSearch" } ], "status": { "unstructured": { "code": "GOOD_STANDING", "description": "Active-Good Standing" } } }, "entityId": "019f3ba1-6b80-7b29-8d39-b9f1fdc28db7", "informationSources": { "d76b9d14-3661-484d-83d0-cc45ca86688e": { "provider": "", "isAuthoritative": true, "providerReference": "d1ce51c7-8f1b-4182-ae6d-bc14c7c1f167" } }, "officials": [ { "entityId": "c8a78d65-a4b4-4471-90c3-12370b0e11cc", "entityType": "INDIVIDUAL", "role": { "code": "CE", "description": "CEO" }, "title": "CEO" } ] } } ``` #### What Verification Adds | Field | What It Contains | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `details.jurisdiction` | The state in which the business is registered, as `country` and `subdivision`. | | `details.registrationDetails[]` | The Secretary of State filing record — registered name, subdivision, registration number, status, and a link to the state registry. `registry` is `SOS`. | | `details.status` | The business's overall standing, for example `GOOD_STANDING`. | | `officials[]` | The business's officers, each with an `entityId`, `role` code and `title`. | | `informationSources` | Gains an entry with `isAuthoritative: true` and a `providerReference`, alongside the original `MANUAL` entry. The `provider` value identifies the verifying data source — shown as `` in the example above. | | `addresses[]` | May gain additional addresses discovered during verification, distinguished by `type`. | Officers returned in `officials[]` are created as `INDIVIDUAL` entities. You can run individual KYC checks against them using their `entityId`. *** ## Next Steps Once verification has completed, parse the `workflowResult` object to understand the outcome of every check. For a complete breakdown of every field in the response, see **[Interpreting Workflow Results](/docs/kyb/interpreting-workflows-v2)**. *** ## Additional Resources * [Standard Workflows](/docs/kyb/standard-kyb-bundles) * [Executing a Workflow](/docs/kyb/executing-workflows) * [Error Handling](/docs/kyb/error-handling) * [FrankieOne Support](/docs/contacting-developer-support) # Integrating with OneSDK Source: https://docs.frankieone.com/docs/kyc-v2/features/idv-biometrics-onesdk Learn how to integrate FrankieOne's IDV and Biometrics services using the FrankieOne SDK (OneSDK) for a streamlined and efficient implementation. ## Introduction to OneSDK The FrankieOne SDK (OneSDK) is the recommended solution for integrating IDV and Biometrics services into your web and mobile applications. It is designed to simplify the implementation process by abstracting the complexities of direct API interactions and providing pre-built UI components to guide your users through the verification process. **Why Use the OneSDK?** * **Simplified Integration:** The SDK reduces development time by handling the low-level API calls for session creation, data submission, and result polling. * **Seamless User Experience:** Pre-built UI components ensure a consistent and intuitive user journey for document capture and biometric authentication. * **Enhanced Data Accuracy:** The SDK includes optimized workflows for capturing high-quality document images and biometric data, which improves verification success rates. * **Robust Error Management:** Built-in error handling and reporting mechanisms simplify troubleshooting and enhance the reliability of your integration. * **Continuous Updates and Support:** The SDK is actively maintained by FrankieOne, ensuring compatibility with the latest features, security standards, and provider updates. *** ## Implementation Steps Integrating the OneSDK involves a four-step process: obtaining a session token from your backend, initializing the SDK on your frontend, presenting the UI to the user, and handling the results. Before initializing the OneSDK on your client-side application, you must securely fetch a session token from your backend. This requires a server-to-server call to the FrankieOne authentication endpoint. **Never expose your API Key in frontend code.** ```javascript theme={null} // Example: Server-side code (Node.js) to fetch a session token import fetch from 'node-fetch'; const CUSTOMER_ID = 'YOUR_CUSTOMER_ID'; const API_KEY = 'YOUR_API_KEY'; const AUTH_ENDPOINT = '[https://backend.kycaml.uat.frankiefinancial.io/auth/v2/machine-session](https://backend.kycaml.uat.frankiefinancial.io/auth/v2/machine-session)'; async function fetchSessionToken() { try { const response = await fetch(AUTH_ENDPOINT, { method: 'POST', headers: { 'authorization': 'machine ' + Buffer.from(`${CUSTOMER_ID}:${API_KEY}`).toString('base64'), 'Content-Type': 'application/json', }, body: JSON.stringify({ permissions: { preset: 'one-sdk', reference: "your-unique-customer-reference", // A unique reference for the user session }, }), }); if (!response.ok) { console.error('Failed to fetch session token:', response.status); return null; } return await response.json(); } catch (error) { console.error('Error fetching session token:', error); return null; } } ``` In your frontend application, use the session token obtained in the previous step to initialize the OneSDK. You can also configure the SDK with a "recipe" to define the specifics of the verification flow, such as the number of documents to capture. ```javascript theme={null} // Example: Client-side code to initialize OneSDK import OneSDK from '@frankieone/one-sdk'; async function initializeOneSdk() { // This function should call your backend to get the session token const sessionTokenResult = await yourBackend.fetchSessionToken(); if (sessionTokenResult && sessionTokenResult.session) { const oneSdk = await OneSDK({ session: sessionTokenResult, mode: "production", // or "sandbox" recipe: { ocr: { maxDocumentCount: 3, }, }, }); return oneSdk; } else { console.error('Failed to initialize OneSDK due to missing session token.'); return null; } } ``` Once the SDK is initialized, you can call its methods to launch the pre-built user interface. This UI will guide the user through all the necessary steps, such as selecting their document type, taking photos, and completing the selfie/liveness check. The SDK emits events throughout the verification process. Your application should listen for these events to track the user's progress and handle the final outcome. Implement callbacks to manage success, error, or user cancellation scenarios. Please refer to the detailed OneSDK documentation for a complete list of events and how to handle them. *** ## Service Flows Handled by the SDK By using the OneSDK, you abstract away the complexity of the underlying service flows. The SDK seamlessly manages: * **Document Capture and Validation:** Ensures high-quality images are captured and submitted for analysis. * **Selfie Capture and Facial Comparison:** Guides the user through the selfie process and matches it against the document photo. * **Liveness Detection:** Verifies that the user is physically present, preventing spoofing attempts. * **Integration with IDV Providers:** Manages all communication with the underlying IDV and Biometrics vendors. # Reseller Checks with Experian AU Source: https://docs.frankieone.com/docs/kyc-v2/implementation-guide/experian-reseller-abn If you perform Experian AU credit header checks on behalf of another reporting entity, that entity's ABN needs to be supplied with each check. This guide shows how to pass the ABN via the individual's custom attributes. ## Overview Some customers act as a **reseller** — they run KYC checks on behalf of another business, and that business (not the reseller) is the AML/CTF reporting entity for the check. Experian AU requires the ABN of that end business to be supplied with every credit header check, so the enquiry can be attributed to the correct obligated entity. FrankieOne collects this ABN as a custom attribute on the individual and forwards it to Experian as `AMLObligatedEntityABN`. This applies only to **Experian AU credit header checks** performed through the Experian v2 connector. It has no effect on other data sources, and it is not needed by customers who are the reporting entity for their own checks. *** ## Enabling the feature Reseller ABN passthrough is enabled by FrankieOne on a per-configuration basis. Enabling it does two things: * Makes the `CustomerChannelReferenceIdentifier` custom attribute visible and mandatory in the FrankieOne Portal, so the ABN can be captured for profiles created manually. * Makes the attribute **required** for API-created entities — a check submitted without it fails validation before it reaches Experian. Contact [help@frankieone.com ](mailto:help@frankieone.com) to have reseller ABN passthrough turned on for your configuration. Until it has been enabled, the attribute is stored on the entity but not forwarded to Experian. *** ## Supplying the ABN Set a custom attribute named `CustomerChannelReferenceIdentifier` on the individual, with the end business's ABN as the value. The attribute can be set when [creating the individual](/docs/managing-individuals) or added later with an update — it simply needs to be present on the entity at the time the workflow runs. ```http HTTP Request theme={null} POST /v2/individuals ``` ```json JSON Request Body theme={null} { "individual": { "name": { "givenName": "Jane", "familyName": "Citizen" }, "dateOfBirth": { "year": "1992", "month": "08", "day": "15" }, "addresses": [ { "type": "RESIDENTIAL", "streetNumber": "123", "streetName": "Exhibition", "streetType": "Street", "locality": "Melbourne", "subdivision": "VIC", "postalCode": "3000", "country": "AUS" } ], "customAttributes": { "CustomerChannelReferenceIdentifier": { "type": "STRING", "value": "11111111111" } }, "consents": [ { "type": "GENERAL" }, { "type": "CREDITHEADER" } ] } } ``` ### Field reference | Field | Value | Notes | | :------------- | :----------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | | Attribute name | `CustomerChannelReferenceIdentifier` | Case-sensitive — it needs to match exactly. | | `type` | `STRING` | The ABN is sent to Experian as a string. | | `value` | The end business's ABN | 11 digits, no spaces. This is the ABN of the business the check is being performed **for**, not the reseller's own ABN. | Credit header consent is still required for Experian AU checks. The reseller ABN is in addition to — not a replacement for — the `CREDITHEADER` consent. See [Creating & Managing Individuals](/docs/managing-individuals#consents). *** ## What FrankieOne sends to Experian The attribute is forwarded in the request payload as an additional detail: ```xml theme={null} AMLObligatedEntityABN 11111111111 ``` The value sent is also recorded against the check in the audit trail. *** ## Behaviour when the ABN is missing | Configuration | Attribute supplied? | Result | | :-------------------------------- | :------------------ | :--------------------------------------------------------------------------------------------------- | | Reseller passthrough **enabled** | Yes | ABN forwarded to Experian as `AMLObligatedEntityABN`. | | Reseller passthrough **enabled** | No | The check fails validation. No request is sent to Experian, and no credit header result is produced. | | Reseller passthrough **disabled** | Either | The attribute is ignored and nothing is forwarded. | Because a missing ABN stops the check before it reaches Experian, set the attribute on the entity **before** executing the workflow. See [Error Handling](/docs/error-handling) for how validation failures are surfaced. # Single Name Handling Source: https://docs.frankieone.com/docs/kyc-v2/implementation-guide/single-name-verification Learn how to correctly format API requests to verify individuals with a single name (mononym) against various data sources, including the Australian DVS. ## Overview In many cultures, it is common for an individual to have only a single name (a mononym). The FrankieOne platform supports these cases, but correct data mapping is crucial as requirements vary significantly between different types of verification checks. This guide will walk you through the correct API implementation for handling single-name applicants to ensure successful verification and global compliance. *** ## General API Implementation The recommended approach for submitting a single name via the API is to populate the `familyName` and use a placeholder for the `givenName`. **Why this approach?** `familyName` is the only name field the API requires — `givenName` is optional. Many downstream data sources also have a mandatory requirement for a `familyName` or "Last Name" field. Placing the single name here ensures the request is valid and gives the highest compatibility across our network of data sources. ```json theme={null} { "individual": { "name": { "givenName": "-", "familyName": "Sukarno" } } } ``` Do not submit the single name in `givenName` with an empty or omitted `familyName` — `familyName` is required, so the request will be rejected. If you have an existing integration that places the single name in `givenName` and a placeholder in `familyName`, it will still be accepted, but we recommend migrating to the format above: the critical factor is meeting the requirements of the specific end data source you are checking against, and most require a populated family name. *** ## Verification Compatibility Support for single-name verification is **not universal**. It depends entirely on the rules of the end data source. Submitting a single name to an unsupported service will result in a "No Match" or an error. | Verification Type | Single Name Support | Notes | | :----------------------------------- | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | | **Credit Bureau Checks** | ⚠️ **Partial** | Support for single names varies. While some checks will succeed, others require both a first and last name and will fail. | | **Government ID Checks (DVS)** | ✅ **Yes (Conditional)** | Support depends on the document type. See [Australian DVS Formatting Rules](#australian-dvs-formatting-rules) below. | | **Australian Electoral Roll Checks** | ❌ **No** | This service requires both a first and last name and will not process a single-name entry. | | **Superannuation & Payroll Checks** | ❌ **No** | These services have mandatory first and last name fields with no available workaround. | | **Other KYC & AML Checks** | **Varies** | Compatibility depends on the specific check and region. We recommend following the standard `familyName` + hyphenated `givenName` format. | *** ## Australian DVS Formatting Rules The Australian Document Verification Service (DVS) matches the name you submit against the name held by the issuing authority. Because DVS is an exact-match service, a single name will only verify where the document itself records the individual under a single name. The general convention across all DVS document types is to place the single name in `familyName` and submit a placeholder in `givenName`: * Use a hyphen (`-`) as the `givenName` placeholder. This is the default and the format we recommend. * A full stop (`.`) is accepted as an alternative where a provider prefers it. * FrankieOne normalises the placeholder before the request reaches DVS, submitting a blank given name rather than the literal `-` or `.` character. | Document Type | `givenName` | `familyName` | Notes | | :-------------------------------- | :---------- | :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | | **Australian Passport** | `-` or `.` | The single name | Supported. The placeholder is converted to a blank given name before the check is sent. | | **ImmiCard** (`IMMIGRATION`) | `-` | The single name, exactly as printed on the card | Supported. Match the card's case, spelling and spacing exactly. | | **Driver's Licence** | `-` | The single name, exactly as printed on the licence | Follows the general convention. The licence record itself must hold a single name. | | **National Health ID (Medicare)** | `-` | The single name, exactly as printed on the card | Follows the general convention. The `supplementaryData.nameOnCardLine*` fields must also match the card as printed. | | **Birth Certificate** | `-` | The single name | Follows the general convention. Apply the same convention to `supplementaryData.registeredGivenName` and `supplementaryData.registeredFamilyName`. | | **Citizenship Certificate** | `-` | The single name, exactly as printed on the certificate | Follows the general convention. | | **Centrelink Card** | `-` | The single name, exactly as printed on the card | Follows the general convention. | | **Marriage Certificate** | `-` | The single name | Follows the general convention. Apply the same convention to the `supplementaryData.partner1*` and `supplementaryData.partner2*` name fields. | | **Name Change Certificate** | `-` | The single name | Follows the general convention. Apply the same convention to `supplementaryData.registeredGivenName` and `supplementaryData.registeredFamilyName`. | A single name will return a **No Match** if the issuing authority holds the individual under both a given and a family name. In that case, submit the name as it is recorded on the document rather than as a mononym. For the full field-by-field requirements of each document type, see [Australian Documents](/docs/australian-documents-v2). # Working With Addresses Source: https://docs.frankieone.com/docs/kyc/feature-guides/concepts-and-definitions/addresses ## Key Requirements When updating an existing address, always include the `addressId`. You can retrieve it from the `addresses` array in the entity response. The `country` field is mandatory and must use ISO 3166-1 alpha-3 codes (e.g., `AUS`, `USA`, `GBR`). ## V2 Address Model: What's Changed The v2 address schema introduces two key structural changes from v1: **1. `type` + `status` replaces `addressType`** In v1, address purpose and history were encoded in a single `addressType` field (e.g., `RESIDENTIAL1`, `RESIDENTIAL2`). In v2, these are separated: * `type` — what kind of address it is (e.g., `RESIDENTIAL`, `POSTAL`) * `status` — the temporal state of that address (`CURRENT`, `PREVIOUS`, `FUTURE`) **2. Field names align to global address standards** | v1 Field | v2 Field | Notes | | ------------- | -------------- | ---------------------------------------------------- | | `addressType` | `type` | See `Address-TypeEnum` below | | `town` | `locality` | Town, suburb, village, or city | | `suburb` | `neighborhood` | Only needed when suburb differs from locality | | `state` | `subdivision` | Use ISO 3166-2 sub-division code (e.g., `VIC`, `TX`) | | `region` | `district` | District, county, province, or cantonment | *** ## Address Types The `type` field accepts the following values: | Value | Description | | --------------------------- | ----------------------------------------------------------- | | `RESIDENTIAL` | Personal residential address | | `POSTAL` | Individual mailing address | | `BUSINESS` | Business address | | `REGISTERED_OFFICE` | Registered office address | | `PLACE_OF_BUSINESS` | Principal place of business | | `OFFICIAL_CORRESPONDANCE` | Business postal/mailing address | | `PLACE_OF_BIRTH` | Place of birth | | `OFFICE_LOCALITY` | Office locality | | `AUTHORITATIVE_RESIDENTIAL` | Authoritative residential address returned by a data source | | `OTHER` | Any other address type | Use `type` in conjunction with `status` to express address history. For example, a current home address is `type: RESIDENTIAL, status: CURRENT`. A previous home address is `type: RESIDENTIAL, status: PREVIOUS`. The v1 `RESIDENTIAL1` / `RESIDENTIAL2` pattern is not used in v2. Use `RESIDENTIAL` with `status: CURRENT` or `PREVIOUS` instead. *** ## Address Status The `status` field must be used alongside `type` to indicate the temporal state of the address. | Value | Description | | ---------- | ------------------------------------- | | `CURRENT` | The address is currently in use | | `PREVIOUS` | The address was used in the past | | `FUTURE` | The address is planned for future use | *** ## Address Structure Options ### Option 1: Structured Address (Recommended) Providing structured address components produces better matching results and improved data quality than long-form input. | Field | Type | Required | Description | | -------------- | ------ | ------------ | --------------------------------------------------------------------------------------- | | `addressId` | string | For updates | Assigned when an address is added. Must be included when modifying an existing address. | | `type` | string | | Address type. See `Address-TypeEnum`. | | `status` | string | | Address status: `CURRENT`, `PREVIOUS`, or `FUTURE`. Use with `type`. | | `unitNumber` | string | | Unit, apartment, flat, or suite number | | `buildingName` | string | | Name of the building, apartment block, or condominium | | `streetNumber` | string | | Property number on the street. Can be alphanumeric (e.g., `3A`) | | `streetName` | string | | Name of the street. See note below on `addressLine1` input. | | `streetType` | string | | Street type (e.g., `Road`, `Street`, `Ave`, `Circuit`) | | `locality` | string | | Town, village, suburb, or city | | `neighborhood` | string | | Suburb or neighborhood — only supply if you also need a separate `locality` value | | `subdivision` | string | | State or administrative sub-division. Use ISO 3166-2 code (e.g., `VIC`, `TX`) | | `district` | string | | District, county, province, or cantonment | | `postalCode` | string | | Postal or ZIP code | | `country` | string | **Required** | ISO 3166-1 alpha-3 country code (e.g., `AUS`, `USA`, `GBR`) | | `careOf` | string | | Individual or business at this address, if different from the entity name | | `validFrom` | Date | | Date this address first became active. Used primarily with business addresses. | | `validTo` | Date | | Date this address was no longer in use. Used primarily with business addresses. | ```json theme={null} { "addresses": [ { "type": "RESIDENTIAL", "status": "CURRENT", "unitNumber": "1", "streetNumber": "100", "streetName": "South", "streetType": "ST", "locality": "Sydney", "subdivision": "NSW", "postalCode": "2000", "country": "AUS" } ] } ``` When updating an existing address, include `addressId` to target the correct record. ```json theme={null} { "addresses": [ { "addressId": "", "type": "RESIDENTIAL", "status": "CURRENT", "streetNumber": "123", "streetName": "King", "streetType": "Street", "locality": "Melbourne", "subdivision": "VIC", "postalCode": "3000", "country": "AUS" } ] } ``` *** ### Option 2: Long-Form Address Use this format only when structured address components are not available. The API will attempt to parse `longForm` into its constituent fields. Results are not guaranteed — ambiguous or unparsable addresses will return an error. ```json theme={null} { "addresses": [ { "type": "RESIDENTIAL", "status": "CURRENT", "country": "AUS", "longForm": "LEVEL 8, 417 ST KILDA ROAD, MELBOURNE, VIC, 3004" } ] } ``` *** ## Using `streetName` for Combined Address Input If your system stores street details in a single field (commonly called `addressLine1`, e.g., `"42 Main Street"`), place the full value in `streetName`. The `streetName` field can accommodate combined address elements when discrete fields are unavailable. For best matching results, provide `streetNumber`, `streetName`, and `streetType` as separate fields wherever possible. * ✅ **Preferred:** `streetNumber: "42"`, `streetName: "Main"`, `streetType: "Street"` * ⚠️ **Acceptable fallback:** `streetName: "42 Main Street"` (combined `addressLine1` value) *** ## Read-Only Response Fields The following address fields are returned in API responses but cannot be set in request payloads: | Field | Description | | ---------------------- | ------------------------------------------------------------------------------------------ | | `addressId` | Assigned by FrankieOne when an address is first created | | `sourceId` | Links to the `informationSources` map — indicates which data source populated this address | | `unstructuredLongForm` | Raw, unformatted address as received from the source. Not normalised or standardised. | *** ## Additional Resources View the complete list of ISO 3166-1 alpha-3 country codes # Key Concepts Source: https://docs.frankieone.com/docs/kyc/feature-guides/concepts-and-definitions/core-api-concepts An overview of the fundamental building blocks of the FrankieOne platform, such as Entities, Workflows, and Risk Assessments. This guide introduces the primary building blocks of the FrankieOne platform. Understanding these core concepts is the first step toward a successful integration. For details on specific data structures like addresses and consent, see the [Key Data Objects](/docs/kyc/feature-guides/concepts-and-definitions/key-data-objects) page. For a full list of terms, visit the [Glossary](/docs/kyc/feature-guides/concepts-and-definitions/glossary-of-terms). ## Platform Building Blocks These are the fundamental concepts that power the FrankieOne platform. Click on any concept to learn more. An **Entity** is the central object in the FrankieOne platform, representing a single customer you want to verify. All information, checks, and results are linked to an entity. * An **Individual** is an entity type representing a single person. * An **Organization** is an entity type representing a business or other non-individual entity. A **Workflow** is a configurable, end-to-end process that runs a sequence of steps to verify an entity. You can design workflows to meet your specific risk and compliance requirements. A workflow is composed of steps such as KYC verifications, AML screening, IDV checks, and risk assessments. A **Service Profile** provides an overview of an entity's verification progress and risk status in the context of a specific product or service you offer. A single entity can have multiple service profiles, allowing you to apply different rules and risk policies for different products (e.g., a credit card vs. a home loan). A **Process Result** is the raw, granular data returned from a single check against a third-party data source (e.g., a match for a name from a government database). A workflow step evaluates one or more process results to determine its outcome. FrankieOne uses granular **Risk** metrics to calculate a customer's risk profile. During a workflow, an entity is scored against configurable risk factors (e.g., age, location, PEP status). The cumulative score determines the entity's overall risk level, which can trigger different actions like Enhanced Due Diligence (EDD). An **Issue** is a problem raised during a workflow that requires manual review or intervention. Issues are created for significant events, such as a failed KYC check or a match on a sanctions watchlist, and provide clear guidance on the next steps. ##### How The Concepts Connect A typical verification process follows this logical flow: 1. You create an **Entity** representing your customer. 2. You assign a **Service Profile** to the Entity for the product they are accessing. 3. You trigger a **Workflow** to begin verification. 4. The Workflow runs checks, generating **Process Results** from data sources. 5. A **Risk Assessment** is performed based on the results. 6. If problems occur, an **Issue** is created for review. *** ## Technical Architecture The FrankieOne API is built using the **REST (Representational State Transfer)** architectural style. This provides a simple, predictable, and scalable interface for interacting with all platform resources. By adopting REST, FrankieOne ensures that its API is flexible and easy to learn. All communication is performed over secure HTTPS using standard HTTP methods (like `GET`, `POST`, `PATCH`) and clear, resource-oriented URLs. This unified approach allows you to interact with different parts of the platform in a consistent way, supporting robust automation and integration with your systems. # Key Terms & Definitions Source: https://docs.frankieone.com/docs/kyc/feature-guides/concepts-and-definitions/glossary-of-terms ## Glossary A-Z A quick reference for other common terms. | Term | Explanation | | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Adverse Media | Negative news or information about an individual or entity found in reputable media sources. | | AML | **A**nti-**M**oney **L**aundering. Laws and procedures designed to combat the generation of income through illegal actions. | | AML Classification | The process of categorizing AML screening results, often involving manual review to determine if a potential match is a true positive or false positive. | | AML Screening | The process of checking an individual or entity against global watchlists, sanctions lists, and PEP lists. | | Audit | A record of actions performed within the platform, used for tracking and compliance purposes. | | Consent | Permission given by an individual for their information to be checked against various databases and external services. | | Decision | A critical juncture in the workflow that determines the workflow's status—be it PASS, FAIL, or REVIEW, based on the specific actions taken during the workflow. | | Entity | A single individual or organization within the FrankieOne platform that exists separately from other entities. Entities house information about the individual or organization, primarily any personally identifiable information (PII). | | IDV | **I**dentity **V**erification. The process of verifying an identity, often involving document scans, liveness checks, and facial comparison. | | Individual | A single person who can be verified within the FrankieOne platform. Individuals can have service profiles, workflows, and risk assessments related to them. | | Issue | A problem encountered during the execution of a workflow that hinders its successful completion and necessitates manual intervention. | | KYC | **K**now **Y**our **C**ustomer. The mandatory process of identifying and verifying the identity of clients to prevent fraud and financial crime. | | Organization | A business or non-individual entity that can be verified within the FrankieOne platform. | | PEP | **P**olitically **E**xposed **P**erson. An individual with a prominent public function, who may present a higher risk for potential bribery or corruption. | | Process Result | A granular piece of information used to determine the outcome of an action or step performed during a workflow. | | Risk | Granular risk metrics used to determine a customer's risk profile and identify potential money laundering activities. Entities are scored on these risk factors during workflow execution. | | Sanctions | Economic or trade restrictions imposed on specific individuals, entities, or countries by governments or international bodies. | | Service Profile | Provides a concise overview of an entity's progress within the context of a specific product or service. These profiles encompass various risk levels, workflows, and statuses. | | Watchlist | A list of individuals or entities subject to scrutiny under AML and sanctions regulations. | | Workflow | An end-to-end process that involves a series of steps that, when triggered, will enrich or verify stored entity information. Workflows are customizable and can be built to satisfy compliance requirements. | | Workflow Step | A specific action or check within a workflow, such as KYC verification, AML screening, or risk assessment. | # Key Data Objects Source: https://docs.frankieone.com/docs/kyc/feature-guides/concepts-and-definitions/key-data-objects These are the critical data structures you will work with when using the FrankieOne API. This guide details the primary data objects used in FrankieOne API requests and responses. Understanding these structures is essential for sending data correctly and interpreting the verification results. An **Address** object contains the location details for an entity. Providing a complete, structured address is critical for successful verification against data sources. Best Practices for Address Data For optimal verification results, always provide addresses using **structured fields** rather than the `longForm` string. Supplying each component—such as `streetNumber`, `streetName`, `locality`, and `country`—enables more accurate matching and validation. * **Break down addresses:** Always separate address components into their individual fields wherever possible. While `streetName` can combine `streetNumber`, `streetName`, and `streetType` if needed, providing each field separately yields the most accurate results. * **Address types:** * `RESIDENTIAL`: The primary address used to determine the entity’s country of residence and current living address. * `POSTAL`: A mailing address. If a `RESIDENTIAL` address is not provided, this will be used as the default residential address. * **Address status:** Use the `status` field to indicate if the address is current or future. This helps in understanding the context of the address. * **Updating addresses:** Always include the `addressId` (returned when the address was first added) to ensure the correct record is modified. * **Country codes:** Ensure the `country` field is a valid ISO-3166-1 alpha-3 code ([reference](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes)). * **Building details:** Include any building details, such as building level, in the `buildingName` field. #### Common Address Fields | Field Name | Description | Type | Required | | :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- | | `addressId` | Unique identifier for the address (used for updates). | String | No | | `country` | The **ISO-3166-1 alpha-3** country code (e.g., `AUS`). | String | Yes | | `type` | The type of address, e.g., `RESIDENTIAL`, `POSTAL`. Determines how the address is used in verification. | String (enum) | Yes | | `typeDescription` | A description of the address for reference. | String | No | | `unitNumber` | Unit, apartment, flat, or suite number. | String | No | | `streetNumber` | The number on the street (can be alphanumeric, e.g., `3A`). | String | No | | `streetName` | The name of the street. | String | Yes | | `streetType` | The street type, e.g., Road, St, Ave, Circuit. | String | No | | `buildingName` | The name of the building, apartment block, or condo. Include building level details here. | String | No | | `locality` | The locality, town, village, suburb, or city. | String | Yes | | `district` | The district, region, county, or province. | String | No | | `neighborhood` | The neighborhood or suburb. Use only if `locality` is already captured and additional detail is needed. | String | No | | `subdivision` | The administrative area, state, or subdivision. Abbreviations (e.g., "VIC") and full names (e.g., "Victoria") are acceptable. | String | No | | `postalCode` | The postal or zip code. | String | Yes | | `careOf` | Name of the individual or business at this address, if different from the entity's name. | String | No | | `longForm` | The full address as a single string. Use only if breaking down the address is not possible. If the separate fields are supplied, `longForm` will not be used when sending to providers. | String | No | | `status` | The status of the address (e.g., `PREVIOUS`, `CURRENT`, `FUTURE`). Should be used together with `TYPE` to provide more context. | String (enum) | No | | `validFrom` | The date when the entity started using this address. | Date | No | | `validTo` | The date when the entity will stop using this address. | Date | No | ##### Maximum Lengths for NZ Addresses For New Zealand addresses, the following maximum lengths are recommended: * **Address line 1** (building name + unit number + street name + street type): 256 characters * **Address line 2** (distinct to Frankie): 256 characters * **Suburb**: 50 characters * **City**: 50 characters * **Postcode**: 15 characters The **Consent** object is a mandatory part of any verification request. It confirms that you have permission from the user to perform the specified checks. The type of consent required depends on the data sources you intend to use. #### Common Consent Types | Consent Flag | Description | | :--------------- | :----------------------------------------------------------------------------------------------------------- | | `GENERAL` | The user has consented to standard name, address, and date of birth checks. | | `DOCS` | The user has consented to having their identity documents (e.g., passport) checked against official sources. | | `CREDITHEADER` | The user has consented to having their details checked against a credit bureau. This is a premium feature. | | `UNDER18` | A parent or guardian has provided consent for a user who is under 18 years of age. | | `PAYROLL` | This consent is used to allow access to verifying an identity using payroll data. | | `INSURANCE` | This consent is used to allow access to verifying an identity using workcover data. | | `SUPERANNUATION` | This consent is used to allow access to verifying an identity using superannuation data. | A **Document** object represents a piece of identification provided by the user, such as a passport, driver's license, or utility bill. ##### Document Class Guidance When creating a document object, set the `class` field to `IDENTITY` for documents used to verify a person's identity (such as passports or driver's licenses). This ensures the document is processed correctly for identity verification checks. #### Common Document Fields | Field Name | Description | | :-------------------- | :----------------------------------------------------------------------------------- | | `documentId` | The unique identifier for the document object within FrankieOne. | | `type` | The general type of document, such as `DRIVERS_LICENSE`, `PASSPORT`, `UTILITY_BILL`. | | `subtype` | A more specific description of the document type. | | `primaryIdentifier` | The main number on the document (e.g., license number or passport number). | | `secondaryIdentifier` | Any additional identifier on the document. | | `country` | The **ISO-3166-1 alpha-3** country code where the document was issued. | | `expiryDate` | The document's expiration date. | | `issueDate` | The document's date of issue. | An **Issue** is created by a workflow whenever a potential problem is detected that may require manual review. Your system should be designed to handle these issues, often by flagging the case for a compliance officer. #### Key Issue Fields | Field Name | Description | | :---------- | :-------------------------------------------------------------------------- | | `issueId` | The unique identifier for the issue. | | `category` | The general category of the issue (e.g., `AML`, `DUPLICATE`, `DOCUMENT`). | | `issue` | The specific type of issue (e.g., `SANCTION`, `DATA_COMPARISON`). | | `severity` | The severity level, such as `INFO`, `REVIEW`, or `BLOCK`. | | `isCleared` | A boolean indicating if the issue has been manually resolved in the Portal. | The **Risk Assessment** object is returned as part of a `workflowResult` and contains the calculated risk profile for the entity based on your configured policies. #### Key Risk Fields | Field Name | Description | | :------------ | :--------------------------------------------------------------------------------------- | | `riskLevel` | The overall risk level assigned to the entity, such as `LOW`, `MEDIUM`, or `HIGH`. | | `riskScore` | The numerical score that corresponds to the risk level. | | `riskFactors` | An array of the specific factors that contributed to the score (e.g., `age`, `country`). | Interpreting the status of a verification is critical. The API provides results at both the overall **workflow** level and for each individual **step**. #### Common Workflow Statuses (`workflowResult.status`) This tells you the final outcome of the entire verification process. | Status | Meaning | | :-------- | :---------------------------------------------------------------------------------------------- | | `PASS` | The workflow completed and the entity passed all required checks. | | `FAIL` | The workflow completed and the entity did not pass the required checks. | | `REVIEW` | The workflow produced results that require manual review. Check the `issues` array for details. | | `BLOCKED` | The workflow was blocked from completing, often due to a blocklist match. | #### Common Step Results (`workflowStepResults[].result`) This tells you the outcome of a specific check within the workflow. | Result | Meaning | | :--------- | :-------------------------------------------------------------------------------------------------------------- | | `MATCH` | The check was successful and found a positive match. | | `NO_MATCH` | The check was successful but did not find a matching record. | | `HIT` | A match was found against a watchlist (e.g., AML or fraud). This is a positive outcome that requires attention. | | `CLEAR` | No match was found against a watchlist. This is a positive outcome. | | `ERROR` | The step could not be completed due to a system or provider error. | *** # Understanding Issues Source: https://docs.frankieone.com/docs/kyc/feature-guides/concepts-and-definitions/kyc-issue-creation A guide to the types of issues that can arise during KYC workflows and how to handle them. > ***Note:***\ > *In the FrankieOne v2.0.0 API, an “issue” is a fundamental concept used to communicate problems, errors, or specific outcomes that require attention. Issues can arise from simple input validation errors to complex workflow results that require manual review.* *** ## The Structure of an Issue An issue is typically represented as an Issue object, which contains details about what went wrong and where. While the exact structure can vary slightly depending on the context (e.g., a synchronous API error vs. a workflow result), it generally contains the following key fields: | Field | Type | Description | | :------------ | :----- | :-------------------------------------------------------------------------- | | issue | string | Human-readable description of the problem | | issueLocation | string | Context/location where the issue was identified (e.g., `VALIDATE-entityId`) | | issueType | string | *(Optional)* Category for the issue | **Example: 400 Bad Request Error Response** ```json theme={null} { "errorCode": "API-0400", "errorMsg": "Multiple Errors: See Issues list", "details": [ { "issue": "entityId in path must be of type uuid: \"test\"", "issueLocation": "VALIDATE-entityId" } ], "requestId": "01HM5XJ7VASZ3EJMB1VQGTBFJ4" } ``` *** ## How Issues are Created Synchronous errors occur when an API request cannot be fulfilled due to issues like invalid authentication, malformed requests, or server-side problems. The API returns a standard Error object with a relevant HTTP status code (e.g., 400, 401, 500). | Field | Description | | :-------- | :----------------------------------------------------- | | errorCode | Unique FrankieOne code for the error (e.g., AUTH-0002) | | errorMsg | Summary of the error (e.g., Unauthorized) | | details | Array of Issue objects detailing each problem | **Common Error Scenarios:** * **400 Bad Request:** Validation errors (e.g., malformed entityId) * **401 Unauthorized:** Missing or invalid api\_key * **404 Not Found:** Resource does not exist * **5xx Server Error:** Internal platform issues When a workflow runs, the platform performs a series of checks. If any check produces a result that requires attention, a Workflow-Issue object is generated and included in the workflow execution summary. | Field | Type | Description | | :-------- | :------ | :------------------------------------------------------------- | | issueId | string | Unique identifier for the issue | | category | string | Broad classification (e.g., AML, KYC, FRAUD, DOCUMENT) | | issue | string | Specific issue type (e.g., SANCTION, NOT\_FOUND) | | severity | string | Severity level (INFO, REVIEW, BLOCK, WARNING, CRITICAL, ERROR) | | isCleared | boolean | Indicates if the issue has been manually addressed/resolved | | createdAt | string | Timestamp when the issue was created | **Example: Workflow-Execution-Summary with an Issue** ```json theme={null} { "workflowName": "kyc_onboarding", "workflowExecutionId": "01HNE42K1T6JXV41S8W5W8W6X8", "status": "REVIEW", "issues": [ { "issueId": "01HNE42K2G4S8Z6G8Y4Y7B3A2C", "category": "AML", "issue": "SANCTION", "severity": "CRITICAL", "isCleared": false, "createdAt": "2024-05-15T02:18:11.365Z" } ] } ``` *** ## Issue Severity Levels | Severity | Description | | :------- | :--------------------------------------------------- | | INFO | Informational only, no action required | | REVIEW | Requires manual review before proceeding | | BLOCK | Blocks workflow completion until resolved | | WARNING | Indicates a potential problem, but not blocking | | CRITICAL | Serious issue, typically blocks onboarding | | ERROR | Error state, usually requires technical intervention | *** ## Workflow Issue Categories This table lists the general categories that an issue can fall under. | Category | Description | | :------------ | :-------------------------------------------------------------------------- | | AML | Anti-Money Laundering issues. | | BAD\_DATA | Indicates that the data provided is invalid or incorrect. | | BIOMETRICS | Issues found during a biometrics check. | | BLOCKLISTED | The entity has a hit on a blocklist. | | DECEASED | Indicates that the entity is deceased. | | DEVICE | Issues found during device checks. | | DOCUMENT | Issues found during a document check. | | DUPLICATE | Indicates that the entity has duplicates. | | EXPIRY | Indicates that a process or document for the entity has expired. | | FRAUD | Possible fraud detected. | | IDV | Issues found during an Identity Verification (IDV) process. | | INFORMATIONAL | Informational messages that are not issues but are required to be returned. | | KYC | Issues found during a Know Your Customer (KYC) process. | | SYSTEM | System-level issues. | | VERIFY | Issues found during a verification process. | | VISA | Issues found during a visa check. | | WATCHLIST | Issues found during a watchlist check. | | ACTIVITY | Issues found during an activity process. | *** ## Workflow Issue Types & Descriptions | Issue Type | Description | | :-------------- | :---------------------------------------------------- | | PEP | The entity has Politically Exposed Person (PEP) hits. | | SANCTION | The entity has sanction hits. | | MEDIA | The entity has adverse media hits. | | WATCHLIST | The entity has watchlist hits. | | INTERNAL\_MATCH | The entity matched an internal watchlist. | | AML\_ISSUE | General AML issue. | | Issue Type | Description | | :------------------------ | :------------------------------------------------- | | BAD\_DATA\_NAME | Name is required but missing or unusable. | | BAD\_DATA\_DOB | Date of Birth is required but missing or unusable. | | BAD\_DATA\_ADDRESS | Address is required but missing or unusable. | | BAD\_DATA\_ID | ID is required but missing or unusable. | | BAD\_DATA\_EMAIL | Email is required but missing or unusable. | | BAD\_DATA\_MOBILE | Mobile is required but missing or unusable. | | BAD\_DATA\_DEVICE | Device is required but missing or unusable. | | BAD\_DATA\_IP\_ADDRESS | IP Address is required but missing or unusable. | | BAD\_DATA\_EMAIL\_ADDRESS | Email Address is required but missing or unusable. | | Issue Type | Description | | :---------------- | :---------------------------------------- | | MATCHED\_INTERNAL | The entity matched an internal blocklist. | | MATCHED\_SHARED | The entity matched a shared blocklist. | | MATCHED\_EXTERNAL | The entity matched an external blocklist. | | BLOCKED | General blocklist issue. | | Issue Type | Description | | :--------- | :--------------------------------------------------- | | DECEASED | The person whose data is being verified is deceased. | | Issue Type | Description | | :-------------------- | :------------------------------ | | DEVICE\_FRAUD\_MATCH | Fraud detected on the device. | | DEVICE\_INVALID | The device is invalid. | | FRAUD\_LIST | The entity is on a fraud list. | | FRAUD\_CHECK | Fraud detected during checks. | | FRAUD\_DEVICE | Device fraud detected. | | FRAUD\_IP\_ADDRESS | IP address fraud detected. | | FRAUD\_EMAIL\_ADDRESS | Email address fraud detected. | | FRAUD\_PHONE\_NUMBER | Phone number fraud detected. | | FRAUD\_INCOMPLETE | The fraud check was incomplete. | | FRAUD\_ISSUE | General fraud issue. | | Issue Type | Description | | :--------- | :------------------------------------------- | | DUPLICATE | The entity is a duplicate of another entity. | | Issue Type | Description | | :------------- | :------------------------------------- | | REQUIRES\_KYC | KYC process needs to be re-initiated. | | REQUIRES\_IDV | IDV process needs to be re-initiated. | | REQUIRES\_AML | AML process needs to be re-initiated. | | REQUIRES\_VISA | Visa process needs to be re-initiated. | | Issue Type | Description | | :-------------------- | :-------------------------------------------------------- | | DATA\_COMPARISON | Data comparison issue. | | DATA\_VALIDATION | Data validation issue. | | DATA\_CONSISTENCY | Data consistency issue. | | VISUAL\_AUTHENTICITY | Visual authenticity issue. | | IMAGE\_INTEGRITY | Image integrity issue. | | COMPROMISED\_DOCUMENT | Document is compromised. | | LIVENESS\_DETECTION | Liveness detection failed. | | DOCUMENT\_COMPARISON | Document comparison issue. | | OCR | The OCR data does not match what was entered by the user. | | Issue Type | Description | | :------------- | :----------------------------------------------------------------------- | | CREDIT\_HEADER | Credit header information was returned as part of a credit agency check. | **KYC Summary Issue Codes** | Issue Type | Description | Condition | | :--------- | :------------------------------------------- | ------------------------------------------------------------------------------- | | PARTIAL | The KYC check was only partially successful. | Some data matched, but the total results were insufficient to pass the ruleset. | | NOT\_FOUND | No match was found for the given data. | The overall KYC ruleset requirements were not satisfied. | **KYC Detailed Issue Codes** | Issue Type | Description | Condition | | :--------------------------- | :----------------------------------------- | ----------------------------------------------------------------------------------------------- | | NO\_GOVID\_MATCH | GovID required but no GovID match. | A Government ID was required, but no match was found in the system. | | INSUFFICIENT\_GOVID\_MATCH | GovID required but insufficient matches. | Government ID matches were found, but they did not meet the required count. | | NO\_DOB\_MATCH | DOB required but no DOB match. | A Date of Birth check was required, but no match was found. | | INSUFFICIENT\_DOB\_MATCH | DOB required but insufficient matches. | Date of Birth matches were found, but they are below the required threshold. | | NO\_ADDRESS\_MATCH | Address required but no address match. | An Address check was required, but no match was found. | | INSUFFICIENT\_ADDRESS\_MATCH | Address required but insufficient matches. | Address matches were found, but they did not meet the full verification requirements. | | NO\_NAME\_MATCH | Name required but no name match. | A Name check was required, but no match was found. | | INSUFFICIENT\_NAME\_MATCH | Name required but insufficient matches. | Name matches were found, but they were fewer than the ruleset requires. | | PARTIAL\_MATCH | General partial match. | Multiple fields were verified successfully, but the overall verification resulted in a failure. | For more information on how these conditions are evaluated and configured, please refer to the [KYC Ruleset](https://docs.frankieone.com/docs/ekyc-rulesets) page. | Issue Type | Description | | :--------------- | :---------------------------------------------------------------------- | | SERVICE\_TIMEOUT | All providers have timed out. | | SERVICE\_ERROR | All providers have returned an error or an internal error has occurred. | | Issue Type | Description | | :----------- | :----------------------------------- | | DENY\_LIST | The entity matched a visa deny list. | | VISA\_FAILED | Visa check failed from the provider. | | Issue Type | Description | | :--------------- | :----------------------------- | | ACTIVITY\_AML | AML-related activity issue. | | ACTIVITY\_FRAUD | Fraud-related activity issue. | | ACTIVITY\_DEVICE | Device-related activity issue. | *** ## Workflow Issue Severity Levels Severity levels help determine the urgency and impact of an issue. Use them to drive workflow logic and user experience. | Severity | Description | | :------- | :------------------------- | | INFO | Informational only. | | REVIEW | Requires review. | | BLOCK | Blocks further processing. | | WARNING | Warning, but not blocking. | | CRITICAL | Critical issue. | | ERROR | Error encountered. | *** ## Best Practices for Handling Issues * **Monitor the`issues` array** in workflow results to drive automated decisions or flag cases for manual review. * **Map`issueLocation`** to specific fields in your UI for targeted feedback. * **Use`severity`** to determine whether to block, warn, or allow user progression. * **Log`issueId` and `requestId`** for troubleshooting and support. > ***Tip:***\ > *By building logic around issues, you can streamline compliance, automate onboarding, and improve user experience.* *** # Creating & Managing Individuals Source: https://docs.frankieone.com/docs/managing-individuals A guide to the complete lifecycle of an 'individual' entity, from creation and retrieval to updates and deletion. The `individual` is the core object in the FrankieOne platform, representing a single customer. This guide covers the complete lifecycle of creating and managing these entities via the API. ### Video Guide