# Docs finoOS is a modular platform for open banking and data analytics. It provides secure and compliant APIs to access, enrich, and analyze financial, personal, and company-related data. The platform is designed for enterprise use cases and enables seamless integration of individual modules or complete workflows. All APIs follow consistent principles regarding security, data protection, and scalability. Use this documentation to explore available APIs, understand authentication and authorization, and integrate finoOS services into your applications. --- # Overview > Introduction The finoOS API provides a secure and reliable way to access financial services powered by **[fino](https://fino.ai)**. After obtaining a `client identifier` and a `client secret`, you can start using the **finoOS API** as described in the following sections of this documentation. If you are interested in using finoOS and haven't obtained access yet, please [contact](https://fino.digital/en/contact/) our team to get started. Access to the different features of the **finoOS API** is controlled via **Scopes**. Each scope grants access to a specific set of endpoints for a given domain, such as banking, categorization, or other analytics features. For more details, see the **[Scopes](./scopes.mdx)** section. If you are unsure which scopes are required for your use case, please contact our team. ## Environments All API endpoints are available in the following environments: - **Test:** `https://os.test.fino.cloud/api` - **Production:** `https://os.fino.cloud/api` ## Legacy API Documentation If you used finoOS previously to v1.21.0 you might be familiar with the legacy API documentation available at [Legacy API](https://os.fino.ai/docs/). Although everything from the legacy documentation is still valid we did removed some fields, endpoints as they are marked deprecated and might be removed in the future. Therefore, we recommend using the new documentation for all your integration needs. --- # Overview > Principles To integrate with the finoOS API, we assume familiarity with the following technical principles: - **[Web APIs](https://en.wikipedia.org/wiki/Web_API)** - **[HTTP(S)](https://en.wikipedia.org/wiki/HTTPS)** - **[Representational State Transfer (REST)](https://en.wikipedia.org/wiki/Representational_state_transfer)** - **[JSON](https://en.wikipedia.org/wiki/JSON)** For additional background, please refer to the linked resources above. If you are unsure how to integrate with the finoOS API after reading this documentation, feel free to **[contact us](mailto:support.analytics@fino.digital)**. --- # Overview > Scopes Your **client** is assigned a set of scopes during creation. **Scopes** define which services and endpoints can be accessed by your **client**. At the moment, scopes can only be assigned or modified manually by one of our engineers. If you would like to enable or disable specific scopes or services, please **[contact us](mailto:support.analytics@fino.digital)**. To determine which scopes are required for your integration, refer to the endpoints and services you plan to use. The required scope is documented for each endpoint. ## Banking Scopes | Scope | Description | |--------------------|-----------------------------------------------------------------------------| | banking-fetch | Fetch raw accounts and transactions | | banking-connect | Connect to XS2A interfaces to retrieve accounts and transactions and enable automatic daily data synchronization | | banking-upload | Upload raw accounts and transactions | | banking-payment | Authorize payment initiation | ## General Analysis Scopes | Scope | Description | |--------------------|-----------------------------------------------------------------------------| | categorization | Transaction categorization and tagging based on analysis | | account-detection | List of uploaded or XS2A-retrieved accounts, including additional detected accounts | | account-history | Daily balances for all accounts | | contracts | Detection of contracts based on tags and other characteristics | | cockpits | Consolidated overview of analysis results | ## Person Analysis Scopes | Scope | Description | |-----------------------------------|-----------------------------------------------------------------------------| | credit-rating | Indicators used for credit rating calculations | | renter-information | Summary of salary and rental information | | name-verification | Comparison of the provided user name with the registered account holder’s name | | person-income-alimony | Alimony and maintenance payments received | | person-income-child-benefit | Child allowances from public authorities or family members | | person-income-investment | Capital income from securities, dividends, and investment returns | | person-income-other | Other miscellaneous income sources not covered by specific categories | | person-income-parental-allowance | Parental leave benefits and allowances | | person-income-pension | Pension and retirement income payments | | person-income-rental | Rental income from real estate and property leasing | | person-income-salary | Employment income including wages, salaries, and bonuses | | person-income-self-employment | Income from self-employment and freelance work | | person-spending-credit | Loan instalments and credit repayments | | person-spending-credit-card | Credit card payments and monthly settlements | | person-spending-insurance | Insurance premiums and policy payments | | person-spending-investment | Investment contributions, savings plans, and securities purchases | | person-spending-other | Miscellaneous recurring and irregular expenses | | person-spending-rent | Rent and lease payments for residential and commercial properties | | person-risk-back-debit | Number of returned direct debits per calendar month | | person-risk-garnishment | Number of garnishment payments per calendar month | | person-risk-collection | Number of payments to debt collection agencies per calendar month | | person-risk-gambling | Number of gambling transactions with accumulated amounts per month | | person-risk-overdraft-amount | Number of overdraft days per calendar month with corresponding amounts | | person-household-budget | Overview of income and spending patterns | | person-adult-check | Verifies the age status of account holders | ## Company Analysis Scopes | Scope | Description | |---------------------------|-----------------------------------------------------------------------------| | company-cash | Analysis and overview of company cash flow | | company-credit | Information on company credits, loans, and leasing agreements | | company-customer-supplier | Evaluation of customer and supplier relationships | | company-foreign-payment | Analysis of foreign and international transactions | | company-insurance | Overview and analysis of existing insurance contracts | | company-internal-booking | Detection and evaluation of internal bookings between connected accounts | | company-investment | Analysis of investments, such as savings and securities | | company-liquidity | Calculation and monitoring of company liquidity, including monthly income and expenses | | company-risk | Assessment of company risk indicators, such as account overdrafts | | company-spending-other | Analysis of other recurring expenses | | company-staff | Evaluation of personnel costs and employee-related data | | company-top-category | Overview of the most relevant expense categories | ## Other Scopes | Scope | Description | |---------------------------|-----------------------------------------------------------------------------| | webhooks | Create webhooks to receive notifications and analysis results | | categorization-categories | Category hierarchy with localized descriptions (German and English) | | companies | Search for companies to retrieve additional company data | | companiesLogo | Search for companies and retrieve their logos | --- # Overview > Authentication To authenticate with the **finoOS API**, you exchange your `client identifier` and `client secret` for a temporary pair of **[JSON Web Tokens (JWT)](https://en.wikipedia.org/wiki/JSON_Web_Token)** using the **[Authenticate](/api#tag/Authentication/operation/authentication-authenticate)** endpoint. The response includes an `accessToken`, which must be provided with every subsequent API request via the `Authorization` header. --- # Overview > Users # Users In most integrations, you manage end users on your side and want to access information about their financial situation. The first step is to create a corresponding **User** in the finoOS API. See **[Add User](/api#tag/Users/operation/users-add-user)**. Depending on your use case, you can create different types of users: - **Person User**: Represents an individual person. This is the most common user type. - **Company User**: Represents a company or organization. Choosing the correct user type is important, as it determines the available scopes, categorization, and associated data. As described in previous sections, you must provide an `accessToken` in the `Authorization` header for all requests. Additionally, you can change the tenant context of a user. For more details, see **[Tenancy](./tenants)**. # User Lifecycle The typical lifecycle of a user in the finoOS API consists of the following steps: 1. Create a user 2. Connect the user’s financial data (read more about user connections in the **[Connections](../banking/overview)** section) 3. Analyze the user’s financial data - automatically after the data has been received, or - manually by calling the **[Analyze User](/api#tag/Users/operation/users-trigger-analysis)** endpoint 4. Retrieve analytics results via: 1. **[Webhooks](../analytics/webhooks)**, or 2. Polling the relevant analytics endpoints 5. Delete the user when no longer needed: 1. Automatically by setting an `expiresIn` value when creating the user 2. Manually using the **[Delete User](/api#tag/Users/operation/users-delete-user)** endpoint It is recommended not to delete users immediately after data retrieval, as you or your end users may want to update data or request support later. A common approach is to set an `expiresIn` value when creating the user (for example, one week). Steps 2–4 represent the analysis lifecycle and can be repeated as often as required, for example if an end user connects multiple bank logins. Learn more about the analysis lifecycle in the **[Analysis Lifecycle](./analysis-lifecycle)** section. --- # Overview > Tenancy finoOS provides a multi-tenant architecture that allows you to manage different groups of users and their data separately. This is particularly useful when building applications for multiple applications, use cases, or customer segments. Tenants are managed using the `TenantID` request header. If the `TenantID` header is omitted, a default tenant with the name of your `client identifier` is used automatically. Additional tenants are created automatically when a new `TenantID` value is provided in a request. It is important to note that the `TenantID` used when creating a user must also be used for all subsequent requests related to that user. ## Naming Tenants When choosing a `TenantID`, ensure that it is prefixed with your `client identifier`, followed by a hyphen (`-`). ## Example A client with the `client identifier` `example-client` starts using the finoOS API. If no `TenantID` header is provided, a tenant named `example-client` is created automatically, and all users are stored within this tenant. Later, the client introduces a new use case that requires a separate group of users. In this case, it is recommended to use a different tenant identifier, for example `example-client-awesome-app`. This approach simplifies user and data management, improves separation of concerns, and makes potential support cases easier to handle. **Note:** A user created under the tenant `example-client` cannot be accessed using the tenant `example-client-awesome-app`, and vice versa. --- # Overview > Analysis Lifecycle The analysis lifecycle describes how financial data is processed and analyzed within finoOS. Each analysis run is identified by a unique `correlationID`, which is used to track its execution and retrieve results. An analysis can either be triggered automatically or manually, depending on the integration flow. Have a look at the following two common patterns that are ## Using Banking Connect This sequence applies when end users connect their bank accounts using the fino Banking Connect UI. ### Step-by-step flow 1. **Create a user** - Create the user with `automaticAnalysis: active` (default). - This ensures that an analysis is triggered automatically after a successful connection. 2. **Start a banking connect session** - Call the **[Connect User Session](/api#tag/Banking-Connect/operation/banking-create-connect-user-session)** endpoint. - The response includes a `Finoos-Correlation-Id` header. - This correlation ID identifies the entire connect + analysis process. 3. **End user connects their data** - The end user completes the connection using the fino Banking Connect UI. - If the connection succeeds, the analysis is triggered automatically. 4. **Track analysis progress** Depending on your integration, you can: - **Receive a webhook notification** containing the `Finoos-Correlation-Id`, or - **Poll analytics correlation endpoints**, for example **[Get Categorization Correlation](/api#tag/Categorization/operation/categorization-get-correlation)** Possible responses: - `404` → Analysis still in progress or connection was canceled - `200` → Analysis completed successfully ## Uploading existing financial data via Banking Upload This sequence applies when you already have financial data and want to upload it before triggering analysis. ### Step-by-step flow 1. **Create a user** - Create the user with `automaticAnalysis: suspended`. - This prevents automatic analyses on incomplete data. 2. **Upload financial data** - Upload, update, and patch accounts and transactions using **[Banking Upload](/api#tag/Banking-Upload)**. - Repeat this step until all required data has been provided. 3. **Trigger analysis manually** - Call the **[Analyze User](/api#tag/Users/operation/users-trigger-analysis)** endpoint. - The response includes a `Finoos-Correlation-Id` header identifying this analysis run. 4. **Track analysis progress** Depending on your integration, you can: - **Receive a webhook notification** containing the `Finoos-Correlation-Id`, or - **Poll analytics correlation endpoints**, for example **[Get Categorization Correlation](/api#tag/Categorization/operation/categorization-get-correlation)** Possible responses: - `404` → Analysis still in progress - `200` → Analysis completed successfully ## Best Practices - Prefer using webhooks to receive notifications when analyses are completed. This provides results as soon as they are available and reduces the number of required API calls. - If polling is required, implement an exponential backoff strategy to reduce load on both your systems and ours. Do not poll more than twice per second initially, and increase the interval over time. - Only start polling after a successful connection or upload. If the user canceled the process or an error occurred, no analysis results will be available. --- # Overview > Errors Error responses of the API will return one of the **[HTTP error codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)** listed below in the **Status Codes and Errors** table. Error responses will contain a **[JSON-encoded](https://en.wikipedia.org/wiki/JSON)** body of the following format: ```json { "type": "forbidden", // short error type "message": "forbidden. No access to this resource" // detailed error message } ``` **Status Codes and Errors** | Code | Name | Description | |------|-------------------|-----------------------| | 200 | OK | Success | | 201 | Created | Success | | 202 | Accepted | Success | | 204 | No Content | Success, but no response content | | 400 | Bad Request | The provided request was invalid. Most of the times, the given format is incorrect. | | 401 | Unauthorized | Invalid authorization. Check your access tokens or tenant id and secret | | 403 | Forbidden | Access for the given resource or operation was denied | | 404 | Not Found | The requested resource doesn't exist | | 409 | Conflict | The request conflicts with a previous request | | 429 | Too Many Requests | Too many requests hit the API too quickly. Rate limit exceeded | | 5xx | Server Errors | Unknown finoOS server errors | For concrete responses and their possible error responses have a look at the **[API Reference](/api)** section. --- # Overview > Quick Start (Agents) # Quick Start for Agents This guide walks through integrating the finoOS API from scratch in five steps: authenticate, create a user, connect banking data, track analysis, and retrieve results. **Base URL:** `https://os.test.fino.cloud/api` All paths below are relative to this base URL. *** ## Machine-Readable Documentation For AI agents and coding assistants, the full documentation is available in plain-text formats optimized for LLM consumption: | Resource | URL | Description | |----------|-----|-------------| | **llms.txt** | [https://docs.fino.cloud/llms.txt](https://docs.fino.cloud/llms.txt) | Documentation index with agent instructions and API endpoint listing | | **llms-full.txt** | [https://docs.fino.cloud/llms-full.txt](https://docs.fino.cloud/llms-full.txt) | Complete documentation as a single Markdown file (~29k tokens) | | **API Reference** | [https://docs.fino.cloud/api](https://docs.fino.cloud/api) | Interactive OpenAPI documentation | Load `llms.txt` first for an overview, then fetch `llms-full.txt` if you need the full context. *** ## Step 1 -- Authenticate Exchange your client credentials for an access token. **`POST /api/auth`** (content type: `application/x-www-form-urlencoded`) ```bash curl -X POST https://os.test.fino.cloud/api/auth \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "grant_type=client_credentials" ``` **Response (200):** ```json { "access_token": "eyJhbGciOi...", "expires_in": 300, "token_type": "Bearer", "scope": "banking categorization ...", "session_state": "1e2212ad-..." } ``` Use the `access_token` value in all subsequent requests as a Bearer token: ``` Authorization: Bearer ``` The token expires after `expires_in` seconds (typically 300). Re-authenticate before it expires. *** ## Step 2 -- Create a User Create a user to represent the person or company whose financial data you will analyze. **`POST /api/users`** ```json { "type": "person", "automaticAnalysis": "active" } ``` - **type** -- `person` or `company`. Determines available analytics scopes. - **automaticAnalysis** -- Set to `active` (default) for Banking Connect flows so analysis runs automatically. Set to `suspended` for manual upload flows. - Optionally set `expiresIn` (e.g. `"P7D"` for 7 days) to auto-delete the user later. The response includes a `userId` -- store it for all user-scoped requests. *** ## Step 3 -- Connect Banking Data Choose one of two paths depending on whether you have existing banking data. ### Path A: Banking Connect (recommended) Redirect end users to the fino Banking Connect UI to log in to their bank. **`POST /api/users/{user-id}/banking/connect`** The response contains: - A redirect URL for the end user to complete the bank connection. - A **`Finoos-Correlation-Id`** response header -- save this to track the analysis. Once the user completes the connection, analysis is triggered automatically (if `automaticAnalysis` is `active`). ### Path B: Manual Upload Upload account and transaction data you already possess. 1. **Upload accounts and transactions:** **`POST /api/users/{user-id}/banking/accounts`** with a JSON body containing an `accounts` array (each with transactions). 2. **Trigger analysis manually:** **`POST /api/users/{user-id}/trigger-analysis`** The response includes a **`Finoos-Correlation-Id`** header. *** ## Step 4 -- Track Analysis Use the `Finoos-Correlation-Id` from Step 3 to monitor progress. Two options: ### Option A: Webhooks (recommended) Subscribe to webhook notifications to receive the correlation ID and status when analysis completes. See the [Webhooks](../analytics/webhooks) documentation for setup. ### Option B: Polling Poll the correlation endpoint: **`GET /api/users/{user-id}/categorization/correlation`** Pass the correlation ID as a query parameter or header. | Status | Meaning | |--------|---------| | `200` | Analysis completed successfully | | `404` | Analysis still in progress (or connection was canceled) | **Polling best practices:** - Start polling only after a successful connection or upload. - Use exponential backoff. Do not poll more than twice per second initially. - Increase the interval over time. *** ## Step 5 -- Retrieve Results Once analysis is complete, fetch results from the analytics endpoints relevant to your enabled scopes: | Endpoint | Description | |----------|-------------| | `GET /api/users/{user-id}/categorization` | Categorized transactions | | `GET /api/users/{user-id}/analysis/person/income` | Person income analysis | | `GET /api/users/{user-id}/analysis/company/cashflow` | Company cashflow analysis | | `GET /api/users/{user-id}/analysis/company/credits` | Company credits analysis | All analytics endpoints follow the same pattern: `GET /api/users/{user-id}/analysis/{scope}`. Refer to the [API Reference](/api) for the full list of available analytics endpoints matching your enabled scopes. *** ## Summary | Step | Method | Endpoint | |------|--------|----------| | Authenticate | `POST` | `/api/auth` | | Create User | `POST` | `/api/users` | | Banking Connect | `POST` | `/api/users/{user-id}/banking/connect` | | Upload Accounts | `POST` | `/api/users/{user-id}/banking/accounts` | | Trigger Analysis | `POST` | `/api/users/{user-id}/trigger-analysis` | | Track Progress | `GET` | `/api/users/{user-id}/categorization/correlation` | | Get Results | `GET` | `/api/users/{user-id}/categorization` | --- # Banking > Overview The Banking module provides a secure and reliable way to access and manage financial data of bank accounts. For more information, please refer to the detailed sections on **[Connection Flows](./connect-flows/overview.mdx)** and **[Manual Upload](./manual-upload/adding-data.mdx)**. ## Supported Data Import Flows In order to facilitate the import of bank data for analysis, the Banking module supports two primary methods for data import: direct import via bank interfaces and manual upload of bank data for analysis. ### Direct Import via Bank Interfaces - In this flow, the connection is established via our **Universal Bank Access** platform. - As such, this flows redirects user to our application, from where the user can select his bank and login to his bank account (using their standard online banking access). - Through this process, the user grants us a consent to retrieve and synchronize their bank data. - The hereby retrieved data is then accessible to the enabled Analytics modules. - For more references, please see the **[Connect Flows](./connect-flows/overview.mdx)** section. #### Multi Banking Naturally, our system also supports multi banking access. As such, users can connect multiple bank accounts by following this recommended procedure: - For a new user use **[Create Connect User Session](/api#tag/Banking-Connect/operation/banking-create-connect-user-session)** to connect the first bank account. You may include the query parameter `multiple=true`, so that the user is directly redirected to the management UI after the first connection, which allows them to easily connect more accounts. - Further accounts can be added with **[Create Management Session](/api#tag/Banking-Connect/operation/banking-create-management-session)** which by default has an overview UI of the connected accounts. Also, in this step you may set the query parameter `addBankLogin=true` which then skips the overview UI and starts a connect flow for an additional account so that you can seamlessly connect multiple accounts. - Likewise, please see the **[Connect Flows](./connect-flows/overview.mdx)** section for more details on the connection process and the available endpoints. *** ### Manual Upload of Bank Data for Analysis - Alternatively, clients can upload data manually for analysis. - Accordingly, direct retrieval via a bank interface is not required as the data is provided directly by the client themselves. - For more references, please see the **[Manual Upload](./manual-upload/adding-data.mdx)** section. *Please note that this method is typically used in scenarios where direct bank access is not feasible or when clients prefer to provide their data manually. Also, modifying bank data retrieved via bank interfaces is not intended through these endpoints, per regulatory requirements. Accordingly, only manually uploaded data is allowed for manipulation.* --- # Banking > Connect Flows > Overview The Banking Connect Flows enable seamless integration of bank accounts into your application, allowing users to connect their financial institutions securely and efficiently. This overview provides a high-level understanding of the key components and processes involved in the connect flows. ## Key Components - **Connect User Session**: This is the initial step where a user initiates the connection process. A session is created to manage the user's interaction with the banking interface. - **Management Session**: After the initial connection, users can manage their connected bank accounts through a management session. This session provides an overview of all linked accounts and allows for additional connections. - **Banking Interface**: While we aim to provide a seamless experience, parts of the connection - especially authentication and consent - are handled directly by the bank. These steps follow the bank’s own technical standards and regulatory requirements (such as PSD2). Please note, that different interfaces at the same bank can lead to different available account types and different user experiences during the connection process. - **Bank Login**: This represents the user's connection to their bank account and the consent granted for accessing their bank data. - **Recurring User**: Users can be marked as recurring (`recurring=true`) for automatic synchronization of their bank data at regular intervals. Automatic synchronization requires `storeSecrets=true` on the same connect request (default: `true`); if explicitly set to `false`, transactions only refresh when a synchronization session is triggered manually. - **Consent**: User consent is crucial for accessing bank data. The system manages consent expiration and renewal to ensure compliance with regulations. - **Strong Customer Authentication (SCA)**: The connect flows incorporate SCA mechanisms to enhance security during the authentication process. --- # Banking > Connect Flows > Establishing a Connection The Banking Connect Flows provide a structured process for users to securely link their bank accounts to your application. This guide outlines the steps involved in establishing a connection, from initiating a session to managing user consent and authentication. ## Steps to Establish a Connection 1. **Create a Connect User Session** - Initiate the connection process by creating a connect user session using the **[Create Connect User Session](/api#tag/Banking-Connect/operation/banking-create-connect-user-session)** endpoint. - This session will provide you with a redirect URL to our **Universal Bank Access** platform. - Also, this flow automatically creates a new user for the provided ID. If you intend to connect multiple bank accounts for the same user, please use the **[Create Management Session](/api#tag/Banking-Connect/operation/banking-create-management-session)** endpoint instead. 2. **Redirect User to Universal Bank Access** - Upon entering our **Universal Bank Access** platform, the user may search their respective bank they intend to connect to. - After selecting their bank, the user may need to select what type of account to connect (e.g., Checking, Savings, Credit Card, etc.), depending on the bank's configuration. This is typically required for banks that support multiple account types. Please make sure, that the user selects the correct account type to ensure proper data retrieval. 3. **User Authentication and Consent** - The user will be guided through the bank's authentication process, which may include entering their credentials and completing any required Strong Customer Authentication (SCA) steps. - After successful authentication, the user will be prompted to grant consent for data access. - Once consent is granted, the connection is established, and the user is redirected back to your application. *Please note that there are several types of SCA mechanisms that may be employed during the authentication process, depending on the bank's requirements. Generally, we differentiate between the following SCA procedures:* - *Embedded: The authentication process occurs within our Universal Bank Access platform, providing a seamless user experience.* - *Decoupled: The authentication process is handled through a separate device or application, such as a mobile banking app.* - *Redirected: The user is redirected to the bank's website to complete the authentication process.* *There are several mechanisms that banks may use to implement SCA which results in multiple varying user experiences. The required mechanism is determined by every bank and the selected account types, so the exact flow may differ between banks and even account types within the same bank. In any case, our Universal Bank Access platform will guide the user through the appropriate steps to ensure compliance with SCA requirements.* *Should you encounter any issues during the connection process, please refer to our **[Troubleshooting Guide](/docs/banking/connect-flows/troubleshooting.mdx)** for assistance or feel free to contact our **[support team](/docs/support)** for further help.* --- # Banking > Connect Flows > Consent Management ## Bank Logins and Bank Connections In order to establish a connection to a bank account, a **bank login** must be created. As such, every bank login is associated with a **bank connection**. Additionally, every bank login is identifiable through a unique identifier. As already mentioned in the **[Overview](./overview.mdx#key-components)**, a bank login is a technical entity that represents the user's consent for accessing their bank data. Each bank login is associated with one or more bank accounts, and it serves as the basis for managing the connection to the bank. In our system's hierarchy, a bank login stands directly below the user level and above the individual bank accounts. Bank logins are crucial for any process, that involves retrieving or synchronizing bank data. Without a valid bank login, our Banking module in unable to access the respective bank's system. Naturally, we provide endpoints to manage bank logins, including retrieving their synchronization status, creating synchronization sessions, and deleting logins when necessary: - **[Get Logins Synchronization Status](/api#tag/Banking-Connect/operation/banking-get-logins-synchronization-status)** - **[Create Synchronization Session](/api#tag/Banking-Connect/operation/banking-create-synchronization-session)** - **[Delete Login](/api#tag/Banking-Connect/operation/banking-delete-login)** ## Consent Management A **consent** authorizes the Banking module to fetch bank data for a specific bank connection. At any given time, there can only be one valid consent for a unique bank login. Accordingly, there is no concept of multiple consents for the same bank login, as a new consent will automatically invalidate the previous one. In addition to that, there is no concept of an account-level consent, as the consent is always associated with the bank login, which can include multiple accounts. Multiple different bank logins can be created for the same bank, as explained before in the **[Overview](./overview.mdx#key-components)**. Typically, as a rule of thumb, a user can create only one bank login for a unique bank account. However, there are exceptions to this rule, as some banks handle the login process entirely on their side, which can lead to multiple bank logins for the same bank account. We try to prevent this as much as possible, but still in some cases, we can only detect a duplicate connection after the connection process has been completed. Disconnecting a bank login will result in the revocation of the associated consent, and the respective bank connection to that login will be deactivated as well. The same of course applies when just deleting a bank login. Similarly, disconnecting or deleting a user will also lead to the revocation of all consents and deactivation of all bank logins associated with that user. ### Detecting an Expired Consent A valid consent is a mandatory prerequisite for our synchronization feature to work properly. Typically, single-access scenarios, where the user only connects their bank account once and does not intend to synchronize it on a regular basis, have no need to worry about consent expiration, as the consent is only required for the initial connection process. As such, if your use case only involves a one-time connection without any further synchronization, you can simply ignore consent expiration, as it will not affect your use case. Since a valid consent is required for retrieving bank data and triggering any process at the bank itself, it is crucial that we provide mechanisms to inspect the status of a consent. For that very reason, we provide multiple ways to check if a consent is still valid or if it has expired: 1. **[Via Sync Status Endpoint](/api#tag/Banking-Connect/operation/banking-get-logins-synchronization-status)** - This endpoint returns the synchronization status for each bank login of one user, including: - `status`: Shows if a consent is valid (`OK`), if a consent renewal through new Strong Customer Authentication is required (`SCA_REQUIRED`) or if there was any error during the last synchronization attempt (`SYNC_FAILED`). - `active`: Indicates if automatic background synchronization is currently enabled. - `lastSynchronization`: Timestamp of the last successful data sync. - `bankLoginId` and `userId`: Identifiers for tracking the specific login and user. - If `status` is `SCA_REQUIRED` or `SYNC_FAILED`, the consent has expired and needs to be renewed. 2. **[Via Get Synchronization Status Paginated](/api#tag/Banking-Connect/operation/banking-get-synchronization-status-paginated)** - This endpoint provides a paginated list of synchronization statuses for bank logins, allowing you to efficiently check the status of multiple users and their associated bank logins. 3. **[Via a Webhook Event](/api#tag/Webhooks)** - If a webhook for error events is subscribed, the event `ubasyncerror` will be triggered if automatic banking sync cannot be completed. When the `type` is **`CHALLENGE_REQUIRED`**, the user consent has expired and a user action is required to renew the consent. Otherwise, automatic synchronization will be disabled for the respective bank login. *Unfortunately, there is no way to prevent consent expiration, as it is a requirement by the banks and regulatory authorities to ensure that users regularly review and renew their consents for data access. Also, not all banks provide the same consent duration, so the expiration time can vary significantly between different banks and even between different account types within the same bank. Lastly, the information about the exact expiration time of a consent is not provided by the banks, so there is no way to predict when a consent will expire, apart from when the initial consent is granted, which typically has a validity of 90 days, but can be shorter or longer depending on the bank's policies.* ### Consent Renewal We currently provide two options for renewing an expired consent, which can be chosen based on your specific use case and user experience preferences: #### **a) Manual Renewal via the User Interface** 1. Use our **[Create Management Session](/api#tag/Banking-Connect/operation/banking-create-management-session)** endpoint to create a management session for the user, which will provide you with a redirect URL to our **Universal Bank Access** platform. 2. After redirecting the user to the management session, they will be able to see an overview of all their connected bank accounts and manage them accordingly. 3. To renew the consent, initiate a synchronization for the respective bank login, which will automatically trigger a challenge for the user to complete the consent renewal process. #### **b) Automatic Renewal via API** 1. Use our **[Create Synchronization Session](/api#tag/Banking-Connect/operation/banking-create-synchronization-session)** endpoint to trigger a synchronization for the respective bank login. 2. This automatically initiates a **challenge**, prompting the user to renew consent. Once consent is successfully renewed, the bank connection is reactivated, and data retrieval can continue. *Please note that in both cases your user needs to be actively involved in the consent renewal process, as the user must complete the necessary Strong Customer Authentication (SCA) steps to grant a new consent.* --- # Banking > Connect Flows > Webhooks and Bank Data Delivery In combination with both procedures for importing bank data, the system provides multiple mechanisms to ensure that the retrieved bank data is delivered to you in a timely and efficient manner. Of course, there are several endpoints available to retrieve the bank data on demand, but we also provide mechanisms to automatically send the bank data to you without the need for you to trigger a request. This is especially useful for recurring connections, where the bank data is automatically synchronized on a regular basis, and you want to receive the updated data immediately after each synchronization. For this very reason, we provide webhooks: ### Webhook Call After Bank Account Integration Once a bank account is successfully connected, the system automatically sends bank data via webhook - provided that the configuration is correct. For more information on how to set up webhooks, please refer to our **[webhooks specification](/api#tag/Webhooks/Setup)**. For this type of webhook there is no more differentiation between recurring and non-recurring users, as the webhook is triggered immediately after the connection process is completed, regardless of the user's recurring status. ### Automatic Synchronization via Scheduler This webhook type works only with **recurring users**, as it is triggered after each successful synchronization of the bank connection. After each successful synchronization, the system automatically sends the updated bank data via webhook, ensuring that you receive the most recent data without any delay. This is especially useful for use cases that require regular updates of bank data, such as financial management applications, budgeting tools, or any other application that relies on up-to-date financial information. Please note that the synchronization is executed automatically at regular intervals, there is no configuration available to change the synchronization frequency or schedule. #### Synchronization Frequency and Scheduling Behavior The automatic synchronization is executed **twice daily**. Each sync cycle processes all eligible recurring users sequentially. The following scheduling characteristics apply: - **Newly created recurring users** are enrolled in the next available sync cycle. Depending on when the user was created relative to the current cycle, the first synchronization may occur in the subsequent cycle rather than the current one. - **Execution order and timing** within a sync cycle depend on the number of enrolled users and their distribution. This means that individual sync executions may experience slight delays depending on the overall queue position. - **There is no guaranteed fixed time** at which a specific user's synchronization will be executed. The system processes all users within the cycle window, but the exact timing for each user may vary. To verify that synchronization has been completed for a specific user, use the **[Get Logins Synchronization Status](/api#tag/Banking-Connect/operation/banking-get-logins-synchronization-status)** endpoint and check the `lastSynchronization` timestamp. ### Manual Synchronization As mentioned before, you can also trigger a manual synchronization for a specific bank login using our **[Create Synchronization Session](/api#tag/Banking-Connect/operation/banking-create-synchronization-session)** endpoint. For recurring connections, the synchronization is executed immediately provided there is still a valid consent available. For non-recurring connections, the synchronization requires explicit end-user consent and is executed asynchronously, as the user needs to complete the necessary Strong Customer Authentication (SCA) steps to grant a new consent. Once the bank data has been successfully retrieved, the system delivers the updated data via webhook. --- # Banking > Connect Flows > Banking Embed Integration Embedded integration allows you to place the finoOS Banking Connect user interface directly within your application. Rather than redirecting end users to an external page, the entire bank connect flow — from bank selection through credential entry to consent — happens inside your product. This provides a seamless experience where users never leave your application context. Under the hood, the Banking Connect UI is loaded in a sandboxed iframe that communicates with your host application via the browser's `postMessage` API. finoOS offers two integration paths that build on this mechanism: | | Iframe Integration | Widget Integration | |---|---|---| | **Approach** | Embed the Banking Connect UI directly via an ` ``` :::caution Important Both the `sandbox` and `allow` attributes are required for UBA to function correctly. Do not remove individual sandbox permissions. ::: ### 4. Listen to PostMessage Events UBA communicates with the parent window via `window.postMessage`. Always validate the message origin. ```javascript window.addEventListener('message', (event) => { // Security: only accept messages from UBA if (event.origin !== 'https://uba.fino.run') { return; } const { type, message, payload, user } = event.data; switch (type) { case 'ready': console.log('UBA loaded, version:', payload.version); break; case 'bank-select': console.log('Bank selected:', message.bank.shortName); break; case 'bank-login': console.log('Login initiated for:', message.bank.shortName); break; case 'bank-connect': console.log('Accounts connected:', message.accountIds); console.log('Bank login ID:', message.bankLoginId); // Use accountIds to fetch transaction data via finoOS API break; case 'bank-disconnect': console.log('Bank disconnected:', message.bankLoginId); break; case 'redirect': console.log('Redirecting to:', message.url, 'reason:', message.reason); break; case 'state': console.log('State change:', message); break; case 'ERROR': console.error('UBA error:', message); break; case 'EXIT': console.log('User exited the flow'); break; } }); ``` ### 5. Events Reference #### Events sent from UBA to the parent window | Event Type | When | Payload | |---|---|---| | `ready` | Iframe has loaded and initialized | `{ version, features? }` | | `bank-select` | User selected a bank | `{ bank: { bankCode, shortName, icon } }` | | `bank-login` | User submitted bank credentials | `{ bank }` | | `bank-connect` | Accounts successfully connected | `{ accountIds, bankLoginId }` | | `bank-accounts` | Accounts loaded on management screen | `{ accounts }` | | `bank-sync` | User triggered account sync | Sync challenge details | | `bank-disconnect` | User removed a bank connection | `{ bankLoginId }` | | `bank-redirect` | Redirect-based login started | Redirect details | | `redirect` | UBA is about to redirect the user | `{ url, reason }` | | `handle-redirect` | Redirect callback received | Redirect context | | `state` | TAN challenge or redirect state changed | State details | #### Additional granular events | Event Type | Description | |---|---| | `BANK_SEARCH_INIT` | Bank search initialized | | `BANK_LOGIN_SUCCESS` | Bank login succeeded | | `BANK_LOGIN_ERROR` | Bank login failed | | `BANK_LOGIN_TIMEOUT` | Bank login timed out | | `BANK_LOGIN_CONFLICT` | Conflicting bank login detected | | `BANK_LOGIN_ABORT` | Bank login aborted | | `BANK_ACCOUNT_SELECT` | Account selection started | | `BANK_ACCOUNT_SELECT_SUCCESS` | Accounts selected successfully | | `BANK_ACCOUNT_SELECT_ERROR` | Account selection failed | | `BANK_ACCOUNT_SELECT_TOGGLE` | Account toggle changed | | `BANK_REDIRECT_SUCCESS` | Redirect login succeeded | | `BANK_REDIRECT_ERROR` | Redirect login failed | | `BANK_SYNC_SUCCESS` | Sync completed | | `BANK_SYNC_ERROR` | Sync failed | | `TAN_CHALLENGE_SUBMIT` | TAN submitted | | `TAN_CHALLENGE_SUCCESS` | TAN challenge passed | | `TAN_CHALLENGE_ERROR` | TAN challenge failed | | `EXIT` | User exited the flow | | `ERROR` | General error occurred | | `SUCCESS` | Operation succeeded | ### 6. Handling the Redirect Callback After a successful bank connect, UBA redirects the user to your `redirectURL` with query parameters appended: ``` https://myapp.com/callback?userIdentifier=a1b2c3d4&sessionId=eyJhbG... ``` On your callback page, extract these parameters to continue working with the finoOS API: ```javascript const params = new URLSearchParams(window.location.search); const userIdentifier = params.get('userIdentifier'); const sessionId = params.get('sessionId'); ``` :::tip In embedded mode you typically handle the flow entirely via postMessage events (especially `bank-connect`) and may not need the redirect callback at all. Set `redirectURL` anyway as a fallback. ::: ### 7. Theming You can customize UBA's appearance in two ways: setting a **color scheme** (light/dark mode) and providing a **theme** object with specific color overrides. Both can be used independently or combined. #### Color Scheme Control light and dark mode via the `colorScheme` URL parameter: ```javascript iframeUrl.searchParams.set('colorScheme', 'dark'); ``` | Value | Behavior | |---|---| | `light` | Light mode (default) | | `dark` | Dark mode | | `system` | Follows the user's OS preference via `prefers-color-scheme` | The color scheme is resolved with this precedence: **URL parameter > tenant config > default (`light`)**. #### Theme Color Overrides Pass a `theme` parameter as a JSON-encoded object to override individual colors: ```javascript iframeUrl.searchParams.set('theme', JSON.stringify({ primaryColor: '#1A73E8', secondaryColor: '#34A853', backgroundColor: '#FFFFFF' })); ``` Supported color keys: | Key | Default | Description | |---|---|---| | `primaryColor` | `#F7C708` | Primary brand color (buttons, highlights) | | `secondaryColor` | `#288CD1` | Secondary brand color | | `backgroundColor` | `#F8F9FA` | Page background | | `accentColor` | `#288CD1` | Accent elements | | `textColor` | `#363636` | Body text | | `linkColor` | `#F7C708` | Links | | `infoColor` | `#3e8ed0` | Info alerts and badges | | `successColor` | `#48c78e` | Success states | | `warningColor` | `#ffe08a` | Warning states | | `dangerColor` | `#f14668` | Error and danger states | All values must be valid hex colors (3 or 6 digits, with or without the `#` prefix). #### Combining Color Scheme and Theme You can use `colorScheme` and `theme` together. For example, enable dark mode while overriding the background and text colors: ```javascript iframeUrl.searchParams.set('colorScheme', 'dark'); iframeUrl.searchParams.set('theme', JSON.stringify({ backgroundColor: '#272727', textColor: '#FBF8F6' })); ``` :::tip Theming can also be configured at the tenant level via the fino tenant service. Tenant-level theme settings apply as defaults and can still be overridden by URL parameters. ::: ### 8. Error Codes When errors occur, the event payload may include one of these error codes: | Code | Description | |---|---| | `INVALID_PIN` | User entered invalid PIN | | `INVALID_OTP` | Invalid one-time password | | `MISSING_TOKEN` | No authentication at provider API | | `ACCESS_BLOCKED` | Access to bank backend blocked | | `HBCI_ERROR` | Unknown HBCI protocol error | | `OFFLINE_ERROR` | Bank is offline | | `BANK_ERROR` | Bank reported a system error | | `NOT_SUPPORTED` | Bank not supported | | `ACCESS_DENIED` | Provider API error | | `SCA_REQUIRED` | Strong customer authentication required | | `INVALID_CONSENT` | Consent is invalid | | `AUTH_NOT_COMPLETED` | Authentication not completed (redirect flow) | | `UNKNOWN` | Unexpected error | *** ## Option 2: Widget Integration (via npm) The [`@finodigital/uba-widget`](https://www.npmjs.com/package/@finodigital/uba-widget) npm package wraps the iframe integration into a developer-friendly API. Under the hood it uses the exact same iframe mechanism, so all events and parameters described above apply. The key differences are: - **No manual iframe HTML** — The package creates and manages the iframe for you, including all required `sandbox` and `allow` attributes. - **Automatic origin validation** — Message origin checks are built in. - **Clean event API** — Events are dispatched as standard `CustomEvent`s on the element instead of raw `postMessage`. No need to parse `event.data` manually. - **Programmatic control** — Methods like `reload()`, `destroy()`, `setSession()`, and `postMessage()` give you full control over the widget lifecycle. ### Quick Setup ```bash npm install @finodigital/uba-widget ``` #### As a Web Component ```html ``` #### Programmatic API ```javascript import { createUbaWidget } from '@finodigital/uba-widget'; const widget = createUbaWidget({ sessionId: 'eyJhbG...', userIdentifier: 'a1b2c3d4', service: 'myapp', tenant: 'mycompany', hideHeader: true, colorScheme: 'dark', theme: { primaryColor: '#1A73E8', backgroundColor: '#272727' }, origin: 'https://uba.fino.run', }); document.getElementById('uba-container').appendChild(widget.element); await widget.ready(); widget.on('bank-connect', ({ payload }) => { console.log('Connected:', payload.accountIds); }); // Later: update session, reload, or clean up widget.setSession('newSessionId', 'newUserIdentifier'); widget.reload(); widget.destroy(); ``` For the complete API reference, configuration options, and advanced usage, see the full documentation on npm: **[@finodigital/uba-widget on npm](https://www.npmjs.com/package/@finodigital/uba-widget)** *** ## Environments | Environment | Base URL | |---|---| | Testing | `https://uba.test.fino.run/` | | Production | `https://uba.fino.run/` | Adjust the origin in your postMessage validation and widget `origin` attribute accordingly. *** ## Sandbox & Demo For testing without real API credentials, UBA provides a sandbox mode: **URL:** `https://uba.{stage}.fino.run/sandbox` The sandbox auto-creates a session with the fino demo bank. Use these test credentials: | Field | Value | |---|---| | Bank | fino SCA Bank | | Username | `fino01` | | Password | `654321` | Interactive demo pages are also available: - **Iframe demo:** [https://uba.test.fino.run/demo/iframe](https://uba.test.fino.run/demo/iframe) — includes a live event log, session parameter editor, and copy-paste iframe code. - **Widget demo:** [https://uba.test.fino.run/demo/widget](https://uba.test.fino.run/demo/widget) — includes configuration toggles, generated markup, and a live event log. --- # Banking > Connect Flows > Troubleshooting When integrating banking connect flows, you may encounter some common issues. Below are some troubleshooting tips to help you resolve these problems. ## Purpose and Scope This guide provides structured troubleshooting support for issues occurring during: - Bank connection establishment - Consent management and renewal - Synchronization processes - Webhook delivery - Recurring background synchronization It covers typical failure scenarios for banking connections and synchronization. This guide is intended for: - Technical support teams - Integration engineers - Operations teams ## Quick Triage Checklist Before investigating protocol-specific details, verify the following: ### Session Validation - Was a valid **[Connect User Session](/api#tag/Banking-Connect/operation/banking-create-connect-user-session)** or **[Management Session](/api#tag/Banking-Connect/operation/banking-create-management-session)** created? - Has the redirect session expired? - Is the correct user ID being used? ### Bank Login Status Use: **[Get Logins Synchronization Status](/api#tag/Banking-Connect/operation/banking-get-logins-synchronization-status)** **Check:** - `status` - `OK` - `SCA_REQUIRED` - `SYNC_FAILED` - `active` - `lastSynchronization` ### Consent Status - Is there a valid consent? - Has the consent expired? - Was a new consent created that invalidated a previous one? - Refer to the above bank login status for the consent status. ### Webhook Configuration - Is webhook configuration active? - Is webhook endpoint reachable? - Are webhook signatures verified correctly? - Are responses returning HTTP 2xx? ## Connection Establishment Issues ### User Cannot Select Bank **Symptoms** - Bank not found in search - Bank selectable but connection fails immediately **Possible Causes** - Bank interface temporarily unavailable - Bank removed or migrated to new interface - Regional restrictions - Maintenance window **Actions** - Verify bank availability at their own online banking portal - Retry after short delay - Escalate if issue persists across multiple users ### Account Type Not Available **Symptoms** - User cannot see expected account types (e.g., credit card missing) **Possible Causes** - Bank exposes different account types per interface - Selected interface does not support requested account type - Bank-side filtering **Actions** - Verify selected account type during connection - Retry using alternative available interface - Inform user that availability depends on bank configuration ### Authentication Fails During Login **Common Root Causes** - Invalid credentials - Account locked - Multifactor authentication required - Redirect URI mismatch - Session timeout **Actions** - Verify user credentials - Confirm bank access works directly in bank app/website - Check for multifactor setup changes - Retry after ensuring no account lock ## SCA Flow Issues ### Embedded SCA Fails **Possible Causes** - TAN expired - Challenge timed out - Incorrect TAN - Device binding changed ### Decoupled SCA Not Confirmed **Possible Causes** - User did not approve in banking app - Approval window expired - Push notification disabled ### Redirected Flow Breaks **Possible Causes** - Redirect URI mismatch - User manually closed window - Third-party cookie blocking - Session timeout **General Actions** - Restart connection session - Ensure user completes SCA within allowed timeframe - Confirm redirect URL configuration - Check OAuth callback handling ## Consent-Related Issues ### Consent Expired (SCA\_REQUIRED) **Detection** - `status = SCA_REQUIRED` - Webhook ubasyncerror with `type = CHALLENGE_REQUIRED` **Resolution Options** - [Create Management Session](/api#tag/Banking-Connect/operation/banking-create-management-session) and let user renew - Trigger [Create Synchronization Session](/api#tag/Banking-Connect/operation/banking-create-synchronization-session) **Notes** - Only one valid consent per bank login - New consent invalidates previous one - User interaction is mandatory ### SYNC\_FAILED Status **Possible Causes** - Bank API temporarily unavailable - Rate limiting - Interface change - Authentication error during background sync **Actions** - Retry manual synchronization - Check webhook payload for error details - Escalate if persistent ### Duplicate Bank Logins **Symptoms** - Same bank account appears twice - Multiple bank logins for same user and bank **Causes** - Duplicate connection attempt **Resolution** - Identify active bank login - Delete obsolete login - Ensure users are guided to Management Session for additional accounts ## Synchronization Issues ### Manual Synchronization Not Triggering **Checklist** - Valid consent? - Bank login active? - Correct bankLoginId used? If consent expired: - User must complete SCA challenge ### Recurring Synchronization Not Running **Check** - `active = true` - No recent `SCA_REQUIRED` - Webhook subscription active **Common Causes** - Consent expired silently - Bank-side downtime - Recurring user flag not set ### Background Sync Stops After Error **By design:** - Automatic synchronization is disabled if user action required **Resolution:** - Trigger renewal via management session - After renewal, confirm `active = true` ## Webhook Delivery Issues ### Webhook Not Received After Connection **Checklist** - Webhook configured? - Endpoint publicly reachable? - TLS certificate valid? - Returns HTTP 2xx? **Common Causes** - 4xx or 5xx response - Timeout on receiver side - IP allowlisting missing ### Webhook Not Received After Sync **Possible causes** - Sync failed - Consent expired - Recurring disabled - Delivery failed and retried unsuccessfully **Check** - Synchronization status - Webhook logs ## Escalation Guidelines **Escalate if:** - Same issue affects multiple users for same bank - Persistent SYNC\_FAILED across retries - Bank interface recently changed - Webhook delivery failing across tenants **Provide when escalating:** - `userId` - `bankLoginId` - ID of failing request or error code from UI - Bank name - Timestamp of failure - Synchronization status response ## Recommended Monitoring Strategy **For recurring setups:** - Periodically poll synchronization status - Subscribe to webhook error events **Alert on:** - `SCA_REQUIRED` - `SYNC_FAILED` - inactive recurring connections - Track `lastSynchronization` timestamps ## Known Operational Characteristics - Only one valid consent per bank login - Consent always tied to bank login, not account level - User interaction mandatory for renewal - Recurring sync disabled automatically after challenge-required errors - Synchronization schedule not configurable - Bank behavior may differ per account type and interface --- # Banking > Manual Upload > Overview The Banking module allows you to manually manage users' banking data via API, giving you full control over accounts and transactions. Whether you're creating new accounts, enriching them with transactions, updating existing data, or cleaning up errors, this guide walks you through the complete journey. **Use case:** You already have account data and want to run fino Analytics modules on it. --- # Banking > Manual Upload > Adding Data **Scopes Required:** banking-upload ## Create External Accounts This endpoint allows you to add new bank accounts for a user. Use it when you already have the user's banking data and do not rely on the Banking UI. Endpoint: **POST** `/users/{user-id}/banking/accounts` ### What's Possible - Add one or multiple external accounts for a user. - Include account metadata: balance, bank name, IBAN, owner, account type, and optional visuals like icons. - Include transactions, securities, or standing orders associated with the account. - Override existing accounts if accountId and accountNumber match. ### Model - **accountId** - Internal identifier for the account - **accountNumber** - Domestic account number - **balance** - Current account balance - **bankCode** - Bank's internal code - **bankName** - Name of the bank - **bic** - Bank Identifier Code - **currency** - ISO 4217 currency code - **iban** - IBAN of the account - **icon** - URL to bank's logo/icon - **name** - Friendly account name - **owner** - Name of account owner - **type** - Account type (GIRO, KREDIT\_KARTE, DEPOT, etc.) - **transactions** - Array of transactions to pre-fill the account - **securities** - For DEPOT accounts - **standingOrders** - Pre-existing recurring payments ### Journey / Narrative You have raw banking data for your user. Send a POST request with account metadata and optionally transactions. finoOS creates the account, stores metadata, and links any transactions, securities, or standing orders you provided. If an account with the same accountId and accountNumber exists, it will be replaced. ## Add Transactions to an Existing Account After creating an account, you can add transactions to it. Endpoint: **POST** `/users/{user-id}/banking/accounts/{account-id}/transactions` ### What's Possible - Upload one or multiple transactions to an existing account. - Include payment metadata such as bookingText, purpose, merchantCategoryCode, paymentPartner. - Add detailed timestamps: bookingDate (when booked) and valueDate (when funds available). - Prevent duplicates by providing unique transactionId. - Overwrite existing transactions by re-uploading with the same transactionId. ### Model - **transactionId** - Unique ID for each transaction - **amount** - Transaction amount - **currency** - ISO 4217 currency code - **bookingDate** - Unix timestamp of booking - **valueDate** - Unix timestamp when funds are available - **bookingText** - Description of transaction - **purpose** - Purpose of transaction - **paymentPartner** - Merchant or service provider details - **bic** - Bank Identifier Code - **creditorId** - Creditor identifier - **iban** - IBAN of the merchant - **name** - Name of the merchant - **differentCreditor** / differentDebitor - Ultimate payer/receiver if different from paymentPartner - **eref / mref** - Reference numbers - **merchantCategoryCode** - Four-digit merchant classification code - **sepaPurposeCode** - Four-character SEPA classification code - **transactionCode** - Classification ID (typically a one- to three-digit code) ### Journey / Narrative Prepare transaction data from your source system. Ensure each transaction has a unique transactionId. Send a POST request to the account endpoint with the transaction array. finoOS adds transactions to the account. Duplicate transactionIds overwrite the existing transaction automatically. --- # Banking > Manual Upload > Manipulating Existing Data **Scopes Required:** banking-upload ## Update External Accounts Update existing account metadata without recreating the account. Use this when information like bank name, balance, or owner changes. Endpoint: **PATCH** `/users/{user-id}/banking/accounts` ### What's Possible - Update account metadata (balance, bank name, IBAN, owner, type, supportedPayments, etc.). - Update associated transactions in the same request (except IDs and accountNumber). - Perform partial updates; omitted fields remain unchanged. ### Model Identical to Adding Data's [Create External Account](./adding-data.mdx#model) except for IDs (accountId, accountNumber) which cannot be changed: *Please note that transactions can be updated partially within the same payload.* ### Journey / Narrative Identify accounts that need metadata corrections. Send a PATCH request with updated fields. The Banking module applies updates without overwriting unspecified fields, preserving existing data integrity. ## Update Transactions Patch individual transactions to correct or enrich data. Endpoint: **PATCH** `/users/{user-id}/banking/accounts/{account-id}` ### What's Possible - Update transaction fields like amount, bookingText, purpose, merchantCategoryCode, paymentPartner. - Perform partial updates; omitted fields remain unchanged. - Overwrite metadata for existing transactionIds only. ### Model Also, identical to Adding Data's [Add Transactions to an Existing Account](./adding-data.mdx#model) except for IDs (transactionId, accountId) which cannot be changed. ### Journey / Narrative Identify the transaction that needs updating. Send a PATCH request with updated fields. The Banking module modifies the transaction while preserving other fields not included in the request. --- # Banking > Manual Upload > Meaning and importance of data fields ### Meaning and importance of account-data fields The following table outlines the fields used in the request payload for manual upload of accounts. Each field is briefly described in terms of its meaning, expected data type, and relative importance. Fields which are not required might still benefit the quality of analyses or display. | Field | Description | Data Type | Required | Notes | |----------|------------|------------------|----------|-------| | accountId | Internal identifier for the account | string | no | If not set, an ID will be generated | | accountNumber | Domestic account number | string | no | Not used in most analyses, except IBAN is missing | | balance | Current account balance | float | yes | | | bankCode | Bank's code | string | no | Recommended to provide if available | | bankName | Name of the bank | string | yes | | | bic | Bank Identifier Code | string | no | Recommended to provide if available | | overdraft.amount | Maximum value of the agreed overdraft by the bank | boolean | no | Not mandatory for analysis but should be provided if the value is known | | overdraft.available | Defines if an overdraft is available | string | no | Should be provided if overdraft.amount is known to be 0 | | currency | ISO 4217 currency code | string | no | If not set, default will be 'EUR' | | iban | IBAN of the account | string | yes | | | icon | URL to bank's logo/icon | string | no | | | name | Descriptive account name (account product-name in many cases) | string | no | | | owner | Name of account owner | string | yes | | | type | Account type (GIRO, KREDIT\_KARTE, DEPOT, etc.) | string | yes | Default value is 'GIRO'. Must be one of 'BAUSPAREN', 'DEPOT', 'FESTGELD', 'FONDSDEPOT', 'GIRO', 'KREDIT\_KARTE', 'KREDIT\_KONTO', 'KREDITDARLEHEN', 'SPARBUCH', 'TAGESGELD', 'UNKNOWN', 'OTHER' | | transactions | Array of transactions to pre-fill the account | array of transaction-objects | yes | Not required if account-type is 'DEPOT'. More details on transaction-fields can be found below | | securities | Array of securities for DEPOT accounts | array of securities-objects | yes | Only required if account-type is 'DEPOT' | | standingOrders | Pre-existing recurring payments | array of standing-order-objects | yes | More details on securities-fields can be found below | ### Meaning and importance of transaction-data fields The next section provides an overview of the JSON fields of transactions for manual upload. | Field | Description | Data Type | Required | Notes | |----------|------------|------------------|----------|-------| | transactionId | Unique ID for each transaction | string | no | If no ID is provided, it will be generated | | amount | Transaction amount | float | yes | Outgoing money should be provided with a minus, while incoming money needs no plus sign or such | | currency | ISO 4217 currency code | string | no | Default value is 'EUR' | | bookingDate | Unix timestamp of booking | integer | yes | | | valueDate | Unix timestamp when funds are available | integer | no | | | bookingText | Description-text for the transaction | string | no | | | purpose | Purpose text of transaction | string | yes | It is beneficial when meta-information (like SEPA-IDs and such) is added along with the purpose-text | | paymentPartner.bic | Bank Identifier Code of payment partner | string | no | | | paymentPartner.creditorId | Creditor identifier of payment partner | string | yes\* | | | paymentPartner.iban | IBAN of the payment partner | string | yes | Some transactions, like bank-internal charges, cash withdrawals and such, do not always need an IBAN | | paymentPartner.name | Name of the payment partner | string | yes | | | differentCreditor / differentDebitor | Ultimate payer/receiver if different from payment partner | string | no | | | eref | End-to-end-reference number | string | yes\* | | | mref | Mandate-reference number | string | yes\* | | | sepaPurposeCode | Four-character SEPA classification code | string | no | | | transactionCode | Classification ID for types of transactions | integer | no | Typically a one- to three-digit code| \* only applies to SEPA direct-debits ### Meaning and importance of securities-data fields In the following section, the different fields for securities and their respective daty type are listed. As of now, securities-data is only used for display and not for further analyses, so that each field is optional and it is recommended to provide them if possible. | Field | Description | Data Type | Required | Notes | |----------|------------|------------------|----------|-------| | name | Name of the stock | string | no | | | isin | ISIN (International Securities Identification Number) of the stock | string | no | | | wkn | WKN (Wertpapierkennnummer) of the stock | string | no | | | currency | The currency in which the stock was purchased | string | no | | | quantity | Number of shares of the stock held | float | no | | | amount | Amount (in currency from "currency") of the stock held | float | no | Can be calculated by quantity multiplied by price | | amountOriginalCurrency | Equals "amount" unless it was bought in a different currency than stated in "currency" | float | no | | | price | Price of the stock held | float | no | | | purchasePrice | Price the stock shares were purchased for | float | no | | --- # Banking > Manual Upload > Deleting Data **Scopes Required:** banking-upload ## Foreword Upon inspecting the features below, you may notice that account-related operations require the appropriate banking scope. For external customers, the **banking-upload** scope is mandatory to perform any account or transaction deletion. For all manual upload operations—including account and transaction deletion—you must use the **banking-upload** scope. This ensures that only manually uploaded data can be modified or removed. Transaction deletion is only possible for manually uploaded data. Deletion of transactions fetched from banks is not permitted due to regulatory requirements. ## Delete a single Account Remove a single external account completely. All transactions and account metadata are deleted. Endpoint: **DELETE** `/users/{user-id}/banking/accounts/{account-id}` ### What's Possible - Delete one account by its account-id. - Remove all transactions and metadata associated with the account. ### Model - **account-id** - The ID of the account to delete ### Journey / Narrative Identify the account to delete. Send a DELETE request with the account ID in the path. The Banking module removes the account and all associated data permanently. ## Delete Multiple Accounts Remove multiple accounts in a single request by specifying an array of IDs. Endpoint: **DELETE** `/users/{user-id}/banking/accounts` ### What's Possible - Delete multiple accounts at once. - Each account specified by accountId in the request body. - All transactions and metadata associated with the accounts are removed. ### Model - **IDs** - Array of account IDs to delete *Please note that array must be embedded in an object, e.g., `{ "ids": [ "accountId1", "accountId2" ] }`.* ### Journey / Narrative Identify all accounts to remove. Send a DELETE request with the array of IDs. The Banking module deletes all specified accounts and their associated data. ## Delete Transactions Remove specific transactions from an account. Endpoint: **DELETE** `/users/{user-id}/banking/accounts/{account-id}/transactions` ### What's Possible - Delete one or multiple transactions by transactionId - Preserve the account and remaining transactions - Clean up duplicates or incorrect entries without re-uploading the entire account ### Model - **ids** - Array of transaction IDs to delete ### Journey / Narrative Identify transactions to remove. Send a DELETE request with the ids array. The Banking module removes the specified transactions. Remaining transactions remain untouched. ## Best Practices for Deletion **Double-check IDs:** Deletion is irreversible. Always confirm the IDs before sending requests. **Use batch deletion cautiously:** Multiple accounts can be deleted at once, but be aware all associated transactions are also removed. **Log deletions:** Keep an audit trail of removed accounts and transactions for compliance. **Combine with partial updates:** If only certain transactions need removal, use DELETE transactions instead of deleting the whole account. --- # Banking > Account Information Service Once the bank data is successfully imported, either via direct bank access or manual upload, the system processes and makes the data available for analysis through the enabled Analytics modules. The imported data can be accessed and utilized according to the permissions and configurations set for your subscription. We differentiate the data retrieval by either accessing the data directly through Banking (as it is a basic module) or through the Analytics modules: ## Retrieval through Banking - The imported bank data can be accessed directly via the Banking service endpoints. - This allows for basic operations such as retrieving all accounts of a user (with or without transactions) or retrieving all transactions of a specific account. - Likewise, deletion operations are accessible through the same Banking module. - For more details, please refer to the API specification of the **[Banking service](/api/#tag/Banking-General)**. *Please note that we only allow manipulation of existing data for manually uploaded account data, as by regulation, data retrieved via bank interfaces **must not** be altered.* ### Supported formats In general, the Banking module responds with data in JSON format. Make sure to check the respective endpoint documentation for details on the response models. Apart from that, the Banking module also provides a single endpoint that allows for the retrieval of an account's summary as a PDF document. For more details on this feature, please refer to the **[Get Account Summary as PDF](/api#tag/Banking-General/operation/banking-get-account-summary)** endpoint documentation. ## Retrieval through Analytics Modules - The imported bank data is also (partially) accessible through the enabled Analytics modules. - Each Analytics module provides specific endpoints to access and analyze the data according to its functionality. - For instance, the Categorization module allows retrieving categorized transactions as they are processed by the module. - For more details, please refer to the respective Analytics module documentation. --- # Banking > Payment Initiation Service This section covers endpoints for initiating money transfers and retrieving information about existing or previously initiated money transfers. These endpoints are only available for users with an active connection. As this already indicates, there are some regulatory requirements to be fulfilled in order to use these endpoints, such as obtaining user consent for each payment initiation. ## Requirements - Payment Initiation Service must be enabled for your subscription as it is an optional add-on to the Banking service. - The accounts of an established connection used for payment initiation must support payment initiation via the underlying bank interface. - Manually uploaded accounts do not support payment initiation by default. - Unfortunately, not all banks support payment initiation via their interfaces. Therefore, it is recommended to check the capabilities of the connected bank accounts before attempting to initiate payments. For help, feel free to contact us [directly](/docs/support). ## Initiating Payments To initiate a payment, you can use the **[Create Payment Initiation Session](/api#tag/Banking-Money-Transfer/operation/banking-money-transfer)** endpoint. As indicated by our API specification, this endpoint requires both a valid `user-id` and a valid `banklogin-id` which are provided through path parameters. Furthermore, the specified bank login must be active and healthy in order to successfully initiate a payment. You can initiate multiple money transfers in a single request. This is especially useful when debiting one account to pay several recipients at once. When you want to start a payment, just include these details in your request's body: - **accountId**: The internal ID of the account that is to be debited. - **executionDate**: The date you want the transfer to happen (YYYY-MM-DD). It can’t be in the past. If you leave it out, today’s date will be used. - **exitUrl**: The HTTPS link where users should be sent if they leave the payment process. - **fallbackUrl**: The HTTPS link for users if something goes wrong during payment. - **moneyTransferInfos**: A list of details for each transfer you want to make. - **redirectUrl**: The HTTPS link where users go after a successful payment. - **singleBooking**: If you’re making several transfers, set this to `true` (the default) to group them as one booking, or `false` to handle each separately. *Please note that the actual execution of the payment depends on the bank's processing times and policies. Also, despite having an active connection, some banks may require additional user authentication or consent for each payment initiation. Accordingly, the user might need to complete a challenge during the payment process.* **One more important note:** The payment initiation process is **not completed** when you receive a successful response from the **Create Payment Initiation Session** endpoint. A successful response only indicates that the payment initiation was started correctly. The actual completion of the payment depends on the bank's processing times and policies. In such cases, we indicate the current status of the payment initiation in the response. For more information of the possible payment status cases, see the next section. ## Retrieving Payment Information To get details about existing or previously initiated payments, you can use the **[Get Money Transfer](/api#tag/Banking-Money-Transfer/operation/banking-get-money-transfer)** endpoint. This endpoint requires a valid `user-id`, `banklogin-id`, and `money-transfer-id` as path parameters. When you initiate a payment, the response you receive provides detailed information about the specified payment *order*. As specified before, we support multiple money transfers in one go, so the response includes a list of transfers that are part of the payment order, each with its own details. The following fields are included in the response for each transfer: - **amount**: The exact amount that is to be transferred for this payment. This is a numeric value and should match the intended transaction sum. - **creditor**: Details about the recipient of the payment. This object typically includes information such as the name and account details of the person or entity you are sending money to. - **currency**: The currency in which the payment will be made, following the ISO 4217 standard (for example, `EUR` for Euro or `USD` for US Dollar). If the currency is not supported, it will be indicated as `OTHER`. - **debtor**: Information about the sender of the payment. This object contains details about the account from which the money will be debited. - **purpose**: A short description or reason for the payment. This helps both you and the recipient understand the context of the transaction. Besides these fields for each transfer, the response also includes a status field indicating the overall state of the payment initiation, which helps you track the progress of your transfer. The possible values for the status field are: **status**: - **OPEN**: The payment initiation has been created and is awaiting further processing. - **PENDING**: The payment initiation is being processed by the bank and yet to be completed. - **SUCCESSFUL**: The payment was completed successfully. - **NOT\_SUCCESSFUL**: The payment could not be completed. - **DISCARDED**: The payment initiation was canceled or discarded. By reviewing these fields, you can follow the journey of your payment from initiation to completion, ensuring transparency and clarity at every step. ***One final note:** As the completion of payments happens asynchronously at the bank's side, the previously established connection must remain active and healthy to track the payment status effectively. We cannot acquire any updates on the payment's status if the connection is inactive or has been revoked.* --- # Banking > Demo Users As a part of our commitment to providing a seamless experience for our clients, we offer demo users that allow you to explore the functionalities of our banking module without the need for real bank accounts. These demo users are designed to simulate real banking scenarios, enabling you to test and understand how our system works in a risk-free environment. Please note that the demo users are intended for testing and demonstration purposes only. As such, these users connect towards our own mock bank implementation, which simulates the behavior of real banks but does not connect to any actual financial institutions. ## Available Demo Users We currently offer the following demo users: | Demo User Name | Description | |----------------|-------------| | persondemo | Typical demo user for personal banking scenarios. This user simulates a standard individual bank connection with some standard accounts. | | companydemo | Typical demo user for business banking scenarios. This user simulates a business bank connection that contains some business accounts. | | depot01 | Typical demo user for investment banking scenarios. This user simulates an investment account that contains some example securities. | ## Password combinations While we provide different demo users for various banking scenarios, the password can define specific behaviors for the demo users, allowing you to test different scenarios and functionalities. The following table outlines the available password combinations and their corresponding behaviors: | Password | Behavior | |----------|----------| | 654321 | A TAN must be entered (123456) | | 999999 | Simulates an incorrect password | | 999991 | Simulates a decouples TAN process | | 999992 | Simulates a photoTAN challenge (twice) | *Please note that the above password combinations are specific to our demo users and are designed to trigger specific behaviors for testing purposes. These combinations may not reflect real-world banking scenarios and should be used solely for testing and demonstration purposes within our system. Also, if you enter no password at all or just a random combination of characters, the login will succeed, but without any challenge.* ## Testing connect flows with demo users To test the connect flows with our demo users, you can follow these steps: 1. Use the **[Create Connect User Session](/api#tag/Banking-Connect/operation/banking-create-connect-user-session)** endpoint to initiate a connect session for the desired demo user. 2. From the bank search UI, search for our mock bank (e.g., "Fino Bank") and select it. 3. When prompted for credentials, enter the demo username (e.g., `persondemo`) and the desired password from the combinations outlined above. 4. Follow the prompts to complete the connection process, including any additional authentication steps based on the password behavior you have chosen. 5. Once the connection is established, you can explore the functionalities of the banking module using the connected demo user account, allowing you to test various features and scenarios without the need for real bank accounts. ## Testing money transfer with demo users Of course, you can also test the money transfer functionalities with our demo users. To do so, you can follow the steps mentioned above to connect a demo user account, and then use the **[Create Money Transfer](/api#tag/Banking-Money-Transfer/operation/banking-money-transfer)** endpoint to initiate a money transfer from the connected demo user account. However, for the demo money transfer to function properly, you need to use a password that triggers a challenge (e.g., `654321`) during the connection process of the demo user account. ## Force Consent Expire This parameter allows you to simulate an expired consent in order to test different error and edge-case scenarios. ### Behavior To use this feature, you must authenticate with one of the available demo users listed above and use the PIN **`654321`**. Depending on the value of `triggerChallenge`, the endpoint **[Create Synconization Session](/api#tag/Banking-Connect/operation/banking-create-management-session)** behaves as follows: - **`triggerChallenge = true`** - The endpoint responds with **HTTP 451** - The response indicates that a user challenge (e.g., re-authentication) is required - **`triggerChallenge = false`** - The endpoint responds with **HTTP 206 (Partial Content)** - The related process status is set to **`SYNC_FAILED`** if you call the **[Get Connect User Session Status](/api#tag/Banking-Connect/operation/banking-get-logins-synchronization-status)** endpoint ### Asynchronous Behavior In addition to the immediate API response, an asynchronous webhook is triggered: - Event type: `ubasyncerror` - Purpose: Simulates an error during asynchronous processing ### Use Cases This feature is particularly useful for: - Testing **consent expiration scenarios** - Simulating **synchronization failures** - Validating **error-handling and retry logic** - Verifying **webhook processing** --- # Analytics > General Analytics > Overview Based on the received Banking data FinoOS provides a variety of Analyses and Insights to get a better understanding of the individual Users financial situation. In this section you will find an overview of Analytics and Insights that are available for both **Person** and **Company** Users. There are also scopes that are only available for one of the user types, which will be described in the respective sections for **[Person Users](./../person/overview)** and **[Company Users](./../company/overview)**. --- # Analytics > General Analytics > Categorization One of the core features of finoOS Analytics is the ability to categorize transactions very precisely. Each transaction is categorized and is available through **[Get Categorization](/api#tag/Categorization/operation/get-categorization)** **Example Transaction Response:** ```json { "accountId": "account-1", "transactionId": "transaction-1", "creationDate": "2026-01-22T14:08:47+01:00", "descriptiveTag": "insurance_legal", "localizedTag": "Rechtsschutzversicherung", // optional "tags": [ "insurance_legal", "insurance", "spending" ], "transaction": { // optionally the raw transaction data can be included } } ``` As you can see we provide - a `tags` array with all the tags that apply to the transaction. - a `descriptiveTag` which is the most specific tag that applies to the transaction. - a `localizedTag` which is the localized version of the `descriptiveTag` (if requested). Note: The available tags differ between **Person** and **Company** Users, as they are based on different algorithms, so be sure to create your users with the correct user type. ### Obtain Categorization Results As for all other analytics results, you can obtain the categorization results either via **webhooks** or by **polling** the relevant endpoints. - See the **[Analysis Lifecycle](./../../overview/analysis-lifecycle.mdx)** section for more details on how to track the analysis progress and obtain results. - See the **[Webhooks](./../webhooks/webhooks.mdx)** section for more details on how to receive webhook notifications. --- # Analytics > General Analytics > Contracts The finoOS Contracts module uses an intelligent bank account analysis algorithm to detect recurring payments like subscriptions, various types of contracts or installments on one or multiple bank accounts of a user. This way, you can easily see the ongoing and past contracts of a user to get an understanding of their financial relationships. Be aware that we define a contract as any transactions which: - belong to one counter part (a person or a company) - recur in a certain interval - can be grouped together for a specific purpose **Example Contract Response:** ```json { "contractId": "347e903e-128b-465a-adf5-1abf13d2fe1c", "amount": -55.08, "amountConsistency": "FIX", "category": "GEZ", "contractPartner": { // detailed information about the contract partner }, "duration": 90, "interval": "QUARTERLY", "isActive": true, "mref": "6666666066666", "nextBookingDate": "2026-05-16", "nextBookingRange": [ "2026-05-08", "2026-05-24" ], "transactions": [ { "transactionId": "T3de380d6-7452-4e30-b3a3-b5f2807a87b3" }, { "transactionId": "Tef59d8f9-f48f-476c-b885-5f11fa727595" } ], "additionalInfo": {} } ``` The main fields of a contract are: - `contractId`: The unique identifier of the contract - `amount`: The amount of the contract. This is based on the transactions, Category, Interval and possible other factors that belong to the contract. Can be interpreted as the regular amount that is paid for the contract. - `interval`: The interval in which the contract transactions recur. - `category`: The category of the contract. This is based on the categorization and potential other factors of the transactions that belong to the contract. - `isActive`: Whether the contract is currently active or not. For each contract, a booking-range for the next expected transactions is calculated, based on previous patterns. If no transaction is found after the booking-range has ended, the contract is considered to be inactive - `transactions`: The transactions that belong to the contract. The Ids allow you to easily retrieve the full transaction data if needed. --- # Analytics > General Analytics > Account Detection This Module returns a list of Bank-Account & CreditCards that the User has connected. Additionally other Accounts that were found through the Analysis of the Users Transaction-Data are also returned. If an account was found through the analysis the field `additionalAnalysesInfo.IsUserAdded` will be `true`. **Example Response:** ```json { "accountsOverview": { "accountsView": [ { "accountId": "account-1", // other account fields... "type": "GIRO", "additionalAnalysesInfo": { "isUserAdded": true, "analysisPeriod": { "since": "2024-01-02T01:01:01Z", "until": "2026-02-20T01:01:01Z" }, "analysis": { "median": 150, // other analysis fields... }, "creditorId": "" } ], "creditsView": [ { "accountId": "", // other account fields... "type": "KREDIT_KARTE", "additionalAnalysesInfo": { "isUserAdded": false, "analysisPeriod": { "since": "2024-01-24T01:01:01Z", "until": "2026-01-24T01:01:01Z" }, "analysis": { "median": -180.15, "average": -180.15, "medianEarning": 0, "medianSpending": -180.15, "averageEarning": 0, "averageSpending": -180.15, "spending": { "median": -180.15, "average": -180.15, "transactionIDs": [ "T082a6370-dc82-42b9-87d0-753dbb9c79e8" ] } } }, "creditorId": "DE3810400000020144" } ] } } ``` In this example you can see that the first account was added by the user, while the creditcard was found through the analysis of the users transactions. Under `additionalAnalysesInfo` you can find more information about the period and payment relations found for that account. --- # Analytics > General Analytics > Account History The Account-History section provides an overview of all accounts and their daily balances for the past 2 years. \*\* Example:\*\* ```json { "histories": [ { "account": { "accountId": "account-1" }, "dailyBalances": [ { "date": "2026-02-23", "balance": 7481.06 }, { "date": "2026-02-22", "balance": 7481.06 }, { "date": "2026-02-21", "balance": 7481.06 }, ... ``` --- # Analytics > Person Analytics > Overview # Person Analysis The finoOS API's Person Analysis provides comprehensive account data analysis to evaluate a person's financial situation. The system consists of five main components: **Income**, **Spending**, **Risk**, **Household-Budget**, **Adult-Check**, and **Living-Situation**. The unique feature of Person Analysis is its flexible architecture: The first three components (Income, Spending, Risk) have a module-based structure where multiple modules can be **booked individually** but are accessed through a **single endpoint**. The Household-Budget and Adult-Check components are standalone analyses without modular subdivisions. ## Income Income Analysis identifies and categorizes various types of income based on transaction data. The system analyzes transfer data to detect regular and irregular income sources. **API Endpoint:** [Person-Income API](/api#tag/Person-Income) For detailed information about individual modules, see [Income modules](./income.mdx). ## Spending Spending Analysis identifies and categorizes various spending categories to understand spending patterns and financial obligations. **API Endpoint:** [Person-Spending API](/api#tag/Person-Spending) For detailed information about individual modules, see [Spending modules](./spending.mdx). ## Risk Risk Analysis identifies risk indicators based on problematic transaction patterns that may indicate financial difficulties. **API Endpoint:** [Person-Risk API](/api#tag/Person-Risk) For detailed information about individual modules, see [Risk module](./risk.mdx). ## Household-Budget Household-Budget provides a comprehensive analysis of monthly income and spending patterns to calculate the household's financial balance and overall budget situation. **API Endpoint:** [Person-Household-Budget API](/api#tag/Person-Household-Budget) ## Adult-Check Adult-Check verifies the age status of account holders to determine if they meet legal age requirements for financial services. **API Endpoint:** [Person-Adult-Check API](/api#tag/Person-Adult-Check) ## Living-Situation Living-Situation analyzes transaction patterns to determine information about the account holder's living circumstances, including family situation, mobility, property ownership, and rental arrangements. **API Endpoint:** [Person-Living-Situation](/api#tag/Person-Living-Situation) For detailed information about all components, see [Living Situation](./living-situation.mdx). ## Modular Booking Concept The first three main components (Income, Spending, Risk) can be flexibly configured: - **Individual modules** can be licensed separately - **Combinations** of modules within a component are possible - **One endpoint** per component delivers all booked modules - **[Scopes](../../overview/scopes.mdx#person-analysis-scopes)** define which modules are available The Household-Budget, Adult-Check, and Living-Situation components are standalone analyses that can be booked as complete units without modular subdivisions. This enables customers to implement tailored solutions that contain only the needed analysis functions, while keeping API integration simple and unified. --- # Analytics > Person Analytics > Income modules ## Salary Required Scope: `person-income-salary` This module returns several kinds of salary-payments. This covers all forms of salary and wages, including standard employment income, civil servant pay, expense-related allowances (e.g. coaching or training fees), bonuses, apprenticeship or trainee compensation, salary advances and short-time work benefits. It does not cover expense reimbursements, subsidy or assistance payments, and commission-based income. *** ## Pension Required Scope: `person-income-pension` This module returns pension and retirement income as well as private retirement benefits. *** ## Child allowances Required Scope: `person-income-child-benefit` This module returns child allowances, whether provided by public authorities or by family members. *** ## Parental allowance Required Scope: `person-income-parental-allowance` This module returns parental leave benefits. *** ## Rental income Required Scope: `person-income-rental` This module returns rental income, including income from leasing residential property, garages, parking spaces, and similar assets. *** ## Investment revenues Required Scope: `person-income-investment` This module returns capital income, such as dividends from securities, proceeds from the sale of securities, income from cryptocurrency sales, and interest earned on deposits or savings. *** ## Loans Required Scope: `person-income-loan` This module returns loan disbursements. *** ## Support payments / alimony Required Scope: `person-income-alimony` This module returns income from maintenance and support payments. *** ## Self employment Required Scope: `person-income-self-employment` This module returns income self-employment such as owner's drawings, commissions, and performance-based compensation. *** ## Miscellaneous Required Scope: `person-income-other` This module returns recurring income from various sources, like feed-in tariffs for electricity generation, pocket money, unemployment benefits, other government or public benefits, and recurring private contributions (e.g. for shared household expenses), as well as irregular / one-off income such as cash deposits, refunds for energy or utility costs, gambling winnings, one-off transfers, and similar payments. --- # Analytics > Person Analytics > Spending modules ## Rent payments Required Scope: `person-spending-rent` This module returns several forms of rent-payments, such as residential rent, garage rent, stable or horse box rent, locker rental, and similar lease expenses *** ## Investments Required Scope: `person-spending-investment` This module returns regular savings and investment contributions, including securities savings plans, home savings schemes, and recurring deposits into fixed-term or overnight savings accounts. It also covers irregular or one-off savings and investment expenses, such as purchases of securities, one-time cryptocurrency investments, one-off contributions to home savings plans, and small cash savings. *** ## Insurances Required Scope: `person-spending-insurance` This module returns insurance-related expenses, covering a wide range of policies such as private health insurance, personal liability insurance, professional or financial loss liability insurance, household contents insurance, private pension or retirement insurance, legal expenses insurance, and similar insurance products. *** ## Credits and loans Required Scope: `person-spending-credit` This module returns loan- and credit-related expenses, including regular loan instalments, early/special lump-sum repayments, short-term loan instalments, consumer credit or instalment payments, repayments of student loans, and energy-efficiency refurbishment loan instalments. *** ## Credit cards Required Scope: `person-spending-creditCard` This module returns expenses from credit card statements, limited to monthly credit card settlements and excluding individual card transactions. *** ## Miscellaneous Required Scope: `person-spending-other` This module returns regular recurring expenses such as streaming subscriptions, advance or instalment payments for utilities (electricity, gas, water), telecommunications contracts, and sports club or gym memberships, as well as irregular day-to-day expenses including grocery shopping, fuel purchases, one-off transfers, online shopping, and similar payments. --- # Analytics > Person Analytics > Risk modules ## Returned direct debits Required Scope: `person-risk-backDebit` This module returns number of returned direct debits per calendar month. The value represents the count of returned direct debit transactions for each month. If both returned direct debits and returned direct debit fees are present for the same account and month, the maximum value of either returned direct debits or returned direct debit fees is reported. *** ## Garnishments Required Scope: `person-risk-garnishment` This module returns the number of garnishment payments per calendar month. *** ## Collection payments Required Scope: `person-risk-collection` This module returns the number of payments to debt collection agencies per calendar month. *** ## Gambling Required Scope: `person-risk-gambling` This module returns the number of gambling-transactions with the accumulated amount per calendar month. *** ## Overdrafts Required Scope: `person-risk-overdraft-amount` This module returns the number overdraft days per calendar month based on the end-of-day account balance. For each overdraft day, the corresponding overdraft amount is provided. --- # Analytics > Person Analytics > Household Budget # Household Budget The Household Budget analysis provides a comprehensive monthly financial overview by combining income and spending data to calculate the household's financial balance and budget situation. ## Overview Household Budget analysis consolidates data from the [Income modules](./income.mdx) and [Spending modules](./spending.mdx) to generate a complete monthly budget breakdown. This analysis calculates average monthly values across all observed data and provides a financial balance assessment. **Required Scope:** `person-household-budget` ## Core Components ### Monthly Income Breakdown The analysis aggregates income from various sources: - **Salary** - Employment-related income - **Pension** - Retirement and pension payments - **Child Benefit** - Child allowances and benefits - **Parental Allowance** - Parental leave benefits - **Rental** - Income from property rentals - **Alimony** - Maintenance and support payments - **Other Recurring** - Regular income from other sources (e.g., insurance payouts) - **Other Non-Recurring** - One-time payments and irregular income ### Monthly Spending Breakdown The analysis categorizes spending across key areas: - **Rent** - Housing and rental costs - **Credits** - Loan instalments and credit payments - **Insurances** - Insurance premiums and policies - **Investments** - Savings plans and investment contributions - **Credit Cards** - Credit card payments and settlements - **Other Recurring** - Regular recurring expenses - **Other Non-Recurring** - Variable consumption and day-to-day expenses ### Financial Balance The analysis calculates the monthly financial balance as: ``` Balance = Total Monthly Income - Total Monthly Spending ``` This balance indicates whether the household has a monthly surplus (positive balance) or deficit (negative balance). --- # Analytics > Person Analytics > Adult Check # Adult Check Required Scope: `person-adult-check` The Adult Check analysis evaluates whether the available financial data provide sufficiently strong evidence that a person is likely to be an adult. The result is a probabilistic business assessment and not a legally binding age verification. ## Decision Types The analysis returns one of three possible decisions: - `ADULT` — the available data indicate that the person is likely to be an adult - `NOT_ADULT` — the available data indicate that the person is likely not an adult - `UNKNOWN` — the available data did not provide sufficient evidence for a confident determination ## Indicator Overview Indicators are derived from the following sources: **Very strong indicators** - `CAR_INSURANCE` — car-related insurance contract - `CONSUMER_CREDIT` — consumer credit contract - `GAMBLING` — gambling-related transactions - `CREDIT_CARD_BILLING` — credit card billing contract - `STABLE_FULL_TIME_INCOME` — regular salary of at least 1,680 € across 3 or more consecutive months - `HIGH_RENT` — rental apartment contract with an amount of 900 € or more - `PROPERTY_OWNERSHIP_COST` — condo fee or leasehold duties indicating property ownership - `CAR_SHARING_USAGE` — car sharing transactions (requires minimum age of 18) - `ADULT_ACCOUNT_METADATA` — account product name classified by the bank as an adult account **Strong indicators** - `MOBILE_PHONE_CONTRACT` — mobile phone contract - `LEASING_CONTRACT` — leasing contract - `LIABILITY_INSURANCE` — liability insurance contract - `HOUSEHOLD_INSURANCE` — household contents insurance contract - `LEGAL_PROTECTION_INSURANCE` — legal protection insurance contract **Medium indicators** - `LOW_RENT` — rental apartment contract with an amount below 450 € - `STREAMING_SUBSCRIPTION` — streaming or media subscription contract - `SECURITIES_TRADING` — securities or capital assets contract **Negative indicators** - `PARENTAL_TRANSFER_PATTERN` — regular small incoming transfers suggesting parental financial support - `LOW_INCOME_PATTERN` — regular salary contract with an amount below 1,000 € - `CASH_DEPENDENT_ACCOUNT` — cash-dominant transaction behaviour with no digital payment activity - `STUDENT_APPRENTICE_TAGS` — apprenticeship salary transactions - `HOUSEHOLD_LEISURE_DOMINANT_SPENDING` — spending dominated by household and leisure with low financial complexity - `LOW_TRANSACTION_VOLUME` — average non-ATM transactions per month below 10 - `YOUTH_ACCOUNT_METADATA` — account product name classified by the bank as an under-18 account Each indicator appears at most once in the response. Where multiple transactions support the same indicator, their IDs are merged under a single entry. ## Observation Period The analysis applies an asymmetric time window: - **Positive indicators** use the full available account history, since adulthood is considered permanent once established. A car insurance from several years ago, for example, remains valid evidence. - **Negative indicators** are restricted to the **last 13 months** relative to the analysis timestamp. This prevents outdated signals — such as old apprenticeship income — from distorting the current assessment. The applied observation period is returned in the response via `observedTimespan`: - `observedTimespan.since` — the earliest booking date found across all contracts and accounts. Reflects how far back the data actually reaches. Falls back to 13 months before the analysis timestamp when no data is present. - `observedTimespan.until` — the analysis timestamp. --- # Analytics > Person Analytics > Living Situation # Living Situation The Living Situation analysis examines transaction patterns to determine key aspects of an account holder's living circumstances, providing insights into their family situation, mobility options, property ownership status, and rental arrangements. ## Overview Living Situation analysis processes banking transaction data to build a comprehensive picture of how and where a person lives. This analysis is valuable for understanding lifestyle patterns, housing costs, family composition, and living arrangements that can inform credit decisions, risk assessments, and personalized financial products. **Required Scope:** `person-living-situation` ## Core Components ### Children The Children component analyzes transaction patterns to determine information about the account holder's family composition. *** ### Motor Vehicle The Motor Vehicle component identifies vehicle ownership based on transaction analysis. *** ### Property The Property component determines property ownership status and real estate-related financial obligations. *** ### Housing Rent The Housing Rent component analyzes rental payment patterns for tenants. --- # Analytics > Company Analytics > Overview # Company Analysis The finoOS API's Company Analysis evaluates a company's financial situation based on account and transaction data. It covers different domains, each focused on a specific aspect of company finances. All company analysis endpoints follow the same access pattern: results are computed asynchronously after the Companies Financial Data has been pushed. See [Analysis Lifecycle](./../../overview/analysis-lifecycle.mdx). Each endpoint requires the corresponding [scope](../../overview/scopes.mdx#company-analysis-scopes) to be enabled for your client. ## Cash Transactions & Liquidity Track money movement at the company level and monitor account balances over time. - **Cash Transactions** — Separates cash deposits from cash withdrawals. Returns totals and a monthly breakdown. Required scope: `company-cash`. - **Liquidity** — Tracks income and expenses per account with monthly balance snapshots (end-of-month, minimum, maximum). Required scope: `company-liquidity`. - **Foreign Payments** — Identifies international transactions and groups them by the counterparty's country. Required scope: `company-foreign-payment` · Endpoint: `GET /foreign-payments` For detailed information, see [Cash Flow & Liquidity](./cash-and-liquidity.mdx). ## Risk Identifies risk indicators based on problematic transaction patterns per account. - **Risk** — Returns monthly counts of returned direct debits, garnishments, and overdraft days, broken down per account. Required scope: `company-risk` For detailed information, see [Risk](./risk.mdx). ## Category Breakdowns Analyses recurring financial obligations detected from transactions and contracts. All four domains share the same response structure: a current monthly amount, median, average, and a monthly history distinguishing recurring from non-recurring amounts. - **Credits, Loans & Leasing** — Loan instalments, credit lines, and leasing agreements. Required scope: `company-credit` - **Insurances** — Insurance premium payments. Required scope: `company-insurance` - **Investments** — Savings plans, securities, and investment contributions. Required scope: `company-investment` - **Internal Bookings** — Detects transfers between accounts that belong to the same company. Required scope: `company-internal-booking` For detailed information, see [Category Breakdowns](./category-breakdowns.mdx). ## Business Insights Deeper operational and structural analysis of the company's business activity. - **Staff** — Estimates personnel costs and employee headcount from salary-related transactions and contracts. Required scope: `company-staff` - **Customers & Suppliers** — Ranks the company's top payment partners as customers (incomings) and suppliers (outgoings). Required scope: `company-customer-supplier` - **Top Categories** — Shows the most relevant spending categories with daily and monthly breakdowns. Required scope: `company-top-category` For detailed information, see [Business Insights](./business-insights.mdx). ## Common Response Fields Every company analysis response includes an `observedTimespan` object describing the date range of the underlying transaction data: | Field | Description | |-------|-------------| | `observedTimespan.from` | Earliest transaction date considered | | `observedTimespan.to` | Latest transaction date considered (analysis timestamp) | Monetary values across all endpoints use two decimal places. --- # Analytics > Company Analytics > Liquidity & Cash ## Cash Transactions Required scope: `company-cash` · Endpoint: **[GET /cash-transactions](/api#tag/Company-Liquidity/operation/get-company-liquidity-by-user-id)** Identifies and summarises cash deposits and cash withdrawals across all company accounts. Transactions are tagged as cash deposits or cash withdrawals during the categorisation step — only those tagged transactions appear in this analysis. ### Response structure | Field | Description | |-------|-------------| | `overview.incomings` | Total cash deposits: sum, count, and transaction IDs | | `overview.outgoings` | Total cash withdrawals: sum, count, and transaction IDs | | `overview.totalTransactionAmount` | Combined amount of all cash movements | | `overview.totalTransactionCount` | Total number of cash transactions | | `monthlyOverview[]` | Same breakdown repeated per calendar month, sorted newest-first | | `monthlyOverview[].month` | Month in `YYYY-MM` format | *** ## Liquidity Required scope: `company-liquidity` · Endpoint: **[GET /liquidity](/api#tag/Company-Liquidity/operation/get-company-liquidity-by-user-id)** Tracks all income and expenses per account, month by month. Alongside transaction counts and amounts, each monthly entry includes balance snapshots that show how the account balance evolved within that month. The response contains a cross-account `overview` and a per-account breakdown under `accountLiquidity`. ### Response structure **Top-level overview** (aggregated across all accounts): | Field | Description | |-------|-------------| | `overview.incomings` | Total incoming transactions: sum and count | | `overview.outgoings` | Total outgoing transactions: sum and count | | `overview.totalTransactionAmount` | Net combined amount | | `overview.totalTransactionCount` | Total transaction count | **Per-account entry** (`accountLiquidity[]`): | Field | Description | |-------|-------------| | `account` | Basic account information (IBAN, account type, etc.) | | `overview` | Same structure as the top-level overview, but scoped to this account | | `monthlyOverview[]` | Monthly breakdown for this account, sorted newest-first | | `monthlyOverview[].month` | Month in `YYYY-MM` format | | `monthlyOverview[].endOfMonthBalance` | Account balance at the end of the month | | `monthlyOverview[].minBalance` | Lowest balance recorded during the month | | `monthlyOverview[].maxBalance` | Highest balance recorded during the month | | `monthlyOverview[].incomings` | Incoming transactions for the month | | `monthlyOverview[].outgoings` | Outgoing transactions for the month | | `monthlyOverview[].totalTransactionAmount` | Net amount for the month | *** ## Foreign Payments Required scope: `company-foreign-payment` · Endpoint: **[GET /foreign-payments](/api#tag/Company-Foreign-Payments/operation/get-company-foreign-sales-by-user-id)** Identifies transactions involving international counterparties — detected by a non-domestic IBAN prefix on the payment partner. Results are grouped by the counterparty's country code. ### Response structure | Field | Description | |-------|-------------| | `overview.incomings` | Total international income: sum, count, transaction IDs | | `overview.outgoings` | Total international expenses: sum, count, transaction IDs | | `overview.totalTransactionAmount` | Combined total of all international transactions | | `overview.totalTransactionCount` | Total count of international transactions | | `byState[]` | Breakdown by country code (ISO 3166-1 alpha-2), sorted alphabetically | | `byState[].code` | Two-letter country code derived from the IBAN | | `byState[].incomings` | International income from this country | | `byState[].outgoings` | International expenses to this country | --- # Analytics > Company Analytics > Risk Factors ## Risk Required scope: `company-risk` · Endpoint: **[GET /risk](/api#tag/Company-Risk/operation/get-company-risk-by-user-id)** Identifies risk indicators based on problematic transaction patterns. Results are broken down per account and per calendar month. ### Risk indicators | Indicator | Description | |-----------|-------------| | **Back debits** | Returned direct debits — transactions that were reversed after being initially booked. A high count may signal payment difficulties or insufficient funds. | | **Garnishments** | Garnishment payments, indicating active enforcement proceedings against the account holder. | | **Overdraft days** | Number of days within the month where the account balance was below the account overdraw limit at end-of-day. | ### Response structure The response contains one entry per account under `accountRisks`: | Field | Description | |-------|-------------| | `accountRisks[].account` | Basic account information (IBAN, account type, etc.) | | `accountRisks[].monthlyOverview[]` | Monthly risk summary for this account, sorted newest-first | | `monthlyOverview[].month` | Month in `YYYY-MM` format | | `monthlyOverview[].backDebit.count` | Number of returned direct debits | | `monthlyOverview[].backDebit.transactionIDs` | IDs of the underlying transactions | | `monthlyOverview[].garnishment.count` | Number of garnishment payments | | `monthlyOverview[].garnishment.transactionIDs` | IDs of the underlying transactions | | `monthlyOverview[].overdraftDays` | Number of days the account was in overdraft | --- # Analytics > Company Analytics > Category Breakdowns # Category Breakdowns Credits, insurances, investments, and internal bookings all use the same response structure. The analysis detects recurring financial obligations from transactions and contract data, then provides current, median, and average monthly amounts alongside a full monthly history. ## Shared Response Structure | Field | Description | |-------|-------------| | `available` | `true` if the analysis found relevant data; `false` if nothing was detected | | `current` | Monthly amount for the most recent complete month | | `median` | Median monthly amount across the observed timespan | | `average` | Average monthly amount across the observed timespan | | `monthlyOverview[]` | Monthly breakdown, sorted newest-first | | `monthlyOverview[].month` | Month in `YYYY-MM` format | | `monthlyOverview[].amount` | Total amount for the month (recurring + non-recurring) | | `monthlyOverview[].recurringAmount` | Amount from recurring transactions/contracts | | `monthlyOverview[].nonRecurringAmount` | Amount from one-off transactions | | `monthlyOverview[].recurringTransactionIDs` | IDs of recurring transactions | | `monthlyOverview[].nonRecurringTransactionIDs` | IDs of one-off transactions | | `contractSummary[]` | List of detected contracts contributing to this analysis | | `observedTimespan` | Date range of the underlying data | --- ## Credits, Loans & Leasing Required scope: `company-credit` · Endpoint: **[GET /credits](/api#tag/Company-Credits/operation/get-company-credits-by-user-id)** Covers all credit-related payments: loan instalments, credit line drawdowns, and leasing payments. Detected from both contract data and tagged transactions. --- ## Insurances Required scope: `company-insurance` · Endpoint: **[GET /insurances](/api#tag/Company-Insurances/operation/get-company-insurances-by-user-id)** Covers insurance payments. Detected from contract data and tagged transactions categorised as insurance products. --- ## Investments Required scope: `company-investment` · Endpoint: **[GET /investments](/api#tag/Company-Investments/operation/get-company-investments-by-user-id)** Covers savings plans, securities purchases, and other investment contributions. Includes both regular savings plan instalments and one-off investment transactions. --- ## Internal Bookings Required scope: `company-internal-booking` · Endpoint: **[GET /internal-bookings](/api#tag/Company-Internal-Bookings/operation/get-company-internal-bookings-by-user-id)** Detects transfers between accounts that belong to the same company (i.e. accounts present in the same analysis context). These are typically treasury transfers or inter-account settlements. --- # Analytics > Company Analytics > Business Insights # Business Insights These domains give a deeper view into the company's operational structure: who works there, who it does business with, where it pays internationally, and how its spending is distributed. *** ## Staff Required scope: `company-staff` · Endpoint: **[GET /staff](/api#tag/Company-Staff/operation/get-company-staff-by-user-id)** Estimates personnel costs and employee headcount from salary-related transactions and contracts. The analysis distinguishes between gross salary expenses and additional wage costs (e.g. social insurance contributions). ### Response structure | Field | Description | |-------|-------------| | `salary.totalMonthly` | Combined estimated monthly personnel cost | | `salary.totalMonthlyExpenses` | Gross salary component | | `salary.totalMonthlyAdditionalWageCosts` | Additional wage costs (social contributions, etc.) | | `employees.minNumberOfEmployees` | Lower bound of estimated employee count | | `employees.maxNumberOfEmployees` | Upper bound of estimated employee count | | `sources.contracts` | Contracts that contributed to the analysis | | `sources.transactionIDs` | Transaction IDs used for collective payment detection | :::note Employee count is estimated from individually detected salary contracts and collective salary transfers. It is provided as a range rather than an exact value. ::: *** ## Customers & Suppliers Required scope: `company-customer-supplier` · Endpoint: **[GET /customer-supplier](/api#tag/Company-Customer-Supplier/operation/get-company-customers-suppliers-by-user-id)** Ranks the company's most significant payment partners. Partners with predominantly incoming payments are classified as customers; those with predominantly outgoing payments as suppliers. Each partner receives a combined ranking score based on transaction volume and frequency. ### Response structure Both `customers` and `suppliers` contain a `partnerList` array, sorted by ranking: | Field | Description | |-------|-------------| | `paymentPartner` | Name, IBAN, and other counterparty details | | `ranking.rank` | Combined score (average of revenue rank and occurrence rank) | | `ranking.revenueRank` | Rank by total transaction amount | | `ranking.revenueScore` | Share of total revenue (percentage) | | `ranking.occurrenceRank` | Rank by number of transactions | | `ranking.occurrenceScore` | Share of total occurrences (percentage) | | `total` | Aggregated amount and count over the entire observed period | | `monthlyOverview[]` | Month-by-month breakdown of payments to/from this partner | | `paymentTimespan` | First and last transaction date with this partner | *** ## Top Categories Required scope: `company-top-category` · Endpoint: **[GET /top-categories](/api#tag/Company-Top-Categories/operation/get-company-top-categories-by-user-id)** Shows how company is distributed across transaction categories. For each detected category, a monthly and daily time series of amounts is provided. ### Response structure | Field | Description | |-------|-------------| | `categories[]` | List of detected spending categories | | `categories[].category` | Category identifier | | `categories[].paymentType` | Payment type: earning / spending | | `categories[].monthlyOverview[]` | Monthly amounts, sorted ascending by month | | `monthlyOverview[].month` | Month in `YYYY-MM` format | | `monthlyOverview[].amount` | Total amount for the month | | `monthlyOverview[].dailyOverview[]` | Per-day breakdown within the month | | `monthlyOverview[].dailyOverview[].date` | Date in `YYYY-MM-DD` format | | `monthlyOverview[].dailyOverview[].amount` | Total amount for that day | | `monthlyOverview[].dailyOverview[].transactionIDs` | IDs of the underlying transactions | --- # Analytics > Cockpits > Cockpits ### Overview As finoOS provides a wide range of data and insights in a modular way, the FinoOS Cockpit can be seen as a data sheet that combines most analyses into a single response. After a user has connected via FinoOS Banking, the cockpit can be obtained - as JSON ([person](/api#tag/Cockpits/operation/cockpits-get-person-cockpit), [company](/api#tag/Cockpits/operation/cockpits-get-company-cockpit)) - this is also available as webhook callback - as a [PDF](/api#tag/Cockpits/operation/cockpit-download) - as a [web link](/api#tag/Cockpits/operation/cockpit-get-cockpit-link) and is available for person or company finoOS users. Here is an example of how a person cockpit looks when viewed as a web link: ![Cockpit - Person - Example](/img/cockpit_person_1.png) ### Configuration The cockpit is fully customizable and can be adapted to your needs. This means that you can - choose which modules should be included in the cockpit - choose the layout and order of the modules - customize the design of the cockpit with your own branding and colors via the [patch cockpit tenant config](/api#tag/Cockpit-Tenants/operation/cockpits-patch-tenant). ### Advisors Another aspect of the cockpit is that it can be used to directly share data from the end user with a potential advisor or consultant within your company. As shown in the screenshot, there is a "Send to consultant" button that the end user can use to share the cockpit with a consultant if desired. For this to work, you have to set up [Advisors](/api#tag/Cockpit-Advisors) via the API. Each advisor will then receive a unique link that end customers can use to create cockpits for them. The process looks like this: 1. You create an advisor via the API and receive a unique link for that advisor. 2. You share that link with your end users (e.g. via email or website). 3. The end user clicks the link and creates a cockpit by connecting their bank data via FinoOS Connect. 4. The end user clicks "Send to consultant" to share the cockpit with the advisor. 5. The advisor receives an email with a link to view the end user’s cockpit. 6. Depending on your use case, the advisor can then contact the end user to provide advice or support based on the insights from the cockpit. ### Managed Cockpit Portal Although the cockpit and all its features are available via the API, if you only intend to use the Cockpit and no other finoOS API features, we also provide a managed Cockpit Portal. This portal allows you to set up your Cockpit Tenant and Advisors via a web UI without the need to write any code or perform any API integration. If this is of interest to you, please [contact](https://kontoanalyse.de/kontakt/) us directly. --- # Analytics > Other > Companies The finoOS Companies module provides access to a database with thousands of verified companies. It holds information about these companies' addresses, contact information, logos, creditor identifiers, related bank accounts and more. Example: 1. **Authentication** - Request access credentials via **[Authentication](/api#tag/Authentication/operation/authentication-authenticate)** 2. **Search Companies** - Search by company name, IBAN, etc.: **[Search Companies](/api#tag/Companies/operation/companies-search-companies)** 3. **Search Logos** - Find company logos: **[Search Logos](/api#tag/Companies/operation/companies-search-logos)** 4. **Provide Logo Feedback (optional)** - Report missing or incorrect logo: **[Create Feedback](/api#tag/Feedback/operation/feedback-create)** with type `missing-logo` or `wrong-logo` --- # Analytics > Other > Webhooks ## Overview Webhooks are **HTTP callbacks** which can be used to send **notifications** to your service/server *when data in a user* on your client *has been changed*. Rather than making an API call, **finoOS2** sends an HTTP request with the data that has been changed to an endpoint you configure. ## Setup The webhooks module allows you to *set up* such **user-defined HTTP callbacks** by subscribing to **events**. Using the webhook module requires the following: - Make sure your client has the `webhooks` scope to have access to the webhooks module - Create a *webhook endpoint on your server* - Use the finoOS2 webhook module to **[set up your webhook](/api#tag/Webhooks/operation/webhooks-create-webhook)** - Select your preferred **HTTP method** that shall be used to send the event related data to your webhook - *Pick one or multiple events* you want to subscribe to from the **[event list](#subscribable-events-and-their-payloads)** below - (Optional) *generate a secret* to secure your webhook - Create your webhook - Make sure your webhook endpoint *can process* the **[payload](#the-payload)** sent by **finoOS2**. - *Send a **2XX http status code** back* after processing the payload to signal **finoOS2** everything went fine - If the webhook response returns an HTTP status code above **299**, a **retry mechanism** is triggered. After a certain number of failed attempts, the process stops. ## Securing The Webhook Before you **[create a webhook](/api#tag/Webhooks/operation/webhooks-create-webhook)** with our webhooks module. Consider to securing the webhook you want to configure by generating a secret and configure you webhook with it. **finoOS2** does nothing with your secret but sending the secret along with the **[payload](#the-payload)** that gets send after a subscribed event triggers on a user. Your webhook endpoint needs *validate the secret to accept the request* on your server. If you already have configured a webhook and want to secure it afterwards. You can **[update your webhook](/api#tag/Webhooks/operation/webhooks-update-webhook)** with a secret. ## The Payload After setting up and optionally securing your webhook. It is time to receive the payload associated to the subscribed events after an event triggers. Down below you can see the generic payload that gets sent to your configured endpoint. - `webhookID` represents the unique identifier of the webhook - `userID` represents the user experiencing the change in data - `customUserID` is a identifier you can choose on **[create user](/api#tag/Users/operation/users-add-user)** - `tenantID` under which tenantID the user was created - `correlationID` which calculation process this event belongs to - `correlationTimestamp` when the calculation process was started - `secret` to secure your webhook - `event` that got triggered - `data` that changes [relevant to the event](#subscribable-events-and-their-payloads) that got triggered. ### Headers Along with the payload additional headers are sent to your configured webhook. These headers are: - `X-Request-Id` representing a unique identifier for the request or event trigger. For example used to trace back the path the event took. - `FinoOS-Tenant-ID` representing the tenant the event belongs to. ## Subscribable Events And Their Payloads --- # Analytics > Other > Feedback Improving our services is important to us. Therefore, sending us feedback helps us. Through the endpoint **[Create a feedback](/api#tag/Feedback/operation/feedback-create)** this is possible. Each feedback has a `module` and `type`. The `module` gives us information about the context of the feedback, e.g., the service or module the feedback is about. The `type` corresponds to the information that is given to us, on which we can act upon. Both of these fields are related to each other and can only be used in these combinations: | **Module** | **Supported Types** | |:---------------------------------------|:----------------------------------------| | contractor | rating, interaction | | cockpit | cockpit | | company-logos | missing-logo, wrong-logo, outdated-logo | > Important: Each `type` influences the required `feedback`-field model! --- # Other Documentation --- ## Untitled (banking/connect-flows/internal-troubleshooting.md) # Internal Troubleshooting Guide ## Protocol-Specific Failure Patterns ### PSD2 Interfaces **Common problems** - OAuth token expiration - Redirect URI mismatch - Consent duration limits (e.g., 90 or 180 days) - Bank sandbox vs production mismatch - Missing scopes **Typical Strategy** - Restart full authorization flow - Verify redirect URL - Validate scope configuration ### FinTS Interfaces **Common problems** - PIN lock after multiple failures - TAN method deactivated - Bank migration to new FinTS version - Dialogue termination errors - Account not allowed for FinTS access **Strategy** - Confirm login works in official banking software - Verify correct TAN procedure - Retry after lock reset ### Web-Based Interfaces (Scraper-Like) **Common problems** - HTML layout changes - CAPTCHA introduced - Additional security questions - Session cookie handling changes **Strategy** - Retry later - Escalate if systematic - Inform user about temporary bank changes ## Connection Establishment Issues (Internal Details) - Bank interface temporarily unavailable (protocol-specific) - Bank removed or migrated to new interface (protocol-specific) - Regional restrictions (protocol-specific) - Maintenance window (protocol-specific) ## Account Type Not Available (Internal Details) - Bank exposes different account types per interface - Selected interface does not support requested account type - Bank-side filtering ## Authentication Fails During Login (Internal Details) | Protocol | Typical Causes | | -------- | -------------------------------------------------------------- | | PSD2 | Invalid credentials, OAuth rejection, redirect URI mismatch | | FinTS | PIN locked, wrong credentials, TAN method mismatch | | Scraper | Layout change, CAPTCHA, additional security prompt | ## SCA Flow Issues (Internal Details) - Embedded SCA: TAN expired, challenge timed out, incorrect TAN, device binding changed - Decoupled SCA: User did not approve in banking app, approval window expired, push notification disabled - Redirected Flow: Redirect URI mismatch, user manually closed window, third-party cookie blocking, session timeout ## Synchronization Issues (Internal Details) - Consent expired silently (protocol-specific) - Bank-side downtime (protocol-specific) - Recurring user flag not set (protocol-specific) ## Known Operational Characteristics (Internal Details) - Only one valid consent per bank login - Consent always tied to bank login, not account level - User interaction mandatory for renewal - Recurring sync disabled automatically after challenge-required errors - Synchronization schedule not configurable - Bank behavior may differ per account type and interface --- ## Support (support.mdx) ## Contact Support If you have questions, issues, or encounter unexpected behavior, please contact our support team via email: **📧 support.analytics@fino.digital** To help us investigate and resolve your request as quickly as possible, please include **as much of the following information as you can**. *** ### Required information - **Client ID** ( identifier you are using to access the API ) - **Request ID** ( if available, from response headers or the error code displayed in the Banking Frontend ) *** ### If the issue affects a specific user - **User ID** *** ### Issue description Please describe the issue as clearly and precisely as possible, for example: - affected endpoint / API path - date and time when the issue occurred - expected behavior - actual behavior - relevant error messages or response codes - screenshots (if applicable) - correlation ID (if available) > The more complete the provided information is, the faster we can analyze and resolve the issue.