# Background

The Account Aggregator (AA) infrastructure is a sophisticated technological framework designed to revolutionize data sharing across the financial sector in India. The collaboration among financial sector regulators (FSRs)—Reserve Bank of India (RBI), Securities and Exchange Board of India (SEBI), Insurance Regulatory Development Authority (IRDA), and Pension Fund Regulatory Development Authority (PFRDA)—under the Financial Sector Development Council (FSDC) has aimed to establish a seamless, secure, and efficient data-sharing mechanism.

The Reserve Bank Information Technology Pvt Ltd (ReBIT), a wholly-owned subsidiary of the RBI, was authorized to establish technology standards for the ecosystem. This regulatory framework established a high-level architecture, and the market was kept independent of operationalizing the data-sharing mechanism. This market-driven approach has led to the formation of Sahamati as an industry alliance to collaboratively build the necessary procedural and technological foundations for the AA ecosystem.

SahamatiNet is the technological infrastructure developed and maintained by Sahamati to support the Account Aggregator (AA) EcoSystem. Hosted in a secure, highly available, and scalable environment, this technological infrastructure ensures the robustness and reliability of the AA EcoSystem. The infrastructure aims to engender trust, build visibility in ecosystem health, offer implementation support and grievance redressal mechanisms, foster a culture of compliance, and enable efficient integrations across the ecosystem. Sahamati has co-created these crucial technology artefacts with the collective intelligence of the ecosystem to serve its diverse needs.

Delve into the functional aspects of the SahamatiNet:

<table data-card-size="large" data-column-title-hidden data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Network Trust</strong></td><td>Sahamati's Central Registry securely lists verified AA ecosystem entities and uses a Token Service to enable trusted, authorized data exchange.</td><td><a href="/files/jiYL2Xww2HoPFhNb3oCJ">/files/jiYL2Xww2HoPFhNb3oCJ</a></td><td><a href="/pages/hMHWhem7J8qEjKLmLPZH#network-trust">/pages/hMHWhem7J8qEjKLmLPZH#network-trust</a></td></tr><tr><td><strong>Network Health</strong></td><td>Sahamati's network health monitoring and MIS dashboards provide real-time visibility and insights to detect issues early, ensure smooth operations, and track key ecosystem metrics.</td><td><a href="/files/2ol50SxrGC2amyHgo2uH">/files/2ol50SxrGC2amyHgo2uH</a></td><td><a href="/pages/hMHWhem7J8qEjKLmLPZH#network-health">/pages/hMHWhem7J8qEjKLmLPZH#network-health</a></td></tr><tr><td><strong>Certification</strong></td><td>Sahamati promotes compliance in the AA ecosystem through a standardized certification process that ensures adherence to ReBIT standards, fosters trust, and enables seamless interoperability.</td><td><a href="/files/HfZ0h1ACZVRbTxqzWp1p">/files/HfZ0h1ACZVRbTxqzWp1p</a></td><td><a href="/pages/hMHWhem7J8qEjKLmLPZH#certification">/pages/hMHWhem7J8qEjKLmLPZH#certification</a></td></tr><tr><td><strong>Network Support</strong></td><td>Sahamati offers support and drives SahamatiNet to ensure seamless onboarding, interoperability, compliance, observability, and policy advocacy for a robust AA ecosystem.</td><td><a href="/files/9Y6hoCZbXDjnqo5PKnIu">/files/9Y6hoCZbXDjnqo5PKnIu</a></td><td><a href="/pages/hMHWhem7J8qEjKLmLPZH#network-support">/pages/hMHWhem7J8qEjKLmLPZH#network-support</a></td></tr></tbody></table>

### Network Trust <a href="#network-trust" id="network-trust"></a>

Sahamati maintains a Central Registry (CR) to facilitate the discoverability of public information related to each member endpoint. CR is a comprehensive database listing all authenticated and authorized entities within the AA ecosystem. It ensures that only verified Account Aggregators, Financial Information Providers (FIPs), and Financial Information Users (FIUs) can participate. CR empowers eligibility verification and streamlines the onboarding process onto the network, fostering stakeholder confidence and trust.

The CR is supported through a token service that ensures the validity & reliability of end-point information. It enhances security by managing secure and efficient data exchanges between entities. It issues and validates tokens, ensuring that all data requests and transfers are authenticated, authorized, and encrypted. By codifying network-level authorization rules, the token service safeguards against unauthorized access and enhances trust within the network.

### Network Health

Sahamati has built a network health monitoring infrastructure that provides visibility into various parameters of health in the ecosystem. Through continual tracking of the performance of the ecosystem, the system equips identification of potential issues such as downtimes or implementation bugs. It enables proactive management and rapid resolution of any disruptions, ensuring smooth and efficient operations. Complementing the monitoring system are the Management Information System (MIS) dashboards, which offer real-time visibility into key metrics and performance indicators. These dashboards provide detailed insights into volumes of accounts linked as well as consents fulfilled.

### Certification

Sahamati is committed to fostering a culture of compliance in the Account Aggregator (AA) ecosystem. It has institutionalized a certification process before onboarding members to foster a standardized and secure ecosystem. Members can opt for this certification service to ensure adherence to the Technical Standards set by ReBIT and simplify compliance. Sahamati has strategically empanelled organizations to provide independent certification services, guaranteeing compliance and impartial assessment. Certification also fosters trust and enables easy integration, facilitating seamless interoperability and reducing integration friction.

### Network Support

Sahamati equips the ecosystem with implementation support and grievance redressal mechanisms. During the implementation phase, Sahamati provides comprehensive support, offering technical assistance, guidance, and resources to ensure smooth onboarding and effective utilization of the infrastructure. A dedicated support application is available to address grievances and resolve issues faced by members. This mechanism ensures that any problems are promptly addressed, maintaining member satisfaction and trust in the ecosystem.

SahamatiNet aims to create an interoperable, customer-centric ecosystem through a secure, transparent, and efficient infrastructure. This holistic infrastructure ensures the reliability, security, and growth of the AA ecosystem. The infrastructure enhances the efficiency of data-sharing transactions and promotes trust and collaboration among all stakeholders, driving the overall success of the AA ecosystem.

Currently, SahamatiNet is dedicated to addressing key ecosystem challenges, including interoperability, data usage compliance, and operational efficiency, to provide a seamless experience for AA ecosystem members. The following are the primary focus areas of SahamatiNet:

* **Interoperability:** Enable ecosystem members to connect seamlessly with all other Sahamati Network entities. This eliminates the need for multiple integration points, significantly reducing the integration and operational efforts for members.
* **Fair Use Compliance:** FIUs and AAs are expected to align their consent usage within ecosystem-defined boundaries to ensure the fair use of AA. SahamatiNet aims to develop a programmatic, policy-based automated framework that ensures compliance with fair use policies regarding customer consent and data.
* **Network Observability:** SahamatiNet aims to scale the current network health monitoring system to a comprehensive infrastructure that provides real-time data access and monitors fraud to aid efficient dispute resolution, billing & reconciliation, and tracking network usage.
* **Policy Development and Advocacy**: The organization is engaged in developing policies and advocating for regulatory frameworks that support the growth and sustainability of the AA ecosystem.
* **Additional Initiatives**: Sahamati is continually exploring and implementing other initiatives to support and enhance the AA ecosystem's functionality and resilience.

However, it is important to adopt and implement technological solutions alongside governance measures to expedite the resolution of these challenges.


# SahamatiNet POC

## SahamatiNet

SahamatiNet is the technological infrastructure developed and maintained by Sahamati to support the Account Aggregator (AA) ecosystem. It comprises a set of specifications, Application Programming Interfaces (APIs), and services aimed at improving the ecosystem's performance, trust, and reliability. By establishing a robust infrastructure, SahamatiNet addresses key challenges such as interoperability, data compliance, data quality, and operational efficiency, thereby ensuring a seamless and trustworthy experience for AA ecosystem entities involved.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Introduction</strong></td><td>SahamatiNet streamlines the AA ecosystem by enabling FIUs, AAs, and FIPs to integrate through a single platform, reducing complexity and improving interoperability.</td><td><a href="/files/D58rJfGathP2qlZ2hM3g">/files/D58rJfGathP2qlZ2hM3g</a></td><td><a href="/pages/4XwzJRST3DaCJAb682un">/pages/4XwzJRST3DaCJAb682un</a></td></tr><tr><td><strong>Applications</strong></td><td>SahamatiNet Applications enable secure, seamless integration in the AA ecosystem through the router, central registry, and identity access management.</td><td><a href="/files/oHQ91KlbtJ5ZiJ9Jp0WD">/files/oHQ91KlbtJ5ZiJ9Jp0WD</a></td><td><a href="/pages/XXnYQrid7QRGZdhvL60X">/pages/XXnYQrid7QRGZdhvL60X</a></td></tr><tr><td><strong>Observability</strong></td><td>It focus on monitoring metrics, logs, and alerts for performance and health. It ensures quick detection of issues, real-time tracking, and visualized data to maintain operational efficiency and transparency.</td><td><a href="/files/dwKocwTqmn2v2q70QsOM">/files/dwKocwTqmn2v2q70QsOM</a></td><td><a href="/pages/A66taPH4paCIxJKP8wQ9">/pages/A66taPH4paCIxJKP8wQ9</a></td></tr><tr><td><strong>API Specification</strong></td><td>The SahamatiNet API Specification for Central Registry (CR), IAM and Router.</td><td><a href="/files/7uIkfMgQRKxhawLAECW2">/files/7uIkfMgQRKxhawLAECW2</a></td><td><a href="/pages/Ivx87BIb1DDfn2aAFskU">/pages/Ivx87BIb1DDfn2aAFskU</a></td></tr><tr><td><strong>Onboarding</strong></td><td>Overview of participation in the SahamatiNet Router PoC within the Sandbox environment as part of the onboarding process.</td><td><a href="/files/apJdmuJOKnTHwU9JZdAQ">/files/apJdmuJOKnTHwU9JZdAQ</a></td><td><a href="/pages/CCdZbrGZsjqAsRhxCqK1">/pages/CCdZbrGZsjqAsRhxCqK1</a></td></tr><tr><td><strong>Integration with SahamatiNet Router</strong></td><td>Provides technical guidance and code-level instructions for integrating your system with the SahamatiNet Router.</td><td><a href="/files/wiWuoM2eBSxV2wemc5TW">/files/wiWuoM2eBSxV2wemc5TW</a></td><td><a href="/pages/K0ikdfmrEU0ycGo1Za8G">/pages/K0ikdfmrEU0ycGo1Za8G</a></td></tr></tbody></table>


# Introduction

### **Current AA Network Mode - Many to Many Integrations**

The integration and interoperability within the AA ecosystem are significantly simplified through the use of SahamatiNet, a unified platform that serves as a central hub for all participants—FIUs (Financial Information Users), AAs (Account Aggregators), and FIPs (Financial Information Providers). Traditionally, these entities would have to establish separate connections and integrations with one another, each facing unique challenges related to data exchange, security, and compliance with standards. However, with SahamatiNet, this complexity is reduced as all participants—FIUs, AAs, and FIPs—now only need to integrate with this single application.

<figure><img src="/files/yhLrCmptsBgkyUv70o00" alt=""><figcaption><p>Existing Integrations in AA ecosystem</p></figcaption></figure>

At present, the integration model within the Account Aggregator (AA) ecosystem involves multiple connections:

* **(FIU x AA)**: Financial Information Users (FIUs) integrate with Account Aggregators (AAs).
* **(AA x FIP)**: Account Aggregators (AAs) also integrate with Financial Information Providers (FIPs).

This results in a complex network of individual, point-to-point connections between participants, which increases the integration effort and maintenance overhead.

## **Interoperability**&#x20;

SahamatiNet serves as a central interface that **significantly enhances interoperability** within the AA ecosystem. It allows all participants—FIUs, AAs, and FIPs—to interact seamlessly by leveraging a unified set of shared protocols and standards defined by ReBIT. By integrating with SahamatiNet Router, each participant can effortlessly connect with and exchange data with other members of the ecosystem, **without needing to establish multiple individual integrations**. This centralised approach reduces complexity and eliminates the need for separate, technical connections, ensuring consistent data handling, security, and **simplified interoperability across all participants**.

The platform standardises communication between all roles, facilitating smoother and more efficient connections. Participants no longer have to navigate through complex and disparate systems to access necessary data or services. Instead, they rely on SahamatiNet Router to manage interactions, significantly simplifying integration efforts. This approach leads to a more streamlined and scalable model for data exchange, security enforcement, and access management, fostering a cohesive ecosystem. By consolidating previously fragmented connections into a single, unified application, SahamatiNet Router makes interoperability faster, more secure, and more efficient for all participants in the AA ecosystem.

<figure><img src="/files/FUay7qE2oTBoJsU9Zrtv" alt=""><figcaption><p>Integrations using SahamatiNet Router for AA ecosystem</p></figcaption></figure>

However, as entities integrate with **SahamatiNet**, this integration model will be streamlined. The number of necessary integrations will be significantly reduced to a simpler structure:

* **(FIU + AA + FIP)**: Financial Information Users (FIUs), Account Aggregators (AAs), and Financial Information Providers (FIPs) will now interact with one central service (SahamatiNet). This centralisation simplifies the communication process, reduces the number of direct integrations, and enhances the overall efficiency of the ecosystem.

## Delegation of Trust&#x20;

The AA ecosystem shifts from a traditional **bilateral-trust** model to a more scalable **network-trust** framework, where trust is centrally managed through SahamatiNet. This framework guarantees interoperability across all participants—FIPs, AAs, and FIUs—by applying consistent security standards and protocols. Instead of each participant individually establishing trust with others, trust is delegated to SahamatiNet, ensuring secure and seamless interactions throughout the ecosystem.

\
To maintain this trust, **FIPs** are required **to subject SahamatiNet** to a rigorous onboarding process before integrating with it, ensuring the platform meets their security and operational standards. Once FIPs are onboarded, **Sahamati** applies the same level of scrutiny when **onboarding AAs.** Similarly, **AAs** apply rigorous checks when onboarding **FIUs,** and once an FIU passes this process, **Sahamati** applies the same level of rigor to onboard the **FIU to SahamatiNet**. This **delegation of trust** streamlines the process, enabling more efficient and reliable interoperability across the entire AA ecosystem.


# Applications

SahamatiNet Applications

## SahamatiNet Router

Interoperability is a core challenge in any data-sharing ecosystem. The Router acts as a bridge to ensure smooth and standardised communication between various ecosystem members using ReBIT APIs. When a request is made by one member to another (such as an FIU requesting data from an FIP), the Router  ensures that the API requests and responses are correctly routed and formatted. This service is crucial for ensuring that no matter what system or infrastructure a member uses, the interaction remains standardised and interoperable across the network.

**Key Features:**

* Facilitates interoperability between ecosystem members.
* Routes and standardises API requests and responses.
* Simplifies cross-ecosystem communication by eliminating compatibility issues.

### Current API reference <a href="#current-api-reference" id="current-api-reference"></a>

The following diagram shows the current flow between FIU and AA flow for Consent API. With the current structure, the API requests are sent to the respective recipient member directly. This requires each member to understand the metadata of the recipient member and use their base path while sending.

<figure><img src="/files/6WFmDNU54NNnVhaiUUzH" alt=""><figcaption><p>Existing approach to use the APIs by AA Ecosystem in case of Consent API between FIU and AA</p></figcaption></figure>

### Using Sahamati Router APIs <a href="#using-sahamati-proxy-apis" id="using-sahamati-proxy-apis"></a>

Sahamati Router simplifies the process for members to send requests to any recipient by simply including the recipient identifier (**x-recipient-id**) in the header, under **x-request-meta**. The Router will then redirect the request to the corresponding recipient. This update must be implemented across all ReBIT APIs in the respective regulated entity's application.

<figure><img src="/files/JIKOOc3nLAWpEjCgGfzc" alt=""><figcaption><p>Using Sahamati Router APIs for AA Ecosystem for Consent API between FIU and AA</p></figcaption></figure>

Currently, the Router is fully implemented with all APIs compliant with ReBIT specifications v2.x.

## Central Registry (CR)

The Central Registry is a core service in the AA ecosystem, provided by Sahamati, which serves as a directory for all participants—Account Aggregators (AAs), Financial Information Providers (FIPs), and Financial Information Users (FIUs). It provides essential information about each participant, including their public IP addresses and public keys, enabling secure and interoperable communication within the ecosystem.

The Central Registry offers an API that allows participants to access details of other members, subject to role-based access restrictions. These roles are defined through identity tokens issued by Sahamati, ensuring that each participant can only access relevant information. For instance, AAs can fetch details of FIPs and FIUs, while FIPs and FIUs can retrieve information about AAs.

Additionally, the Central Registry is closely integrated with the Token Issuance service, which provides each participant with a short-lived JSON Web Token (JWT) for secure API calls across the ecosystem. This JWT is used to authenticate each participant and must be refreshed every 24 hours.

The Central Registry ensures seamless interaction within the AA ecosystem by making vital participant information easily accessible and securely managed.

## Identity Access Management (Token Service)

The Identity and Access Management (IAM) system within the AA ecosystem is responsible for ensuring secure and authorized access to ecosystem APIs. It manages participant roles, such as AA, FIP, or FIU, which are assigned during registration and embedded in the identity tokens issued by Sahamati. These roles govern access to services and ensure that participants can only access information they are authorized for.

To facilitate secure interactions, IAM utilizes Access Tokens—short-lived JSON Web Tokens (JWT)—to authorise participants when they access ecosystem APIs. The Access Tokens, linked to the participant's role, ensure that only authorised individuals or entities can retrieve specific data or interact with services. Through role-based access control and token-based authentication, IAM safeguards the ecosystem's integrity and protects sensitive data while enabling secure communication among participants.


# Observability

SahamatiNet Router serves as an additional layer on top of the AA network, offering extra services and policies. By integrating with the Sahamati Router, FIUs, FIPs, and AAs can seamlessly connect with all other entities within the Router. This eliminates the need for multiple integration points, significantly reducing the integration and operational efforts for members

**Comprehensive Technology Infrastructure – SahamatiNet**&#x20;

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc7KiX9_kkwnLYvbtjjGXAM3mrrcDl_7-Rt-Bx5vTtpkapn50xLgWBbac-iM-Ad7ws8f06PQf9LKIIYVyrhz7Fj-NnVLICwFd6kyEVZwUG44L2Y7P4oRj-mCUqQtJ5yOwPR5-fZBw?key=IIQ76WiEq3n0M56Feh3IbF87" alt=""><figcaption></figcaption></figure>

**SahamatiNet - Services on Observability**

**MIS** :&#x20;

Daily reports on Discovery, Linking, Consent, and data fetch, generated from the Router’s meta data. Will be more accurate that currently available due to varying cadences, formats, incorrect data and naming conventions.

**Network Health :**&#x20;

Complete picture of health of FIP and AA applications derived from a single source of truth. Avoids overlapped calls from AAs to the FIPs and ecosystem health reporting is not dependent on vagaries of reporting.

**SLA Reporting :**&#x20;

* Report on SLA Adherence for each scenario’s success case, error rate for AAs and FIPs.
* Need to define and agree SLAs for each ecosystem participants and report on adherence and Report on non-adherence to SLA commitments

**NOC Support :**&#x20;

* Sahamati NOC Support using Network Health metrics and SLA Adherence
* Facilitates proactive action to correct ‘sick’ nodes
* Grievance Redressal

**Technical Audit :**

* API Telemetry&#x20;
* Tracking of changes in Ecosystem such as onboarding of REs, ad

**Billing and Recon :**

Generate data fetch statements to support downstream billing & any reconciliation efforts amongst participants bilaterally<br>


# Integration Steps

For the SahamatiNet Proof Of Concept (POC)

## SahamatiNet POC Onboarding Checklist

1. **Register as a Ecosystem Member for POC**&#x20;
   1. Identify the key fields needed for registration.
      1. Choose your **member type**: Account Aggregator (AA), Financial Information Provider (FIP), or Financial Information User (FIU).
      2. Provide the following organisation details for the Central Registry (CR):
         * Entity ID (unique identifier)
         * Base URL for your service
         * RSA Public Key for secure communication
         * IP Address, Inbound and Outbound Ports (for production; optional for UAT and Sandbox)
      3. **Designate a user** (preferably with a service email account) to manage the entity as an admin in CR and IAM.
   2. Complete the [Google Form for Registration](https://forms.gle/JKPSivKt36P4iH3a7) to onboard with the Central Registry (CR).&#x20;
2. **Verify and Set Up User and Entity Access Tokens**&#x20;
   1. The designated user will **receive an email with a password reset link**.
   2. **Reset the password** and complete the account setup.
   3. **Generate the User Access Token** using the user’s email and new password.
   4. Use the User Access Token to **read the entity’s secret** from the Sahamati IAM API.
      1. If needed, **reset the secret** using the designated API.
   5. Use the entity secret to **generate the Entity Access Token** for ReBIT APIs.
   6. Refer to the section on these APIs [here](/sahamatinet-poc/integration-steps/iam-apis)&#x20;
3. **Integrate with SahamatiNet Router in Sandbox**
   1. Understand the **required changes for integration with the Router.**
      1. Sahamati Router simplifies the process by allowing members to send requests to any recipient by adding the recipient identifier (**recipient-id**) in the header under **x-request-meta.** Refer [here](/sahamatinet-poc/integration-steps/integration-with-router) for more details.
   2. **Changes of additional step of onboarding in your application**
      1. With the transition to integrating with the SahamatiNet Router, the onboarding process for FIUs (Financial Information Users), AAs (Account Aggregators), and FIPs (Financial Information Providers) is no longer necessary. Previously, this step was essential for establishing peer-to-peer trust and enabling communication within the AA ecosystem. However, with Router integration, trust is managed through technical means, eliminating the need for additional onboarding on your side. &#x20;
      2. As an AA Ecosystem participant, **you can bypass the manual onboarding for FIUs, AAs, and FIPs in your application**. These participants would undergo the required compliance through SahamatiNet before interacting with other entities via the Router. **This change streamlines the integration process, removing the need for extra code or configuration**, and improving the efficiency and ease of connections across the AA ecosystem.&#x20;
      3. Note that while the technical integrations are now handled through the Router, the necessary commercial agreements between AA ecosystem participants remain unchanged and will continue as they are.
   3. **Review ReBIT workflows relevant to your entity** **using the Router**.&#x20;
      1. [Account Discovery and Linking workflows](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking)
      2. [Consent workflows ](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/consent-workflow)
      3. [FI Request workflows](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/fi-request-workflow)
4. **Integration with Simulators** &#x20;
   1. Test and validate the Router's functionality with ReBIT workflows tailored to your entity type by using the integration simulators in the sandbox environment (FIU, AA, FIP). You can also test this with your own simulators, if you have them. Please be sure to include the simulator details in the Google form provided above. We will onboard it for validation in the Sandbox environment as part of the POC.
   2. Refer to the section on how to use SahamatiNet simulators [here](https://app.gitbook.com/o/CcobtOsQAdIoa87kTGdF/s/fY7u471KMiCJqdTaYVzZ/~/changes/100/sahamatinet-poc/sahamatinet/testing-with-simulators) and respective simulators links below&#x20;
      1. [AA Simulator](/sahamatinet-poc/integration-with-simulators/aa-simulator)
      2. [FIP Simulator](/sahamatinet-poc/integration-with-simulators/fip-simulator)
      3. [FIU Simulator](/sahamatinet-poc/integration-with-simulators/fiu-simulator)
5. **Validate Integration with Simulators and Regulated Entities**&#x20;
   1. Conduct tests with other onboarded entities in the sandbox environment to review all integration points and ensure seamless operation.
   2. More details on this step will be provided as we progress through the POC.

By following these steps, you will successfully onboard and integrate with SahamatiNet in the sandbox environment, ensuring compliance with ReBIT specifications and the AA ecosystem standards


# Sandbox Onboarding

## Sandbox Onboarding

To participate in the SahamatiNet Router in the Sandbox, an entity (AA, FIP, or FIU) must ensure its API implementation is ReBIT standards-compliant. This ensures that the entity's APIs meet the necessary interoperability standards for the AA ecosystem and can be tested via the SahamatiNet Router.

The onboarding process involves submitting the **Entity (member) information** such as

<table><thead><tr><th width="262">Property Name</th><th>Description</th></tr></thead><tbody><tr><td>ID (Entity ID)</td><td><p>Unique identifier for your organisation used as Entity ID in Central Registry. </p><p></p><p><a href="/pages/AVQmKqc4gZ5a2f2rNpe1">Learn how to choose an Entity ID</a></p></td></tr><tr><td>Name</td><td>Name of the entity</td></tr><tr><td>Type</td><td>Entity Type - one of FIU, FIP, AA (<strong>Member Type</strong>)</td></tr><tr><td>Base URL</td><td><p>Base URL ( Endpoint ) of your respective application to access the APIs and send requests. </p><p><br><strong>(Only v2 API endpoint are supported in Sandbox environment)</strong></p></td></tr><tr><td>Certificate</td><td><p>The <strong>RSA public key</strong> of the entity for secure communication. It will be used by the members to validate the signature </p><p>(<code>x-jws-signature</code>) of the API request.</p><p></p><p><a href="/pages/p1ZHuH5NA0jRxmXazs4U">Learn how to create this certificate</a>.</p></td></tr><tr><td>ips</td><td>The IP address(es) of the entity to whitelist to access of Sahamati Network services (Ex: Router).</td></tr><tr><td>inboundports</td><td>The port of the member that the Sahamati services can connect to.</td></tr><tr><td>outboundports</td><td>The port of the member that the Sahamati services can expect to receive requests from.</td></tr><tr><td>entityhandle</td><td>Relevant and required only for AAs.</td></tr></tbody></table>

For Ecosystem **Member Type:**  Specify whether you represent an AA, FIP or FIU.&#x20;

* **Account Aggregators (AA) :** Entities that facilitate the secure sharing of user financial data between financial information providers (FIPs) and financial information ussers (FIUs)
* **Financial Information Providers (FIP) :** Entities that hold user financial data, such as banks, NBFC, etc.&#x20;
* **Financial Information Users (FIU):** Entities that seek user financial data to provide value-added services like loans, wealth management, and more.&#x20;

For **IP Address, Inbound and Outbound Ports:** Network details for connecting with the AA ecosystem are required for Production, optional for UAT and Sandbox.

**The Designated User of the entity information such as**

<table><thead><tr><th width="266">Property Name</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Name of the user from entity who will manage client secret </td></tr><tr><td>Email</td><td>Email address of the user - preferably service account email </td></tr><tr><td>Mobile [Optional]</td><td>Mobile number of the user</td></tr></tbody></table>

{% hint style="success" %}
The member (entity) will be onboarded along with **a user with admin role** for managing the profile, secret rotation of entity etc,.
{% endhint %}

{% hint style="info" %}
Once the member entry is added to CR, they can whitelist Sahamati Router IP.
{% endhint %}

**Designated User:** Contact details of the representative responsible for generating and managing the client secret in IAM (Token Service). It is recommended to use a service account email for the long-term management and consistency.&#x20;

Ecosystem Member should provide the above details in the [Google Form](https://forms.gle/puL3DnurVQg28iSw5). Sahamati team will validate the details and onboard the entity as the member to the Sahamati's Central Registry (CR) and IAM (Token Service).&#x20;

If you're experiencing difficulties accessing the Google form from your organization's network, you can alternatively generate the following JSON request and email it as an attachment to **<sandbox@sahamati.org.in>**. Please use the subject line: **Onboarding to SahamatiNet Router POC**: and make sure to include the designated user's email ID and full name for each entry.

```json
{
    "type": "<Entity Type - one of FIU, FIP, AA>",
    "requester": {
        "name": "<Your Organisations Full Legal Name>",
        "id": "<Entity ID.. YourOrgsUniqueShortName_Environment_EntityType>"
    },
    "entityinfo": {
        "name": "<Your Organisations Full Legal Name>",
        "id": "<Entity ID.. YourOrgsUniqueShortName_Environment_EntityType>",
        "code": "<Same as above>",
        "entityhandle": "<Your Organisations AA Handle, Only relevant for AA entity type>",
        "Identifiers": [
            {
                "category": "STRONG",
                "type": "MOBILE"
            }
        ],
        "baseurl": "<Base URL of the entity to access ReBIT APIs. Only v2 is supported.>",
        "fitypes": [
            "<Supported FI Types>"
        ],
        "certificate": {
            "<Certificate data>"
        },
        "inboundports": [
            "<in bound ports>"
        ],
        "outboundports": [
            "<out bound ports>"
        ],
        "ips": [
            "<Whitelist IP addresses>"
        ]
    }
}

```


# IAM APIs

Identity and Access Management ( Token Service) APIs

Each member of the Sahamati Network will be onboarded with a designated user who holds an admin role to manage the entity’s profile and secret.

* During the onboarding process, the designated user will receive an email containing a verification link. After email verification, **the user will be prompted to set a password**, completing the account activation process.
* Once the password is set, **the user can generate the User Access Token** by providing their email and the new password. This token is used for authenticating the entity’s secrets.
* The designated user can then use the User Access Token to **access the entity’s secret** and, if necessary, **reset the secret**.
* Finally, the entity secret is used to **generate the Entity Access Token**, which is needed for interactions with the ReBIT APIs within the AA network.

### Entity Token Generation use case&#x20;

The Regulated Entities (REs) should generate the Access Token using the Token API from Sahamati for accessing and authentication of any APIs in the AA ecosystem including Sahamati APIs.

Here is the sequence diagram for the Token Generation Process.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdc4HeMCiC89Fdmj_Xf0Nv3AZZKB6BuqMxBUGRt41o73HkYfBchfZOQ9S_a5dg6nK32KXqo44LBDV1AhjU_IyorOrAk0PFyphQuHLr0k3ilJwrjo2xbHH6XFFhwJB0hZWZuW62-0Q?key=3aTz-3SKYP0rOCX7DFnLglx6" alt=""><figcaption><p>Token Generation use case diagram</p></figcaption></figure>

Below are the Base URL of each environment to use IAM APIs.

<table><thead><tr><th width="213.489501953125">Environment</th><th>Base URL</th></tr></thead><tbody><tr><td>Production</td><td>https://api.sahamati.org.in/iam</td></tr><tr><td>UAT</td><td>https://api.uat.sahamati.org.in/iam</td></tr><tr><td>Sandbox (Used for PoC)</td><td>https://api.sandbox.sahamati.org.in/iam</td></tr></tbody></table>

Please note that the following documentation displays the Base URLs from the Sandbox environment. Ensure you use the appropriate Base URLs depending on the environment you are working in.

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/user/token/generate" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/secret/read" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/secret/reset" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/token/generate" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

## Token Generation APIs:

#### API Postman Collection:&#x20;

{% hint style="info" %}
We recommend you to use below postman collection to try out our Token-Service\[IAM] APIs
{% endhint %}

{% file src="/files/LrPZkvetWRM9Un9XGz41" %}

Below is the Sandbox Environment file for SahamatiNet Services

{% file src="/files/f7BJgqo2Kd0SC0Ix9y74" %}

## Member Secret Management APIs

#### API Collection:

{% file src="/files/nymDUvFE3Ay3pAtIgcs4" %}
Token-Service\[IAM] - API Collection
{% endfile %}


# CR APIs

Central Registry APIs

### Fetching Regulated Entities REs metadata using Central Registry (CR)

A RE should fetch the metadata of the other REs to interact with them through ReBIT APIs to handle the AA ecosystem functionalities. Sahamati provided the CR APIs to access the REs metadata. Here is the sequence diagram for Fetching REs metadata.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcTkKNOEJjQLqrQKi9iJSP8KjDbaa3nfnmSw_IcuBi2yhIjW7cLQKPBlv1k2r8UCmWGT21YNh7mnry6pxFUNKr4hGgwUTn-KjXvmrTcfC3EZkn5YEUV97NYyCZbw_-qmkJBGQsQMQ?key=3aTz-3SKYP0rOCX7DFnLglx6" alt=""><figcaption><p>Fetch REs Metadata using Central Registry</p></figcaption></figure>

{% openapi src="/files/jW0T1thS78gNa6XYDnMn" path="/v2/entityInfo/{type}" method="get" %}
[CR-Service-API-v1.0.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ULRrUF0meRjhWs0vS0Tx/CR-Service-API-v1.0.yaml)
{% endopenapi %}

{% openapi src="/files/jW0T1thS78gNa6XYDnMn" path="/v2/entityInfo/{type}/{id}" method="get" %}
[CR-Service-API-v1.0.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ULRrUF0meRjhWs0vS0Tx/CR-Service-API-v1.0.yaml)
{% endopenapi %}

#### API Collection:

{% file src="/files/6JfkK74IpWh1PQYJfoXX" %}
Central Registry - API Collection
{% endfile %}


# Integration with Router

## Implementing Code Changes for Router Integration

Outlined below are the changes that members need to make to their implementation to use the SahamatiNet Router.

* Use the following **Sahamati Router API endpoint** as base path for all the requests.

```url
https://api.sandbox.sahamati.org.in/router/v2
```

* Do note the Router API endpoint URL mentioned above is used for Sandbox, the respective URL for each environment (UAT and Production) will be updated when we progress to next environments.&#x20;
* Add the recipient ID under the new header **x-request-meta** with **recipient-id** in a JSON object which is the identifier of the receiver to whom the API call needs to be forwarded.
  * The value of the **x-request-meta** is Base64 string of the JSON object with recipient-id.
  * This structure helps us to easily extend the JSON object by adding the required attributes for future use cases.

{% hint style="success" %}

```
x-request-meta: <Base64 of JSON object 
{"recipient-id":"<entityID of the recipient>"}>
```

{% endhint %}

The receiver could be any of the participant, FIU, AA or FIP.&#x20;

<table><thead><tr><th width="109.80975341796875">Particulars</th><th width="284.70166015625">Comments</th><th>Values</th></tr></thead><tbody><tr><td>Host</td><td>The base path to use by the members of SahamatiNet Router.</td><td><a href="https://api.sandbox.sahamati.org.in/router">​</a><a href="https://api.sandbox.sahamati.org.in/router">https://api.sandbox.sahamati.org.in/router</a></td></tr><tr><td>Headers</td><td>This will remain same as previous.</td><td><p>​</p><ul><li>x-jws-signature - Authorization</li><li>Token (from sender)</li></ul></td></tr><tr><td>Additional Headers</td><td>The recipient id is a required property. It is the identifier of the receiver to whom the API call needs to be forwarded.</td><td>x-request-meta</td></tr></tbody></table>

These header changes need to be implemented for communication between FIU and AA, AA and FIP, FIP and AA, as well as FIU and AA.

## Service URLs for the Sandbox

Service Name and their URLS&#x20;

**Public Key**

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/auth/realms/sahamati/protocol/openid-connect/certs
```

{% endcode %}

**IAM (Token Service)** &#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/iam
```

{% endcode %}

**Central Registry (CR)**&#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/cr
```

{% endcode %}

**Router** &#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/router
```

{% endcode %}

Please ensure that, in addition to the changes in the ReBIT API calls, the **entity key validation** for the **public key** is also **pointing to the Sandbox** for your code changes for POC. These URLs will vary across different environments. You can find the Base URLs for these in the [FAQ section](/frequently-asked-questions#base-urls-for-each-environment).

**API Collection:**

{% file src="/files/xSJMC0lSa45pPMxbIdY3" %}


# Sample Code Snippets

These snippets details about the changes that members need to make to their implementation to use the SahamatiNet Router in different languages.

The code snippets have been created using the **Accounts-Discover Scenario** as a reference. The table below provides details of the available implementation samples across different languages along with their respective links.

#### Code Snippet By Programming Language

* [Python](/sahamatinet-poc/integration-steps/integration-with-router/sample-code-snippets/python)
* [Java](/sahamatinet-poc/integration-steps/integration-with-router/sample-code-snippets/java)
* [JavaScript](/sahamatinet-poc/integration-steps/integration-with-router/sample-code-snippets/javascript)
* [GoLang](/sahamatinet-poc/integration-steps/integration-with-router/sample-code-snippets/golang)
* [C#](/sahamatinet-poc/integration-steps/integration-with-router/sample-code-snippets/c)


# Python

***

<details>

<summary>Without Router - Current Approach</summary>

```python
# Assuming this as previous logic without Router
import requests

entity_metadata_from_cr = {
    "baseUrl": "http://fip-1.dev.sahamati.org.in/fip-simulate",
    "id": "FIP-SIMULATOR"
}

def get_http_config(base_url, route, headers, data, method_type):
    return {
        "url": f"{base_url}{route}",
        "headers": headers,
        "data": data,
        "method": method_type
    }

def execute_discovery_request():
    route = "/v2/Accounts/discover"
    
    config = get_http_config(
        base_url=entity_metadata_from_cr["baseUrl"],
        route=route,
        headers={},
        data={},
        method_type="POST"
    )
    
    try:
        response = requests.request(**config)
        return response.json()
    except Exception as error:
        print(f"Error making discovery request: {str(error)}")
        raise
def perform_another_operations(account_discover_response):
    print("Perform another operations with the response", account_discover_response)

if __name__ == "__main__":
    try:
        response = execute_discovery_request()
        perform_another_operations(response)
        print("Account discovery successful.")
    except Exception:
        print("Account discovery failed.")
    finally:
        print("Account discovery completed.")

```

</details>

<details>

<summary>With Router Integration</summary>

```python
# Changes to implementation to integrate with Router

import requests
import json
import base64

# Start - New Changes 

def generate_base64_encoded_json(json_data):
    json_str = json.dumps(json_data)
    return base64.b64encode(json_str.encode()).decode()

def generate_request_meta(recipient_id):
    context = {"recipient-id": recipient_id}
    return generate_base64_encoded_json(context)

def add_sahamati_configuration(config, route):
    router_url = "http://api.dev.sahamati.org.in/router"
    config["url"] = f"{router_url}{route}"
    if "headers" not in config:
        config["headers"] = {}
    config["headers"]["x-request-meta"] = generate_request_meta(entity_metadata_from_cr["id"])
    return config

# END - New Changes

# OLD Changes
entity_metadata_from_cr = {
    "baseUrl": "http://fip-1.dev.sahamati.org.in/fip-simulate",
    "id": "FIP-SIMULATOR"
}

def get_http_config(base_url, route, headers, data, method_type):
    return {
        "url": f"{base_url}{route}",
        "headers": headers,
        "data": data,
        "method": method_type
    }

def execute_discovery_request():
    route = "/v2/Accounts/discover"
    
    config = get_http_config(
        base_url=entity_metadata_from_cr["baseUrl"],
        route=route,
        headers={},
        data={},
        method_type="POST"
    )

    # add Sahamati configuration [Start]
    config = add_sahamati_configuration(config, route)
    # add Sahamati configuration [End]

    try:
        response = requests.request(**config)
        return response.json()
    except Exception as error:
        print(f"Error making discovery request: {str(error)}")
        raise

def perform_another_operations(account_discover_response):
    print("Perform another operations with the response", account_discover_response)

try:
    response = execute_discovery_request()
    perform_another_operations(response)
    print("Account discovery successful.")
except Exception as e:
    print(e)
    print("Account discovery failed.")
finally:
    print("Account discovery completed.")
```

</details>


# Java

<details>

<summary>Without Router - Current Approach</summary>

```java
// Assuming this as previous logic without Router
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;

public class EntityRequest {
    private static final String BASE_URL = "http://fip-1.dev.sahamati.org.in/fip-simulate";
    private static final String RECIPIENT_ID = "FIP-SIMULATOR";

    public static void main(String[] args) {
        try {
            String response = executeDiscoveryRequest();
            performAnotherOperations(response);
            System.out.println("Account discovery successful.");
        } catch (Exception e) {
            System.out.println("Account discovery failed. Error: " + e.getMessage());
        } finally {
            System.out.println("Account discovery completed.");
        }
    }

    private static String executeDiscoveryRequest() throws Exception {
        String route = "/v2/Accounts/discover";
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = getHttpConfig(BASE_URL, route, new HashMap<>(), new HashMap<>(), "POST");
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }

    private static HttpRequest getHttpConfig(String baseUrl, String route, Map<String, String> headers, Map<String, Object> data, String methodType) {
        String url = baseUrl + route;
        String jsonData = mapToJson(data);
        
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .POST(HttpRequest.BodyPublishers.ofString(jsonData))
                .header("Content-Type", "application/json");
        
        headers.forEach(builder::header);
        return builder.build();
    }

    private static void performAnotherOperations(String accountDiscoverResponse) {
        System.out.println("Perform another operations with the response: " + accountDiscoverResponse);
    }

    private static String mapToJson(Map<String, ?> data) {
        StringBuilder jsonData = new StringBuilder("{");
        for (Map.Entry<String, ?> entry : data.entrySet()) {
            jsonData.append("\"").append(entry.getKey()).append("\": \"").append(entry.getValue()).append("\",");
        }
        if (!data.isEmpty()) {
            jsonData.deleteCharAt(jsonData.length() - 1);  
        }
        jsonData.append("}");
        return jsonData.toString();
    }
}

```

</details>

<details>

<summary>With Router Integration</summary>

```java
// Changes to implementation to integrate with Router
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class EntityRequest {
    private static final String BASE_URL = "http://fip-1.dev.sahamati.org.in/fip-simulate";
    private static final String RECIPIENT_ID = "FIP-SIMULATOR";
    private static final String ROUTER_URL = "https://api.dev.sahamati.org.in/router";

    public static void main(String[] args) {
        try {
            String response = executeDiscoveryRequest();
            performAnotherOperations(response);
            System.out.println("Account discovery successful.");
        } catch (Exception e) {
            System.out.println("Account discovery failed. Error: " + e);
        } 
    }

    private static String executeDiscoveryRequest() throws Exception {
        String route = "/v2/Accounts/discover";
        String url = BASE_URL + route;
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = getHttpConfig(url, new HashMap<>(), new HashMap<>());
        // add Sahamati configuration [Start]
        request = addSahamatiConfiguration(request, route);
        // add Sahamati configuration [End]
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();  
    }

    private static HttpRequest getHttpConfig(String url, Map<String, String> headers, Map<String, Object> data) {
        String jsonData = JSONObject(data); 
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .POST(HttpRequest.BodyPublishers.ofString(jsonData))
                .header("Content-Type", "application/json");
        headers.forEach(builder::header);  
        return builder.build();
    }

    private static void performAnotherOperations(String accountDiscoverResponse) {
        System.out.println("Perform another operations with the response: " + accountDiscoverResponse);
    }

    private static String generateBase64EncodedJson(Map<String, String> json) {
        String jsonString = JSONObject(json);  
        return Base64.getEncoder().encodeToString(jsonString.getBytes());
    }

    private static String generateRequestMeta(String recipientId) {
        Map<String, String> context = new HashMap<>();
        context.put("recipient-id", recipientId);
        return generateBase64EncodedJson(context);
    }

    private static HttpRequest addSahamatiConfiguration(HttpRequest request, String route) {
        String newUrl = ROUTER_URL + route;
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(newUrl))
                .method(request.method(), request.bodyPublisher().orElse(HttpRequest.BodyPublishers.noBody()));
    
        request.headers().map().forEach((key, values) -> {
            for (String value : values) {
                builder.header(key, value);
            }
        });
        builder.header("x-request-meta", generateRequestMeta(RECIPIENT_ID));
        return builder.build();
    }
}

```

</details>


# JavaScript

<details>

<summary>Without Router - Current Approach</summary>

```javascript
// Assuming this as previous logic without Router
const axios = require('axios');

const entityMetadataFromCR = {
    baseUrl: 'http://fip-1.dev.sahamati.org.in/fip-simulate',
    id: "FIP-SIMULATOR"
}

const getHttpConfig = ({ baseUrl, route, headers, data, methodType }) => {
    return { url: `${baseUrl}${route}`, headers: headers, data, methodType };
};

const executeDiscoveryRequest = () => {
    const route = '/v2/Accounts/discover';

    const config = getHttpConfig({ baseUrl: entityMetadataFromCR.baseUrl, route, headers: {}, data: {}, methodType: 'POST' });

    axios.request(config)
        .then(response => response.data)
        .catch(error => {
            console.error('Error making discovery request:', error.message);
            throw error;
        });

};

const performAnotherOperations = async (accountDiscoverResponse) => {
    console.log('Perform another operations with the response', accountDiscoverResponse);
}

executeDiscoveryRequest()
    .then(performAnotherOperations)
    .then(() => console.log('Account discovery successful.'))
    .catch(() => console.log('Account discovery failed.'))
    .finally(() => console.log('Account discovery completed.'));

```

</details>

<details>

<summary>With Router Integration</summary>

```javascript
// Changes to implementation to integrate with Router
const axios = require('axios');

// OLD START

const entityMetadataFromCR = {
    baseUrl: 'http://fip-1.dev.sahamati.org.in/fip-simulate',
    id: "FIP-SIMULATOR"
}

const getHttpConfig = ({ baseUrl, route, headers, data, methodType }) => {
    return { url: `${baseUrl}${route}`, headers: headers, data, methodType };
};

const executeDiscoveryRequest = () => {
    const route = '/v2/Accounts/discover';
    
    let config = getHttpConfig({ baseUrl: entityMetadataFromCR.baseUrl, route, headers: {}, data: {}, methodType: 'POST' });

    // add Sahamati configuration [Start]
    config = addSahamatiConfiguration({ config, route });
    // add Sahamati configuration [End]

    axios.request(config)
        .then(response => response.data)
        .catch(error => {
            console.error('Error making discovery request:', error.message);
            throw error;
        });
};

const performAnotherOperations = async (accountDiscoverResponse) => {
    console.log('Perform another operations with the response', accountDiscoverResponse);
}

executeDiscoveryRequest()
    .then(performAnotherOperations)
    .then(() => console.log('Account discovery successful.'))
    .catch(() => console.log('Account discovery failed.'))
    .finally(() => console.log('Account discovery completed.'));


// OLD END


// NEW START
  
const generateBase64EncodedJson = (json) => {
    return btoa(JSON.stringify(json));
}

const generateRequestMeta = (recipientId) => {
    const context = { "recipient-id": recipientId }
    return generateBase64EncodedJson(context);
}

const addSahamatiConfiguration = ({ config, route }) => {
    const routerUrl = 'http://api.dev.sahamati.org.in/fip-router';
    config.url = `${routerUrl}${route}`;
    config.headers["x-request-meta"] = generateRequestMeta(entityMetadataFromCR.id);
    return config;
}

// NEW END
```

</details>


# GoLang

<details>

<summary>Without Router - Current Approach</summary>

```go
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {

	urlStr := "https://fip-1.dev.sahamati.org.in/v2/Accounts/discover"

	body := []byte(fmt.Sprintf(`{
        "ver": "2.0.0",
        "timestamp": "%s",
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "customer_identifier@AA_identifier",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": [
            "DEPOSIT"
        ]
    }`, time.Now().UTC().Format(time.RFC3339)))

	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer(body))
	if err != nil {
		fmt.Printf("Error creating request: %v\n", err)
		return
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-jws-signature", "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshW...")
	req.Header.Set("x-simulate-res", "Ok")
	req.Header.Set("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A")

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error executing request: %v\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error reading response body: %v\n", err)
		return
	}

	fmt.Printf("Status: %s\n", resp.Status)
	fmt.Printf("Headers: %v\n", resp.Header)
	fmt.Printf("Response Body: %s\n", string(respBody))

	if resp.StatusCode >= 400 {
		fmt.Printf("Error response received - Status Code: %d\n", resp.StatusCode)
	}
}

```

</details>

<details>

<summary>With Router Integration</summary>

```go
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {

	urlStr := "https://api.dev.sahamati.org.in/router/v2/Accounts/discover"

	body := []byte(fmt.Sprintf(`{
        "ver": "2.0.0",
        "timestamp": "%s",
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "customer_identifier@AA_identifier",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": [
            "DEPOSIT"
        ]
    }`, time.Now().UTC().Format(time.RFC3339)))

	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer(body))
	if err != nil {
		fmt.Printf("Error creating request: %v\n", err)
		return
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-jws-signature", "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshW...")
	req.Header.Set("x-simulate-res", "Ok")
	req.Header.Set("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A")

	// Router changes - start

	recipientId := "FIP-SIMULATOR"
	metaInfo := map[string]string{
		"recipient-id": recipientId,
	}
	metaInfoBytes, err := json.Marshal(metaInfo)
	if err != nil {
		fmt.Printf("Error marshalling meta info to JSON: %v\n", err)
		return
	}
	base64MetaInfo := base64.StdEncoding.EncodeToString(metaInfoBytes)

	req.Header.Set("x-request-meta", base64MetaInfo) 
	
	// Router changes - end

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error executing request: %v\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error reading response body: %v\n", err)
		return
	}

	fmt.Printf("Status: %s\n", resp.Status)
	fmt.Printf("Headers: %v\n", resp.Header)
	fmt.Printf("Response Body: %s\n", string(respBody))

	if resp.StatusCode >= 400 {
		fmt.Printf("Error response received - Status Code: %d\n", resp.StatusCode)
	}
}

```

</details>


# C\#

<details>

<summary>Without Router - Current Approach</summary>

```csharp
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace AAEcosystem
{
    public class AccountDiscoveryClient
    {
        private const string API_URL = "https://fip-1.dev.sahamati.org.in/v2/Accounts/discover";
        private const string JWS_SIGNATURE = "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshWBhWeY-bLBeSmxkU5VpH-lQjBjGFW_2opX3ZK5XfF7oPc3wkp-Qj7-qVfgTg53YvGyS3oLbKvkMRHtKa33x5I-0b8BmlMzojtnA_zFfubOJoqZVPpz7BQ4qrazizaF2Z6m3FygNGuAkdbdqtnCgPCjBZ6ibkpyiKR_n_g5FcTOq7fa7JgE6IoMD0R575ssdFbHzcT-IZs0DDqc_DJ0pR7m56z9IlmRZ6kUg99kaYVl6GUHSYPwY9OCbmHa7EbgE5vUdIJjhF3vJDZhYMWCojpbh9KLGSpbHkWG4OY19S-YNJv85FtXZe0Q";
        private const string BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A";
        private const string FIP_ID = "FIP-SIMULATOR";

        private static readonly string REQUEST_BODY = @"{
            ""ver"": ""2.0.0"",
            ""timestamp"": ""2023-06-26T06:41:54.904+0000"",
            ""txnid"": ""f35761ac-4a18-11e8-96ff-0277a9fbfedc2"",
            ""Customer"": {
                ""id"": ""customer_identifier@AA_identifier"",
                ""Identifiers"": [
                    {
                        ""category"": ""STRONG"",
                        ""type"": ""AADHAAR"",
                        ""value"": ""XXXXXXXXXXXXXXXX""
                    }
                ]
            },
            ""FITypes"": [
                ""DEPOSIT""
            ]
        }";

        public static async Task Main(string[] args)
        {
            try
            {
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);

                var request = new HttpRequestMessage(HttpMethod.Post, API_URL);
                request.Headers.Add("x-jws-signature", JWS_SIGNATURE);
                request.Headers.Add("x-simulate-res", "Ok");

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", BEARER_TOKEN);
                request.Content = new StringContent(REQUEST_BODY, Encoding.UTF8, "application/json");

                var response = await httpClient.SendAsync(request);
                var responseBody = await response.Content.ReadAsStringAsync();

                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.StatusCode}");
                Console.WriteLine($"Response Body: {responseBody}");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Error occurred: {ex.Message}");
                Console.Error.WriteLine(ex.StackTrace);
            }
        }
    }
}

```

</details>

<details>

<summary>With Router Integration</summary>

```csharp
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace AAEcosystem
{
    public class AccountDiscoveryClient
    {
        private const string API_URL = "https://api.dev.sahamati.org.in/router/v2/Accounts/discover";
        private const string JWS_SIGNATURE = "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshWBhWeY-bLBeSmxkU5VpH-lQjBjGFW_2opX3ZK5XfF7oPc3wkp-Qj7-qVfgTg53YvGyS3oLbKvkMRHtKa33x5I-0b8BmlMzojtnA_zFfubOJoqZVPpz7BQ4qrazizaF2Z6m3FygNGuAkdbdqtnCgPCjBZ6ibkpyiKR_n_g5FcTOq7fa7JgE6IoMD0R575ssdFbHzcT-IZs0DDqc_DJ0pR7m56z9IlmRZ6kUg99kaYVl6GUHSYPwY9OCbmHa7EbgE5vUdIJjhF3vJDZhYMWCojpbh9KLGSpbHkWG4OY19S-YNJv85FtXZe0Q";
        private const string BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A";
        private const string FIP_ID = "FIP-SIMULATOR";

        private static readonly string REQUEST_BODY = @"{
            ""ver"": ""2.0.0"",
            ""timestamp"": ""2023-06-26T06:41:54.904+0000"",
            ""txnid"": ""f35761ac-4a18-11e8-96ff-0277a9fbfedc2"",
            ""Customer"": {
                ""id"": ""customer_identifier@AA_identifier"",
                ""Identifiers"": [
                    {
                        ""category"": ""STRONG"",
                        ""type"": ""AADHAAR"",
                        ""value"": ""XXXXXXXXXXXXXXXX""
                    }
                ]
            },
            ""FITypes"": [
                ""DEPOSIT""
            ]
        }";

        public static async Task Main(string[] args)
        {
            try
            {
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);

                var request = new HttpRequestMessage(HttpMethod.Post, API_URL);
                request.Headers.Add("x-jws-signature", JWS_SIGNATURE);
                request.Headers.Add("x-simulate-res", "Ok");

                // Router changes - start
                var metaInfo = new Dictionary<string, string> { { "recipient-id", FIP_ID } };
                string metaInfoStr = JsonSerializer.Serialize(metaInfo);
                string base64MetaInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(metaInfoStr));
                request.Headers.Add("x-request-meta", base64MetaInfo);
                // Router changes - end

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", BEARER_TOKEN);
                request.Content = new StringContent(REQUEST_BODY, Encoding.UTF8, "application/json");

                var response = await httpClient.SendAsync(request);
                var responseBody = await response.Content.ReadAsStringAsync();

                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.StatusCode}");
                Console.WriteLine($"Response Body: {responseBody}");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Error occurred: {ex.Message}");
                Console.Error.WriteLine(ex.StackTrace);
            }
        }
    }
}

```

</details>


# Router APIs Specifications

The Router, currently in the Sandbox environment for the POC, implements all ReBIT API specifications as detailed in [ReBIT API Documentation](https://api.rebit.org.in).

The following pages provide an overview of these API implementations.

* [Financial Information User (FIU) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/fiu-api-specification)
* [Account Aggregator (AA) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/aa-api-specification)
* [Financial Information Provider (FIP) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/fip-api-specification)


# FIU API Specification

{% openapi src="/files/heipCgFMvnZhqwHwZhSd" path="/Consent/Notification" method="post" %}
[FIU-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ZRUmmdEwrRF1xyatcLgz/FIU-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/heipCgFMvnZhqwHwZhSd" path="/FI/Notification" method="post" %}
[FIU-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ZRUmmdEwrRF1xyatcLgz/FIU-v2-latest.yaml)
{% endopenapi %}


# AA API Specification

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/handle" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/fetch" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/request" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/fetch" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Account/link/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Heartbeat" method="get" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}


# FIP API Specification

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/discover" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/link" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/delink" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/link/verify" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/FI/request" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/FI/fetch" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Consent/Notification" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Consent" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Heartbeat" method="get" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}


# ReBIT Workflows using Router

In the Account Aggregator (AA) ecosystem, secure data sharing is facilitated through three key workflows, each governed by standardized ReBIT APIs. The process begins with **User Login to AA for Account Discovery & Linking**, where users provide identifiers such as mobile numbers to identify and connect their financial accounts across multiple institutions; the linking is authorized via a One-Time Password (OTP). Following this, the **Consent Workflow** enables Financial Information Users (FIUs) to obtain explicit user consent for accessing their financial data from various Financial Information Providers (FIPs), ensuring compliance with stringent privacy standards. Finally, once consent is granted, the **Financial Information (FI) Request Workflow** allows FIUs to securely request financial data from FIPs through the AA, ensuring that only authorized data is retrieved and shared, thereby maintaining privacy and data integrity throughout the process.

## [**Account Discovery & Linking**](/no-longer-relevent/buildaathon-2024/network-scenarios/account-discovery-and-linking)

**Account Discovery & Linking** allows users to identify and link their accounts across multiple financial institutions. This process is initiated when a user provides their mobile number or other identification, which the Account Aggregator uses to query Financial Information Providers (FIPs) for linked accounts. Upon identification, the user is prompted to authorize the linking via an OTP (One-Time Password). ReBIT APIs facilitate the communication and data flow between the AA, FIU, and FIP during the discovery and linking phases.

## [**Consent Workflow**](/no-longer-relevent/buildaathon-2024/network-scenarios/consent-workflow)

The **Consent Workflow** is at the core of the Account Aggregator (AA) ecosystem. It governs how a Financial Information User (FIU) obtains explicit consent from the user to access their financial data held by various Financial Information Providers (FIPs). This workflow ensures that data sharing is fully authorized by the user, adhering to stringent data privacy regulations. The consent mechanism follows a standardized flow, involving the FIU, AA, and FIP, where ReBIT APIs are used to securely request, manage, and process user consent.

## [**Financial Information (FI) Request Workflow**](/no-longer-relevent/buildaathon-2024/network-scenarios/fi-request-workflow)

The **FI Request Workflow** outlines how a Financial Information User (FIU) requests data from Financial Information Providers (FIPs) via the Account Aggregator. Once consent is granted, the FIU can initiate a financial information request, and the AA retrieves the required data from the FIP. ReBIT APIs are integral in transmitting these requests securely and ensuring that only authorized data is shared with the FIU.

## Router Integration Changes

The following sections provide a detailed explanation of these above mentioned workflows, including a diagram illustrating API interactions (Reference) within the AA ecosystem. The diagram also highlights changes related to the Router. Review these sections carefully to understand the modifications and the necessary updates to your code.


# Account Discovery & Linking

The Account Discovery & Linking process involves identifying the financial accounts a user holds across various institutions (FIPs) and linking them to the Account Aggregator for easy management and data access.

### **Steps Involved in Account Discovery & Linking:**

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfjISSEpnWOqjy8C0B1W4uVSxf548B1ti73BbudIHK4wleC0JkB-MyEZuBfbs8ZyxiKQ5hNKz-IxVXUhp99kXMQS8j7u8B7IIf46iIR38-eVwkbN5eSYDdLN3A80sk71QJPnDD2DA?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>Account Discovery &#x26; Linking</p></figcaption></figure>

#### **1. User Login and Identity Verification:**

The user logs into the AA application and provides their mobile number or other identity verification details. The AA then queries the FIPs to discover accounts associated with the user.

***API (Internal API Spec):*** ***/user/send-otp (POST)*****:** The user login process after entering the phone number sends an OTP for login.

***API (Internal API Spec):*** ***/user/verify-otp (POST)*****:** The user enters the OTP sent in the previous step to verify and login.

#### **2. Request to FIPs for Account Discovery&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The Account Discovery request is routed to the FIP via the Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

Upon receiving the request, each FIP searches its records for accounts associated with the provided identity (e.g., mobile number or email).

***ReBIT API:*****&#x20;/Accounts/discover (POST) with 'x-request-meta' header**: The FIP returns details about the user's accounts to the AA.

#### **3. User Confirms Accounts to Link:**

Once the AA receives the list of accounts from various FIPs, it presents this information to the user. The user selects the accounts they wish to link with the AA. To authorize the linking, the user receives a One-Time Password (OTP).

***ReBIT API:*****&#x20;/Accounts/link (POST) with 'x-request-meta' header**: The AA sends a request to FIP through Router with request header (`x-request-meta`) to initiate linking of the account with the AA customer account.

***ReBIT API:*****&#x20;/Accounts/link/verify (POST) with 'x-request-meta' header**: The user needs to provide the OTP sent with the previous step to complete the account linking. The AA send the OTP as token to FIP through Router with request header (`x-request-meta`) to verify the account link.

#### **4. Accounts Linked Successfully:**

After successful OTP verification, the user’s selected accounts are linked to the AA. The FIP will send a notification to the AA on successful OTP verification for the account linking. These accounts can now be used for data sharing in future consent workflows.

***ReBIT API:*****&#x20;/Account/link/Notification (POST) with 'x-request-meta' header**: The FIP sends a notification about status of account linking to AA through Router. The AA confirms that the accounts have been successfully linked and communicates this to the user.

### Reference Implementation Guide & Using Simulator

For the above use case implementation, AA need to implement a few internal APIs for hanlding the user registration, login and accounts data along with the ReBIT API Specification.

In this scenario, the AA need to have a mock FIP to support the integration testing with mock response for the API requests to FIP. Please use the "FIP-SIMULATOR" for the integration testing with mock data. Please refer to [Testing with Simulator](/sahamatinet-poc/integration-with-simulators) for more details.


# Consent Workflow

The consent workflow is a fundamental part of the Account Aggregator (AA) ecosystem. It ensures that Financial Information Users (FIUs) can access user data from Financial Information Providers (FIPs) only after obtaining explicit consent from the user. This workflow is governed by a series of secure and standardized interactions using the ReBIT APIs.

### **Steps Involved in Consent Workflow:**

#### Pre-requisites:

The [Account Discovery & Linking](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking) is handled by the user to execute the Consent workflow.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfldUHurAqJFFUH1yDIOAEoxa2n666KTxfbGkOHF3XeDubtIhV0stST_y65hQEC1jYNxSbFRfsn_I-IHBqe9vkFIAHMRNK48ni2m0xjTKTe-ezJAQyys4rr2t1Uo-0KXfizZi7_Dw?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>Consent Workflow</p></figcaption></figure>

#### **1. FIU Initiates Consent Request&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The FIU initiates the process by sending a consent request to the Account Aggregator (AA). The request specifies the type of financial data, the duration, and the purpose for which it is being requested. This consent request is made by the FIU to the AA through Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

***ReBIT API: /Consent (POST)*****&#x20;with 'x-request-meta' header***:* The FIU sends the consent request to the AA using this API through Router. The request includes the data access requirements, purpose, and duration for which access is required.

***API (AA Internal Spec): /Consent/create (POST):*** The AA create the consent artefact and stores for future use with pending status.

#### **2. AA Presents Consent to User:**

After receiving the consent request, the AA communicates with the user via its mobile app or web portal, presenting the consent details. The user reviews and either approves or denies the request.

***API (AA Internal Spec): /Consent/read (GET)**:* The AA retrieves the consent artefact details to present to the user for approval.

#### **3. User Grants Consent:**

If the user approves the consent request, the AA generates a consent artefact. This artefact is a formal document containing all the details of the user’s consent, such as the scope, purpose, and validity.

***API (AA Internal Spec): /Consent/accept (POST)**:* The AA update the status and stores the consent artefact after the user grants approval.

#### **4. AA Shares Consent with FIU & FIP&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once consent is granted, the AA sends the consent artefact to both the FIU and the relevant FIP. The FIP uses this consent artefact to validate requests for financial data.

***ReBIT API: /Consent/Notification (POST)*****&#x20;with 'x-request-meta' header***:* The FIU & FIP is notified about the granted consent via this API. It helps,&#x20;

* FIU to fetch the consent artefact from AA and use it for FI request.
* FIP to validate the future FI data requests from the FIU.

***ReBIT API: /Consent/fetch (POST)*****&#x20;with 'x-request-meta' header***:* The FIU fetches the Consent artefact from AA through Router to use it for future FI data requests.

#### **5. Consent Revocation (Optional):**

The user has the ability to revoke consent at any time, cutting off access to their data.

***API (AA Internal Spec): /Consent/revoke (POST)**:* This API allows the user to revoke previously granted consent.


# FI Request Workflow

The Financial Information (FI) Request Workflow allows a Financial Information User (FIU) to request data from a Financial Information Provider (FIP) via the Account Aggregator (AA), based on user consent.

### **Steps Involved in FI Request Workflow:**

#### Pre-requisites:

The [Account Discovery & Linking](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking), [Consent Workflow](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/consent-workflow) are handled by the user to execute the FI request.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdl6CUYF1NKze5myGSxCUWeaQshiLP3mNgdIDHLcOI9zDHm_mixEBp9G-TB0D2qHuvDYCZMq9QWgJ57OepHr2s4omoQE4FAvBRtVgsIvp9VvIRR95an-9WU2cIde6LLi0ws12Cz?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>FI Request Workflow</p></figcaption></figure>

#### **1. FIU Sends FI Request to AA&#x20;**<mark style="color:green;">**through Router**</mark>**:**

After the user’s consent is obtained, the FIU sends a Financial Information (FI) request to the AA to retrieve the data from the relevant FIPs. This request contains the details of the data required (such as bank account statements, loan details, etc.).

***ReBIT API:*****&#x20;/FI/Request (POST) with 'x-request-meta' header**: The FIU sends the FI request to the AA specifying the type of financial data required and the consent artefact through Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

#### **2. AA Forwards FI Request to FIP&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The AA validates the request against the consent artefact and forwards it to the relevant FIP through Router. The FIP retrieves the requested data from its system.

***ReBIT API:*****&#x20;/FI/Request (POST) with 'x-request-meta' header**: The AA forwards the FI request to the FIP, including the consent artefact and data requirements.

#### **3. FIP Shares the Session Id with AA:**

Upon receiving the request and validating it against the consent artefact, the FIP provides a session Id to use as reference to fetch the data once it is ready.

#### **4. FIP sends a Notification to AA&#x20;**<mark style="color:green;">**through Router**</mark>**:**

FIP asyncronously compose the requested FI data and sends a notification to AA about the readiness to trigger the FI fetch request to get the data.

***ReBIT API:*****&#x20;/FI/Notification (POST) with 'x-request-meta' header**: The FIP sends a notification to AA through Router once the FI data composed and available to fetch.

#### **5. AA Fetches FI data from FIP & Sends a Notification to FIU&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once the AA receives the notification from the FIP, it fetches the financial information from the FIP through Router. This data is provided in the agreed format and scope as per the consent.

Once the FI data is ready, AA sends a notification to FIU about the readiness of FI data to fetch by FIU from AA.

***ReBIT API:*****&#x20;/FI/fetch (POST) with 'x-request-meta' header**: The AA sends a FI fetch request to FIP through Router to receive the FI data for the specific Session Id.

***ReBIT API:*****&#x20;/FI/Notification (POST) with 'x-request-meta' header**: The AA sends a notification to FIU through Router once the FI data available to fetch.

#### **4. AA Delivers Data to FIU&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once the AA receives the data from the FIP, it delivers the financial information to the FIU. This data is provided in the agreed format and scope as per the consent.

***ReBIT API:*****&#x20;/FI/fetch (POST) with 'x-request-meta' header**: The AA delivers the financial information to the FIU through Router based on the initial request.

#### **5. FI Request Completion:**

After the FIU receives the data, the FI request workflow is marked as complete. The FIU can now process the data in line with the consent provided by the user.


# Integration with Simulators

## Overview

SahamatiNet has developed Response **Simulators** for each type of entity in the AA ecosystem. These simulators replicate the behaviour of AA, FIU, or FIP while interacting with ReBIT APIs for Router integration, enabling seamless testing and validation.

By mimicking real Entity Protocol APIs, the **Response Simulator provides a controlled environment where developers can test the router service** independently without relying on a live entity.

The sample workflow diagram below illustrates the usage of the Response Simulator by including a simulated response with the expected response.

<figure><img src="/files/pOueLGo6jwe7Du8gDGz6" alt=""><figcaption><p>Entity Integration with Router using "Response Simulator"</p></figcaption></figure>

The following two details are required in the request to use the APIs with Response **Simulator**:

* **recipient-id:** This is specified in the **x-request-meta** header through which the router that will route the request to the respective response simulator.&#x20;
  * Based on the respective use case you can use the following Entity ID as `recipient-id`, which are mapped to the respective Response Simulators in Sandbox environment,
    * **AA-SIMULATOR**
    * **FIU-SIMULATOR** and
    * **FIP-SIMULATOR**
* **x-simulate-res:** This header should contain a hint for the expected response from the response simulator. It can be any of the options listed in the specific entity tables. If this is not included, the response simulator will default to returning a 200 OK response.

#### Sample Request Headers:

<pre class="language-javascript"><code class="lang-javascript">x-request-meta: [Base64 of {"recipient-id": "AA-SIMULATOR"}]
<strong>x-simulate-res: DataGone
</strong></code></pre>

## OTP Scenario:

The **FIP's Accounts/link/verify** API is the only one that utilizes the OTP received from the customer. This API is responsible for submitting the token/OTP back to the FIP to complete the account linkage process. The Response Simulator is set up to accept a predefined list of OTPs for successful account linkage. If an OTP outside of this list is used, the account linkage will fail. This is the default behavior of the Response Simulator, functioning without the need for the **x-simulate-res** header.

#### List of OTPs accepted by Response Simulator

<table data-header-hidden data-full-width="false"><thead><tr><th width="103"></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>1234</td><td>123456</td><td>654321</td><td>999999</td><td>223344</td><td>567890</td><td>456789</td><td>234567</td><td>345678</td><td>555444</td><td>222333</td></tr></tbody></table>

The sample workflow diagram below illustrates the usage of the valid OTP &#x20;

<figure><img src="/files/OJijhZBfBmI6eJOsMY4B" alt=""><figcaption></figcaption></figure>

The sample workflow diagram below illustrates the usage of the invalid OTP&#x20;

<figure><img src="/files/I53R2CHIyXWYyroDhloH" alt=""><figcaption></figcaption></figure>


# AA Simulator

## AA - Response Simulator:

This AA response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/AA_2_1_0.yaml>

<table><thead><tr><th width="110">API</th><th width="262">Expected Response</th><th>x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>FI/fetch</td><td><p>403 Forbidden</p><p>(DataFetchRequestInProgress)</p></td><td>Forbidden</td></tr><tr><td>FI/fetch</td><td>410 Data Gone</td><td>DataGone</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

Sample FI/fetch workflow using AA-SIMULATOR:

<figure><img src="/files/1V85rd7lKcE1OVAyln3p" alt=""><figcaption></figcaption></figure>

#### Preloaded Scenarios

The AA Response Simulator (AA-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the AA Simulator.

| API Requests               | Scenario Id                             | Details                                  |
| -------------------------- | --------------------------------------- | ---------------------------------------- |
| /Consent                   | ConsentDeposit\_Success                 | Successful consent request               |
| /Consent/handle            | ConsentHandleDeposit\_Approved          | Consent response with status as Approved |
| /Consent/handle            | ConsentHandleDeposit\_Ready             | Consent response with status as Ready    |
| /Consent/handle            | ConsentHandleDeposit\_Rejected          | Consent response with status as Rejected |
| /Consent/handle            | ConsentHandleDeposit\_Expired           | Consent response with status as Expired  |
| /Consent/handle            | ConsentHandleDeposit\_Failed            | Consent response with status as Failed   |
| /Consent/handle            | ConsentHandleDeposit\_Pending           | Consent response with status as Pending  |
| /Consent/fetch             | ConsentFetchDeposit\_Active             | Consent fetch with status as Active      |
| /Consent/fetch             | ConsentFetchDeposit\_Paused             | Consent fetch with status as Paused      |
| /Consent/fetch             | ConsentFetchDeposit\_Revoked            | Consent fetch with status as Revoked     |
| /Consent/fetch             | ConsentFetchDeposit\_Expired            | Consent fetch with status as Expired     |
| /FI/request                | FIRequestDeposit\_Success               | Successful FI request                    |
| /FI/request                | FIRequestDeposit\_Expired               | FI request with expired consent          |
| /FI/fetch                  | FIFetchDeposit\_Success\_1              | Successful FI fetch from Bank 1          |
| /FI/fetch                  | FIFetchDeposit\_Success\_2              | Successful FI fetch from Bank 2          |
| /Consent/Notification      | ConsentNotificationDeposit\_Success     | Successful consent notification          |
| /FI/Notification           | FINotificationDeposit\_Success          | Successful FI notification               |
| /Account/link/Notification | AccountLinkNotificationDeposit\_Success | Successful Account Link notification     |


# FIP Simulator

### FIP Response Simulator:

This FIP response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/FIP_2_1_0.yaml>

<table><thead><tr><th>API</th><th>Expected Response</th><th width="340">x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>FI/fetch</td><td><p>403 Forbidden</p><p>(DataFetchRequestInProgress)</p></td><td>Forbidden</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

#### Preloaded Scenarios

The FIP Response Simulator (FIP-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the FIP Simulator.

| API Requests          | Scenario Id                         | Details                                                                  |
| --------------------- | ----------------------------------- | ------------------------------------------------------------------------ |
| /Accounts/discover    | DiscoveryFlowDeposit\_Success       | Successful account discovery                                             |
| /Accounts/discover    | DiscoveryFlowDeposit\_NotFoundMatch | Not found any accounts                                                   |
| /Accounts/discover    | DiscoveryFlowDeposit\_Multiple      | <p>Successful account discovery with 2 accounts<br>- Bank 1 & Bank 2</p> |
| /Accounts/link        | LinkFlowDeposit\_Success\_1         | Successful account link for Bank 1                                       |
| /Accounts/link        | LinkFlowDeposit\_Success\_2         | Successful account link for Bank 2                                       |
| /Accounts/delink      | DeLinkFlowDeposit\_Success\_1       | Successful account de-link for Bank 1                                    |
| /Accounts/delink      | DeLinkFlowDeposit\_Success\_2       | Successful account de-link for Bank 2                                    |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_Success\_1   | Successful account verification for Bank 1                               |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_Success\_2   | Successful account verification for Bank 1                               |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_InvalidOTP   | Invalid OTP for account verification                                     |
| /Consent              | ConsentDeposit\_Success             | Successful consent response                                              |
| /FI/request           | FIRequestDeposit\_Success           | Successful FI request                                                    |
| /FI/request           | FIRequestDeposit\_Expired           | FI request with expired consent                                          |
| /FI/fetch             | FIFetchDeposit\_Success\_1          | Successful FI fetch from Bank 1                                          |
| /FI/fetch             | FIFetchDeposit\_Success\_2          | Successful FI fetch from Bank 2                                          |
| /Consent/Notification | ConsentNotificationDeposit\_Success | Successful consent notification                                          |


# FIU Simulator

### FIU Response Simulator

This FIU response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/FIU_2_0_0.yaml>

<table><thead><tr><th width="145">API</th><th width="176">Expected Response</th><th width="354">x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

#### Preloaded Scenarios

The FIU Response Simulator (FIU-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the FIU Simulator.

| API Requests          | Scenario Id                         | Details                         |
| --------------------- | ----------------------------------- | ------------------------------- |
| /Consent/Notification | ConsentNotificationDeposit\_Success | Successful consent notification |
| /FI/Notification      | FINotificationDeposit\_Success      | Successful FI notification      |


# Validation of Integration

For the POC integration, there are two key validation steps to be completed:

1. **Validation with Simulators**: The first step involves validating your Application/APIs with the respective simulators based on your Entity Type. If you are an FIU, you will test the integration with the AA Simulator. If you are an AA, you will validate with both the FIU and FIP Simulators. If you are an FIP, you will validate with the AA Simulator. This ensures that all APIs are functioning correctly and the response codes align with the ReBIT Specification Response Codes.
2. **Validation with REs:** The second step occurs once other respective REs (Registered Entities) have onboarded and completed their validation with the simulators. You will then test your integration with these REs to ensure that your application works seamlessly with other participants in the ecosystem.

The Sahamati team will share the list of test cases for API testing based on the ReBIT specification. We will collaborate with you to evolve these test cases throughout the POC, refining and improving them to ensure they comprehensively cover all aspects of the integration and make the process more streamlined and effective.

In both of these validation steps, you are required to share the results with the Sahamati team as evidence to confirm that the integration meets the necessary standards.

More details on these validations will be provided as we progress through the POC.


# SahamatiNet MVP

## SahamatiNet

SahamatiNet is the technological infrastructure developed and maintained by Sahamati to support the Account Aggregator (AA) ecosystem. It comprises a set of specifications, Application Programming Interfaces (APIs), and services aimed at improving the ecosystem's performance, trust, and reliability. By establishing a robust infrastructure, SahamatiNet addresses key challenges such as interoperability, data compliance, data quality, and operational efficiency, thereby ensuring a seamless and trustworthy experience for AA ecosystem entities involved.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Introduction</strong></td><td>SahamatiNet streamlines the AA ecosystem by enabling FIUs, AAs, and FIPs to integrate through a single platform, reducing complexity and improving interoperability.</td><td><a href="/files/D58rJfGathP2qlZ2hM3g">/files/D58rJfGathP2qlZ2hM3g</a></td><td><a href="/pages/4XwzJRST3DaCJAb682un">/pages/4XwzJRST3DaCJAb682un</a></td></tr><tr><td><strong>Applications</strong></td><td>SahamatiNet Applications enable secure, seamless integration in the AA ecosystem through the router, central registry, and identity access management.</td><td><a href="/files/oHQ91KlbtJ5ZiJ9Jp0WD">/files/oHQ91KlbtJ5ZiJ9Jp0WD</a></td><td><a href="/pages/XXnYQrid7QRGZdhvL60X">/pages/XXnYQrid7QRGZdhvL60X</a></td></tr><tr><td><strong>Observability</strong></td><td>It focus on monitoring metrics, logs, and alerts for performance and health. It ensures quick detection of issues, real-time tracking, and visualized data to maintain operational efficiency and transparency.</td><td><a href="/files/dwKocwTqmn2v2q70QsOM">/files/dwKocwTqmn2v2q70QsOM</a></td><td><a href="/pages/A66taPH4paCIxJKP8wQ9">/pages/A66taPH4paCIxJKP8wQ9</a></td></tr><tr><td><strong>API Specification</strong></td><td>The SahamatiNet API Specification for Central Registry (CR), IAM and Router.</td><td><a href="/files/7uIkfMgQRKxhawLAECW2">/files/7uIkfMgQRKxhawLAECW2</a></td><td><a href="/pages/Ivx87BIb1DDfn2aAFskU">/pages/Ivx87BIb1DDfn2aAFskU</a></td></tr><tr><td><strong>Onboarding</strong></td><td>Overview of participation in the SahamatiNet Router PoC within the Sandbox environment as part of the onboarding process.</td><td><a href="/files/apJdmuJOKnTHwU9JZdAQ">/files/apJdmuJOKnTHwU9JZdAQ</a></td><td><a href="/pages/CCdZbrGZsjqAsRhxCqK1">/pages/CCdZbrGZsjqAsRhxCqK1</a></td></tr><tr><td><strong>Integration with SahamatiNet Router</strong></td><td>Provides technical guidance and code-level instructions for integrating your system with the SahamatiNet Router.</td><td><a href="/files/wiWuoM2eBSxV2wemc5TW">/files/wiWuoM2eBSxV2wemc5TW</a></td><td><a href="/pages/K0ikdfmrEU0ycGo1Za8G">/pages/K0ikdfmrEU0ycGo1Za8G</a></td></tr></tbody></table>


# Introduction

### **Current AA Network Mode - Many to Many Integrations**

The integration and interoperability within the AA ecosystem are significantly simplified through the use of SahamatiNet, a unified platform that serves as a central hub for all participants—FIUs (Financial Information Users), AAs (Account Aggregators), and FIPs (Financial Information Providers). Traditionally, these entities would have to establish separate connections and integrations with one another, each facing unique challenges related to data exchange, security, and compliance with standards. However, with SahamatiNet, this complexity is reduced as all participants—FIUs, AAs, and FIPs—now only need to integrate with this single application.

<figure><img src="/files/yhLrCmptsBgkyUv70o00" alt=""><figcaption><p>Existing Integrations in AA ecosystem</p></figcaption></figure>

At present, the integration model within the Account Aggregator (AA) ecosystem involves multiple connections:

* **(FIU x AA)**: Financial Information Users (FIUs) integrate with Account Aggregators (AAs).
* **(AA x FIP)**: Account Aggregators (AAs) also integrate with Financial Information Providers (FIPs).

This results in a complex network of individual, point-to-point connections between participants, which increases the integration effort and maintenance overhead.

## **Interoperability**&#x20;

SahamatiNet serves as a central interface that **significantly enhances interoperability** within the AA ecosystem. It allows all participants—FIUs, AAs, and FIPs—to interact seamlessly by leveraging a unified set of shared protocols and standards defined by ReBIT. By integrating with SahamatiNet Router, each participant can effortlessly connect with and exchange data with other members of the ecosystem, **without needing to establish multiple individual integrations**. This centralised approach reduces complexity and eliminates the need for separate, technical connections, ensuring consistent data handling, security, and **simplified interoperability across all participants**.

The platform standardises communication between all roles, facilitating smoother and more efficient connections. Participants no longer have to navigate through complex and disparate systems to access necessary data or services. Instead, they rely on SahamatiNet Router to manage interactions, significantly simplifying integration efforts. This approach leads to a more streamlined and scalable model for data exchange, security enforcement, and access management, fostering a cohesive ecosystem. By consolidating previously fragmented connections into a single, unified application, SahamatiNet Router makes interoperability faster, more secure, and more efficient for all participants in the AA ecosystem.

<figure><img src="/files/FUay7qE2oTBoJsU9Zrtv" alt=""><figcaption><p>Integrations using SahamatiNet Router for AA ecosystem</p></figcaption></figure>

However, as entities integrate with **SahamatiNet**, this integration model will be streamlined. The number of necessary integrations will be significantly reduced to a simpler structure:

* **(FIU + AA + FIP)**: Financial Information Users (FIUs), Account Aggregators (AAs), and Financial Information Providers (FIPs) will now interact with one central service (SahamatiNet). This centralisation simplifies the communication process, reduces the number of direct integrations, and enhances the overall efficiency of the ecosystem.

## Delegation of Trust&#x20;

The AA ecosystem shifts from a traditional **bilateral-trust** model to a more scalable **network-trust** framework, where trust is centrally managed through SahamatiNet. This framework guarantees interoperability across all participants—FIPs, AAs, and FIUs—by applying consistent security standards and protocols. Instead of each participant individually establishing trust with others, trust is delegated to SahamatiNet, ensuring secure and seamless interactions throughout the ecosystem.

\
To maintain this trust, **FIPs** are required **to subject SahamatiNet** to a rigorous onboarding process before integrating with it, ensuring the platform meets their security and operational standards. Once FIPs are onboarded, **Sahamati** applies the same level of scrutiny when **onboarding AAs.** Similarly, **AAs** apply rigorous checks when onboarding **FIUs,** and once an FIU passes this process, **Sahamati** applies the same level of rigor to onboard the **FIU to SahamatiNet**. This **delegation of trust** streamlines the process, enabling more efficient and reliable interoperability across the entire AA ecosystem.


# Applications

SahamatiNet Applications

## SahamatiNet Router

Interoperability is a core challenge in any data-sharing ecosystem. The Router acts as a bridge to ensure smooth and standardised communication between various ecosystem members using ReBIT APIs. When a request is made by one member to another (such as an FIU requesting data from an FIP), the Router  ensures that the API requests and responses are correctly routed and formatted. This service is crucial for ensuring that no matter what system or infrastructure a member uses, the interaction remains standardised and interoperable across the network.

**Key Features:**

* Facilitates interoperability between ecosystem members.
* Routes and standardises API requests and responses.
* Simplifies cross-ecosystem communication by eliminating compatibility issues.

### Current API reference <a href="#current-api-reference" id="current-api-reference"></a>

The following diagram shows the current flow between FIU and AA flow for Consent API. With the current structure, the API requests are sent to the respective recipient member directly. This requires each member to understand the metadata of the recipient member and use their base path while sending.

<figure><img src="/files/6WFmDNU54NNnVhaiUUzH" alt=""><figcaption><p>Existing approach to use the APIs by AA Ecosystem in case of Consent API between FIU and AA</p></figcaption></figure>

### Using Sahamati Router APIs <a href="#using-sahamati-proxy-apis" id="using-sahamati-proxy-apis"></a>

Sahamati Router simplifies the process for members to send requests to any recipient by simply including the recipient identifier (**x-recipient-id**) in the header, under **x-request-meta**. The Router will then redirect the request to the corresponding recipient. This update must be implemented across all ReBIT APIs in the respective regulated entity's application.

<figure><img src="/files/JIKOOc3nLAWpEjCgGfzc" alt=""><figcaption><p>Using Sahamati Router APIs for AA Ecosystem for Consent API between FIU and AA</p></figcaption></figure>

Currently, the Router is fully implemented with all APIs compliant with ReBIT specifications v2.x.

## Central Registry (CR)

The Central Registry is a core service in the AA ecosystem, provided by Sahamati, which serves as a directory for all participants—Account Aggregators (AAs), Financial Information Providers (FIPs), and Financial Information Users (FIUs). It provides essential information about each participant, including their public IP addresses and public keys, enabling secure and interoperable communication within the ecosystem.

The Central Registry offers an API that allows participants to access details of other members, subject to role-based access restrictions. These roles are defined through identity tokens issued by Sahamati, ensuring that each participant can only access relevant information. For instance, AAs can fetch details of FIPs and FIUs, while FIPs and FIUs can retrieve information about AAs.

Additionally, the Central Registry is closely integrated with the Token Issuance service, which provides each participant with a short-lived JSON Web Token (JWT) for secure API calls across the ecosystem. This JWT is used to authenticate each participant and must be refreshed every 24 hours.

The Central Registry ensures seamless interaction within the AA ecosystem by making vital participant information easily accessible and securely managed.

## Identity Access Management (Token Service)

The Identity and Access Management (IAM) system within the AA ecosystem is responsible for ensuring secure and authorized access to ecosystem APIs. It manages participant roles, such as AA, FIP, or FIU, which are assigned during registration and embedded in the identity tokens issued by Sahamati. These roles govern access to services and ensure that participants can only access information they are authorized for.

To facilitate secure interactions, IAM utilizes Access Tokens—short-lived JSON Web Tokens (JWT)—to authorise participants when they access ecosystem APIs. The Access Tokens, linked to the participant's role, ensure that only authorised individuals or entities can retrieve specific data or interact with services. Through role-based access control and token-based authentication, IAM safeguards the ecosystem's integrity and protects sensitive data while enabling secure communication among participants.


# Observability

SahamatiNet Router serves as an additional layer on top of the AA network, offering extra services and policies. By integrating with the Sahamati Router, FIUs, FIPs, and AAs can seamlessly connect with all other entities within the Router. This eliminates the need for multiple integration points, significantly reducing the integration and operational efforts for members

**Comprehensive Technology Infrastructure – SahamatiNet**&#x20;

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc7KiX9_kkwnLYvbtjjGXAM3mrrcDl_7-Rt-Bx5vTtpkapn50xLgWBbac-iM-Ad7ws8f06PQf9LKIIYVyrhz7Fj-NnVLICwFd6kyEVZwUG44L2Y7P4oRj-mCUqQtJ5yOwPR5-fZBw?key=IIQ76WiEq3n0M56Feh3IbF87" alt=""><figcaption></figcaption></figure>

**SahamatiNet - Services on Observability**

**MIS** :&#x20;

Daily reports on Discovery, Linking, Consent, and data fetch, generated from the Router’s meta data. Will be more accurate that currently available due to varying cadences, formats, incorrect data and naming conventions.

**Network Health :**&#x20;

Complete picture of health of FIP and AA applications derived from a single source of truth. Avoids overlapped calls from AAs to the FIPs and ecosystem health reporting is not dependent on vagaries of reporting.

**SLA Reporting :**&#x20;

* Report on SLA Adherence for each scenario’s success case, error rate for AAs and FIPs.
* Need to define and agree SLAs for each ecosystem participants and report on adherence and Report on non-adherence to SLA commitments

**NOC Support :**&#x20;

* Sahamati NOC Support using Network Health metrics and SLA Adherence
* Facilitates proactive action to correct ‘sick’ nodes
* Grievance Redressal

**Technical Audit :**

* API Telemetry&#x20;
* Tracking of changes in Ecosystem such as onboarding of REs, ad

**Billing and Recon :**

Generate data fetch statements to support downstream billing & any reconciliation efforts amongst participants bilaterally<br>


# Integration Steps

For the SahamatiNet Minimum viable product (MVP)

## SahamatiNet MVP Onboarding Checklist

1. **Register as a Ecosystem Member for MVP**&#x20;
   1. Identify the key fields needed for registration.
      1. Choose your **member type**: Account Aggregator (AA), Financial Information Provider (FIP), or Financial Information User (FIU).
      2. Provide the following organisation details for the Central Registry (CR):
         * Entity ID (unique identifier)
         * Base URL for your service
         * RSA Public Key for secure communication
         * IP Address, Inbound and Outbound Ports (for production; optional for UAT and Sandbox)
      3. **Designate a user** (preferably with a service email account) to manage the entity as an admin in CR and IAM.
   2. Complete the [Google Form for Registration](https://forms.gle/JKPSivKt36P4iH3a7) to onboard with the Central Registry (CR).&#x20;
2. **Verify and Set Up User and Entity Access Tokens**&#x20;
   1. The designated user will **receive an email with a password reset link**.
   2. **Reset the password** and complete the account setup.
   3. **Generate the User Access Token** using the user’s email and new password.
   4. Use the User Access Token to **read the entity’s secret** from the Sahamati IAM API.
      1. If needed, **reset the secret** using the designated API.
   5. Use the entity secret to **generate the Entity Access Token** for ReBIT APIs.
   6. Refer to the section on these APIs [here](/sahamatinet-poc/integration-steps/iam-apis)&#x20;
3. **Integrate with SahamatiNet Router in Sandbox**
   1. Understand the **required changes for integration with the Router.**
      1. Sahamati Router simplifies the process by allowing members to send requests to any recipient by adding the recipient identifier (**recipient-id**) in the header under **x-request-meta.** Refer [here](/sahamatinet-poc/integration-steps/integration-with-router) for more details.
   2. **Changes of additional step of onboarding in your application**
      1. With the transition to integrating with the SahamatiNet Router, the onboarding process for FIUs (Financial Information Users), AAs (Account Aggregators), and FIPs (Financial Information Providers) is no longer necessary. Previously, this step was essential for establishing peer-to-peer trust and enabling communication within the AA ecosystem. However, with Router integration, trust is managed through technical means, eliminating the need for additional onboarding on your side. &#x20;
      2. As an AA Ecosystem participant, **you can bypass the manual onboarding for FIUs, AAs, and FIPs in your application**. These participants would undergo the required compliance through SahamatiNet before interacting with other entities via the Router. **This change streamlines the integration process, removing the need for extra code or configuration**, and improving the efficiency and ease of connections across the AA ecosystem.&#x20;
      3. Note that while the technical integrations are now handled through the Router, the necessary commercial agreements between AA ecosystem participants remain unchanged and will continue as they are.
   3. **Review ReBIT workflows relevant to your entity** **using the Router**.&#x20;
      1. [Account Discovery and Linking workflows](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking)
      2. [Consent workflows ](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/consent-workflow)
      3. [FI Request workflows](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/fi-request-workflow)
4. **Integration with Simulators** &#x20;
   1. Test and validate the Router's functionality with ReBIT workflows tailored to your entity type by using the integration simulators in the sandbox environment (FIU, AA, FIP). You can also test this with your own simulators, if you have them. Please be sure to include the simulator details in the Google form provided above. We will onboard it for validation in the Sandbox environment as part of the POC.
   2. Refer to the section on how to use SahamatiNet simulators [here](https://app.gitbook.com/o/CcobtOsQAdIoa87kTGdF/s/fY7u471KMiCJqdTaYVzZ/~/changes/100/sahamatinet-poc/sahamatinet/testing-with-simulators) and respective simulators links below&#x20;
      1. [AA Simulator](/sahamatinet-poc/integration-with-simulators/aa-simulator)
      2. [FIP Simulator](/sahamatinet-poc/integration-with-simulators/fip-simulator)
      3. [FIU Simulator](/sahamatinet-poc/integration-with-simulators/fiu-simulator)
5. **Validate Integration with Simulators and Regulated Entities**&#x20;
   1. Conduct tests with other onboarded entities in the sandbox environment to review all integration points and ensure seamless operation.
   2. More details on this step will be provided as we progress through the POC.

By following these steps, you will successfully onboard and integrate with SahamatiNet in the sandbox environment, ensuring compliance with ReBIT specifications and the AA ecosystem standards


# Sandbox Onboarding

## Sandbox Onboarding

To participate in the SahamatiNet Router in the Sandbox, an entity (AA, FIP, or FIU) must ensure its API implementation is ReBIT standards-compliant. This ensures that the entity's APIs meet the necessary interoperability standards for the AA ecosystem and can be tested via the SahamatiNet Router.

The onboarding process involves submitting the **Entity (member) information** such as

<table><thead><tr><th width="262">Property Name</th><th>Description</th></tr></thead><tbody><tr><td>ID (Entity ID)</td><td><p>Unique identifier for your organisation used as Entity ID in Central Registry. </p><p></p><p><a href="/pages/AVQmKqc4gZ5a2f2rNpe1">Learn how to choose an Entity ID</a></p></td></tr><tr><td>Name</td><td>Name of the entity</td></tr><tr><td>Type</td><td>Entity Type - one of FIU, FIP, AA (<strong>Member Type</strong>)</td></tr><tr><td>Base URL</td><td><p>Base URL ( Endpoint ) of your respective application to access the APIs and send requests. </p><p><br><strong>(Only v2 API endpoint are supported in Sandbox environment)</strong></p></td></tr><tr><td>Certificate</td><td><p>The <strong>RSA public key</strong> of the entity for secure communication. It will be used by the members to validate the signature </p><p>(<code>x-jws-signature</code>) of the API request.</p><p></p><p><a href="/pages/p1ZHuH5NA0jRxmXazs4U">Learn how to create this certificate</a>.</p></td></tr><tr><td>ips</td><td>The IP address(es) of the entity to whitelist to access of Sahamati Network services (Ex: Router).</td></tr><tr><td>inboundports</td><td>The port of the member that the Sahamati services can connect to.</td></tr><tr><td>outboundports</td><td>The port of the member that the Sahamati services can expect to receive requests from.</td></tr><tr><td>entityhandle</td><td>Relevant and required only for AAs.</td></tr></tbody></table>

For Ecosystem **Member Type:**  Specify whether you represent an AA, FIP or FIU.&#x20;

* **Account Aggregators (AA) :** Entities that facilitate the secure sharing of user financial data between financial information providers (FIPs) and financial information ussers (FIUs)
* **Financial Information Providers (FIP) :** Entities that hold user financial data, such as banks, NBFC, etc.&#x20;
* **Financial Information Users (FIU):** Entities that seek user financial data to provide value-added services like loans, wealth management, and more.&#x20;

For **IP Address, Inbound and Outbound Ports:** Network details for connecting with the AA ecosystem are required for Production, optional for UAT and Sandbox.

**The Designated User of the entity information such as**

<table><thead><tr><th width="266">Property Name</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Name of the user from entity who will manage client secret </td></tr><tr><td>Email</td><td>Email address of the user - preferably service account email </td></tr><tr><td>Mobile [Optional]</td><td>Mobile number of the user</td></tr></tbody></table>

{% hint style="success" %}
The member (entity) will be onboarded along with **a user with admin role** for managing the profile, secret rotation of entity etc,.
{% endhint %}

{% hint style="info" %}
Once the member entry is added to CR, they can whitelist Sahamati Router IP.
{% endhint %}

**Designated User:** Contact details of the representative responsible for generating and managing the client secret in IAM (Token Service). It is recommended to use a service account email for the long-term management and consistency.&#x20;

Ecosystem Member should provide the above details in the [Google Form](https://forms.gle/puL3DnurVQg28iSw5). Sahamati team will validate the details and onboard the entity as the member to the Sahamati's Central Registry (CR) and IAM (Token Service).&#x20;

If you're experiencing difficulties accessing the Google form from your organization's network, you can alternatively generate the following JSON request and email it as an attachment to **<sandbox@sahamati.org.in>**. Please use the subject line: **Onboarding to SahamatiNet Router MVP**: and make sure to include the designated user's email ID and full name for each entry.

```json
{
    "type": "<Entity Type - one of FIU, FIP, AA>",
    "requester": {
        "name": "<Your Organisations Full Legal Name>",
        "id": "<Entity ID.. YourOrgsUniqueShortName_Environment_EntityType>"
    },
    "entityinfo": {
        "name": "<Your Organisations Full Legal Name>",
        "id": "<Entity ID.. YourOrgsUniqueShortName_Environment_EntityType>",
        "code": "<Same as above>",
        "entityhandle": "<Your Organisations AA Handle, Only relevant for AA entity type>",
        "Identifiers": [
            {
                "category": "STRONG",
                "type": "MOBILE"
            }
        ],
        "baseurl": "<Base URL of the entity to access ReBIT APIs. Only v2 is supported.>",
        "fitypes": [
            "<Supported FI Types>"
        ],
        "certificate": {
            "<Certificate data>"
        },
        "inboundports": [
            "<in bound ports>"
        ],
        "outboundports": [
            "<out bound ports>"
        ],
        "ips": [
            "<Whitelist IP addresses>"
        ]
    }
}

```


# IAM APIs

Identity and Access Management ( Token Service) APIs

Each member of the Sahamati Network will be onboarded with a designated user who holds an admin role to manage the entity’s profile and secret.

* During the onboarding process, the designated user will receive an email containing a verification link. After email verification, **the user will be prompted to set a password**, completing the account activation process.
* Once the password is set, **the user can generate the User Access Token** by providing their email and the new password. This token is used for authenticating the entity’s secrets.
* The designated user can then use the User Access Token to **access the entity’s secret** and, if necessary, **reset the secret**.
* Finally, the entity secret is used to **generate the Entity Access Token**, which is needed for interactions with the ReBIT APIs within the AA network.

### Entity Token Generation use case&#x20;

The Regulated Entities (REs) should generate the Access Token using the Token API from Sahamati for accessing and authentication of any APIs in the AA ecosystem including Sahamati APIs.

Here is the sequence diagram for the Token Generation Process.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdc4HeMCiC89Fdmj_Xf0Nv3AZZKB6BuqMxBUGRt41o73HkYfBchfZOQ9S_a5dg6nK32KXqo44LBDV1AhjU_IyorOrAk0PFyphQuHLr0k3ilJwrjo2xbHH6XFFhwJB0hZWZuW62-0Q?key=3aTz-3SKYP0rOCX7DFnLglx6" alt=""><figcaption><p>Token Generation use case diagram</p></figcaption></figure>

Below are the Base URL of each environment to use IAM APIs.

<table><thead><tr><th width="213.489501953125">Environment</th><th>Base URL</th></tr></thead><tbody><tr><td>Production</td><td>https://api.sahamati.org.in/iam</td></tr><tr><td>UAT</td><td>https://api.uat.sahamati.org.in/iam</td></tr><tr><td>Sandbox (Used for MVP)</td><td>https://api.sandbox.sahamati.org.in/iam</td></tr></tbody></table>

Please note that the following documentation displays the Base URLs from the Sandbox environment. Ensure you use the appropriate Base URLs depending on the environment you are working in.

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/user/token/generate" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/secret/read" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/secret/reset" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

{% openapi src="/files/gjX2IrAF9w69AKVACfQE" path="/entity/token/generate" method="post" %}
[IAM-Service-Sprint-9.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/zYPSph83Hfc1EyFzkrQt/IAM-Service-Sprint-9.yaml)
{% endopenapi %}

## Token Generation APIs:

#### API Postman Collection:&#x20;

{% hint style="info" %}
We recommend you to use below postman collection to try out our Token-Service\[IAM] APIs
{% endhint %}

{% file src="/files/LrPZkvetWRM9Un9XGz41" %}

Below is the Sandbox Environment file for SahamatiNet Services

{% file src="/files/f7BJgqo2Kd0SC0Ix9y74" %}

## Member Secret Management APIs

#### API Collection:

{% file src="/files/nymDUvFE3Ay3pAtIgcs4" %}
Token-Service\[IAM] - API Collection
{% endfile %}


# CR APIs

Central Registry APIs

### Fetching Regulated Entities REs metadata using Central Registry (CR)

A RE should fetch the metadata of the other REs to interact with them through ReBIT APIs to handle the AA ecosystem functionalities. Sahamati provided the CR APIs to access the REs metadata. Here is the sequence diagram for Fetching REs metadata.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcTkKNOEJjQLqrQKi9iJSP8KjDbaa3nfnmSw_IcuBi2yhIjW7cLQKPBlv1k2r8UCmWGT21YNh7mnry6pxFUNKr4hGgwUTn-KjXvmrTcfC3EZkn5YEUV97NYyCZbw_-qmkJBGQsQMQ?key=3aTz-3SKYP0rOCX7DFnLglx6" alt=""><figcaption><p>Fetch REs Metadata using Central Registry</p></figcaption></figure>

{% openapi src="/files/jW0T1thS78gNa6XYDnMn" path="/v2/entityInfo/{type}" method="get" %}
[CR-Service-API-v1.0.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ULRrUF0meRjhWs0vS0Tx/CR-Service-API-v1.0.yaml)
{% endopenapi %}

{% openapi src="/files/jW0T1thS78gNa6XYDnMn" path="/v2/entityInfo/{type}/{id}" method="get" %}
[CR-Service-API-v1.0.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ULRrUF0meRjhWs0vS0Tx/CR-Service-API-v1.0.yaml)
{% endopenapi %}

#### API Collection:

{% file src="/files/6JfkK74IpWh1PQYJfoXX" %}
Central Registry - API Collection
{% endfile %}


# Integration with Router

## Implementing Code Changes for Router Integration

Outlined below are the changes that members need to make to their implementation to use the SahamatiNet Router.

* Use the following **Sahamati Router API endpoint** as base path for all the requests.

```url
https://api.sandbox.sahamati.org.in/router/v2
```

* Do note the Router API endpoint URL mentioned above is used for Sandbox, the respective URL for each environment (UAT and Production) will be updated when we progress to next environments.&#x20;
* Add the recipient ID under the new header **x-request-meta** with **recipient-id** in a JSON object which is the identifier of the receiver to whom the API call needs to be forwarded.
  * The value of the **x-request-meta** is Base64 string of the JSON object with recipient-id.
  * This structure helps us to easily extend the JSON object by adding the required attributes for future use cases.

{% hint style="success" %}

```
x-request-meta: <Base64 of JSON object 
{"recipient-id":"<entityID of the recipient>"}>
```

{% endhint %}

Beyond routing, certain attributes are also captured in the `x-request-meta`  headers to enable observability across the AA ecosystem. These headers can be generated by making an API call to the **Router Integration Helper (RIH)**, which returns the required values. More details are provided in the [Observability through Router section.](/sahamatinet-mvp/integration-steps/integration-with-router/observability-through-router)

Beyond routing, certain attributes are also captured in&#x20;

The receiver could be any of the participant, FIU, AA or FIP.&#x20;

<table><thead><tr><th width="109.80975341796875">Particulars</th><th width="284.70166015625">Comments</th><th>Values</th></tr></thead><tbody><tr><td>Host</td><td>The base path to use by the members of SahamatiNet Router.</td><td><a href="https://api.sandbox.sahamati.org.in/router">​</a><a href="https://api.sandbox.sahamati.org.in/router">https://api.sandbox.sahamati.org.in/router</a></td></tr><tr><td>Headers</td><td>This will remain same as previous.</td><td><p>​</p><ul><li>x-jws-signature - Authorization</li><li>Token (from sender)</li></ul></td></tr><tr><td>Additional Headers</td><td>The recipient id is a required property. It is the identifier of the receiver to whom the API call needs to be forwarded.</td><td>x-request-meta</td></tr></tbody></table>

These header changes need to be implemented for communication between FIU and AA, AA and FIP, FIP and AA, as well as FIU and AA.

## Service URLs for the Sandbox

Service Name and their URLS&#x20;

**Public Key**

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/auth/realms/sahamati/protocol/openid-connect/certs
```

{% endcode %}

**IAM (Token Service)** &#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/iam
```

{% endcode %}

**Central Registry (CR)**&#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/cr
```

{% endcode %}

**Router** &#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/router
```

{% endcode %}

**Router Integration Helper**&#x20;

{% code overflow="wrap" fullWidth="true" %}

```url
https://api.sandbox.sahamati.org.in/router-helper
```

{% endcode %}

Please ensure that, in addition to the changes in the ReBIT API calls, the **entity key validation** for the **public key** is also **pointing to the Sandbox** for your code changes for POC. These URLs will vary across different environments. You can find the Base URLs for these in the [FAQ section](/frequently-asked-questions#base-urls-for-each-environment).

**API Collection:**

{% file src="/files/xSJMC0lSa45pPMxbIdY3" %}


# Sample Code Snippets

These snippets details about the changes that members need to make to their implementation to use the SahamatiNet Router in different languages.

The code snippets have been created using the **Accounts-Discover Scenario** as a reference. The table below provides details of the available implementation samples across different languages along with their respective links.

#### Code Snippet By Programming Language

* [Python](/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/python)
* [Java](/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/java)
* [JavaScript](/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/javascript)
* [GoLang](/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/golang)
* [C#](/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/c)


# Python

***

<details>

<summary>Without Router - Current Approach</summary>

```python
# Assuming this as previous logic without Router
import requests

entity_metadata_from_cr = {
    "baseUrl": "http://fip-1.dev.sahamati.org.in/fip-simulate",
    "id": "FIP-SIMULATOR"
}

def get_http_config(base_url, route, headers, data, method_type):
    return {
        "url": f"{base_url}{route}",
        "headers": headers,
        "data": data,
        "method": method_type
    }

def execute_discovery_request():
    route = "/v2/Accounts/discover"
    
    config = get_http_config(
        base_url=entity_metadata_from_cr["baseUrl"],
        route=route,
        headers={},
        data={},
        method_type="POST"
    )
    
    try:
        response = requests.request(**config)
        return response.json()
    except Exception as error:
        print(f"Error making discovery request: {str(error)}")
        raise
def perform_another_operations(account_discover_response):
    print("Perform another operations with the response", account_discover_response)

if __name__ == "__main__":
    try:
        response = execute_discovery_request()
        perform_another_operations(response)
        print("Account discovery successful.")
    except Exception:
        print("Account discovery failed.")
    finally:
        print("Account discovery completed.")

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```python
import requests
import json
from datetime import datetime
from typing import Dict, Any

# ==============================
#  Config Metadata
# ==============================
ENTITY_METADATA_FROM_CR = {
    "baseUrl": "http://fip-1.sandbox.sahamati.org.in/fip-simulate",
    "id": "FIP-SIMULATOR"
}
ROUTER_INTEGRATION_HELPER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/request/header"


# ==============================
#  Core Functions
# ==============================
def build_discovery_request_body() -> Dict[str, Any]:
    """Creates the ReBIT-defined account discovery request body."""
    return {
        "ver": "2.0.0",
        "timestamp": datetime.utcnow().isoformat(),
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "9766334467@aa_simulator",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": ["DEPOSIT"]
    }


def get_http_config(base_url: str, route: str, headers: Dict[str, str], data: Dict[str, Any], method_type: str) -> Dict[str, Any]:
    """Builds base HTTP config."""
    return {
        "url": f"{base_url}{route}",
        "headers": headers,
        "json": data,
        "method": method_type
    }


def router_integration_helper(route: str, rebit_request_body: Dict[str, Any]) -> Dict[str, Any]:
    """Calls Router Integration Helper service to get host and x-request-meta."""
    payload = {
        "rebitAPIEndpoint": route,
        "recipientId": ENTITY_METADATA_FROM_CR["id"],
        "customerId": "96203773344@aa_simulator",
        "requestBody": rebit_request_body
    }

    response = requests.post(
        ROUTER_INTEGRATION_HELPER_URL,
        json=payload,
        headers={"Content-Type": "application/json"},
        timeout=30
    )
    response.raise_for_status()
    return response.json()


def add_sahamati_configuration(config: Dict[str, Any], route: str, rebit_request_body: Dict[str, Any]) -> Dict[str, Any]:
    """Updates config with router URL and adds x-request-meta header by calling Router Helper API."""
    header_response = router_integration_helper(route, rebit_request_body)

    baseurl = header_response.get("baseurl")
    if not baseurl:
        raise RuntimeError("Router Helper response missing required field 'baseurl'")

    # Update URL
    config["url"] = f"{baseurl}{route}"
    config.setdefault("headers", {})

    # Add x-request-meta header only if it exists
    x_request_meta = header_response.get("x-request-meta")
    if x_request_meta:
        config["headers"]["x-request-meta"] = x_request_meta

    return config


def execute_discovery_request() -> Dict[str, Any]:
    """Executes account discovery request via Sahamati Router (helper API flow)."""
    route = "/Accounts/discover"
    rebit_request_body = build_discovery_request_body()

    # Step 1: Base config
    config = get_http_config(
        base_url=ENTITY_METADATA_FROM_CR["baseUrl"],
        route=route,
        headers={},
        data=rebit_request_body,
        method_type="POST"
    )

    # Step 2: Add Router configuration (call helper API)
    config = add_sahamati_configuration(config, route, rebit_request_body)

    # Step 3: Execute request
    response = requests.request(**config, timeout=30)
    response.raise_for_status()
    return response.json()


def perform_another_operations(account_discover_response: Dict[str, Any]) -> None:
    """Placeholder for next steps."""
    print("Next steps with response:")
    print(json.dumps(account_discover_response, indent=2))


# ==============================
#  Main Runner
# ==============================
if __name__ == "__main__":
    try:
        response = execute_discovery_request()
        perform_another_operations(response)
        print("Account discovery successful.")
    except Exception as e:
        print(f"Account discovery failed. Reason: {e}")
    finally:
        print("Account discovery completed.")


```

</details>

<details>

<summary>With Router Integration - Response</summary>

```python
import json
import requests
from flask import Flask, request, jsonify, make_response

app = Flask(__name__)

ROUTER_RESPONSE_HEADER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/response/header"
RECIPIENT_ID = "AA-SIMULATOR"


def fetch_account_from_request_body(request_body):
    if not request_body:
        return None
    customer = request_body.get("Customer")
    if not isinstance(customer, dict):
        return None
    identifiers = customer.get("Identifiers")
    if not isinstance(identifiers, list):
        return None
    for id_obj in identifiers:
        if not isinstance(id_obj, dict):
            continue
        category = id_obj.get("category", "")
        id_type = id_obj.get("type", "")
        value = id_obj.get("value", "")
        if category == "STRONG" and id_type == "AADHAAR" and value:
            return {
                "FIType": "DEPOSIT",
                "accType": "SAVINGS",
                "accRefNumber": "BANK11111111",
                "maskedAccNumber": "XXXXXXX3468"
            }
    return None


def routerIntegrationHelper(request_body):
    headers = {"Content-Type": "application/json"}
    resp = requests.post(ROUTER_RESPONSE_HEADER_URL, headers=headers, data=json.dumps(request_body), timeout=30)
    resp.raise_for_status()
    return resp.json()


@app.route("/accounts/discover", methods=["POST"])
def handle_account_discovery():
    incoming_request_body = request.get_json(force=True)
    discovered_account = fetch_account_from_request_body(incoming_request_body)
    if not discovered_account:
        return make_response(jsonify({"error": "Account not found"}), 404)

    response_body = {
        "ver": "2.0.0",
        "timestamp": now().isoformat(),
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedcs",
        "DiscoveredAccounts": [discovered_account]
    }

    response_header_request_body = {
        "rebitAPIEndpoint": "/accounts/discover",
        # Optionally extract customerId from incoming_request_body if available
        "customerId": "9977336577@aa_simulator",
        "recipientId": RECIPIENT_ID,
        "additionalAttributes": {},
        "responseBody": response_body
    }

    response_header_resp = routerIntegrationHelper(response_header_request_body)
    x_response_meta = response_header_resp.get("x-response-meta")

    response = make_response(jsonify(response_body))
    if x_response_meta:
        response.headers["x-response-meta"] = x_response_meta
    return response


if __name__ == "__main__":
    app.run(debug=True)


```

</details>


# Java

<details>

<summary>Without Router - Current Approach</summary>

```java
// Assuming this as previous logic without Router
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;

public class EntityRequest {
    private static final String BASE_URL = "http://fip-1.dev.sahamati.org.in/fip-simulate";
    private static final String RECIPIENT_ID = "FIP-SIMULATOR";

    public static void main(String[] args) {
        try {
            String response = executeDiscoveryRequest();
            performAnotherOperations(response);
            System.out.println("Account discovery successful.");
        } catch (Exception e) {
            System.out.println("Account discovery failed. Error: " + e.getMessage());
        } finally {
            System.out.println("Account discovery completed.");
        }
    }

    private static String executeDiscoveryRequest() throws Exception {
        String route = "/v2/Accounts/discover";
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = getHttpConfig(BASE_URL, route, new HashMap<>(), new HashMap<>(), "POST");
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }

    private static HttpRequest getHttpConfig(String baseUrl, String route, Map<String, String> headers, Map<String, Object> data, String methodType) {
        String url = baseUrl + route;
        String jsonData = mapToJson(data);
        
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .POST(HttpRequest.BodyPublishers.ofString(jsonData))
                .header("Content-Type", "application/json");
        
        headers.forEach(builder::header);
        return builder.build();
    }

    private static void performAnotherOperations(String accountDiscoverResponse) {
        System.out.println("Perform another operations with the response: " + accountDiscoverResponse);
    }

    private static String mapToJson(Map<String, ?> data) {
        StringBuilder jsonData = new StringBuilder("{");
        for (Map.Entry<String, ?> entry : data.entrySet()) {
            jsonData.append("\"").append(entry.getKey()).append("\": \"").append(entry.getValue()).append("\",");
        }
        if (!data.isEmpty()) {
            jsonData.deleteCharAt(jsonData.length() - 1);  
        }
        jsonData.append("}");
        return jsonData.toString();
    }
}

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Example flow for calling Sahamati Router with account discovery.
 * - Step 1: Build initial request.
 * - Step 2: Enrich it with adding headers.
 * - Step 3: Send the request.
 */
public class EntityRequest {
    private static final String BASE_URL = "http://fip-1.sandbox.sahamati.org.in/fip-simulate";
    private static final String RECIPIENT_ID = "FIP-SIMULATOR";
    private static final String ROUTER_INTEGRATION_HELPER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/request/header";

    private static final HttpClient client = HttpClient.newHttpClient();
    private static final ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {
        try {
            // Execute account discovery
            String response = executeDiscoveryRequest();
            System.out.println("Account discovery successful: " + response);

            // Do something with response
            performAnotherOperations(response);

        } catch (Exception e) {
            System.out.println("Account discovery failed. Error: " + e.getMessage());
        }
    }

    /**
     * Runs account discovery by calling BASE_URL + /Accounts/discover
     */
    private static String executeDiscoveryRequest() throws Exception {
        String route = "/Accounts/discover";
        String url = BASE_URL + route;
        rebitRequestBody = {} // Rebit Defined request body
        // Initial request
        HttpRequest request = buildHttpRequest(url, new HashMap<>(), rebitRequestBody);

        // New code starts here
        request = addSahamatiConfiguration(request, route, new HashMap<>());
        // New code ends here

        // Execute the request
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }

    /**
     * Builds a basic POST request with headers + JSON data.
     */
    private static HttpRequest buildHttpRequest(String url, Map<String, String> headers, Map<String, Object> data) throws Exception {
        String jsonData = mapper.writeValueAsString(data);

        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonData));

        headers.forEach(builder::header);
        return builder.build();
    }

    private static void performAnotherOperations(String accountDiscoverResponse) {
        System.out.println("Next steps with response: " + accountDiscoverResponse);
    }

    /**
     * Adds Sahamati Router headers by calling the Router Integration Helper API.
     * - Fetches baseurl + x-request-meta from helper service.
     * - Rebuilds request with updated URL and headers.
     */
    private static HttpRequest addSahamatiConfiguration(HttpRequest request, String route, Map<String, Object> rebitRequestBody) {
        try {
            // Call Router Integration Helper to get x-request-meta + baseurl
            Map<String, Object> headerResponse = routerIntegrationHelper(route, rebitRequestBody);

            String baseurl = (String) headerResponse.getOrDefault("baseurl", ""); // Get the baseurl URL (router URL if integrated, else entity baseurl)
            String xRequestMeta = (String) headerResponse.getOrDefault("x-request-meta", ""); // Request metadata generated by router helper

            // Build new Router URL dynamically
            String newUrl = baseurl + route;

            // Rebuild request with original body + headers
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(newUrl))
                    .method(request.method(), request.bodyPublisher().orElse(HttpRequest.BodyPublishers.noBody()));

            // Copy existing headers
            request.headers().map().forEach((key, values) -> values.forEach(value -> builder.header(key, value)));

            // Add x-request-meta header, if exist in the response
            if(!xRequestMeta.isEmpty()){
                builder.header("x-request-meta", xRequestMeta);
            }
            return builder.build();

        } catch (Exception e) {
            throw new RuntimeException("Failed to configure Sahamati Router headers", e);
        }
    }

    /**
     * Calls Router Integration Helper Service to get:
     * - baseurl
     * - x-request-meta
     */
    private static Map<String, Object> routerIntegrationHelper(String rebitAPIEndpoint, Map<String, Object> rebitRequestBody) throws Exception {
        // Build payload
        Map<String, Object> payload = new HashMap<>();
        payload.put("rebitAPIEndpoint", rebitAPIEndpoint);
        payload.put("recipientId", RECIPIENT_ID);
        payload.put("customerId", "9766334467@aa_simulator");
        payload.put("requestBody", rebitRequestBody);

        // Convert payload to JSON
        String requestJson = mapper.writeValueAsString(payload);

        // Call Router Integration Helper Service
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(ROUTER_INTEGRATION_HELPER_URL))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(requestJson))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        // Convert JSON response into Map
        return mapper.readValue(response.body(), Map.class);
    }
}


```

</details>

<details>

<summary>With Router Integration - Response</summary>

```java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Structured example for FIP-SIMULATOR: Handles incoming account discovery request,
 * calls /response/header to get x-response-meta, and adds it to the outgoing response headers.
 */
public class FipSimulatorResponseMeta {
	private static final String ROUTER_RESPONSE_HEADER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/response/header";
	private static final String RECIPIENT_ID = "AA-SIMULATOR";
	private static final HttpClient client = HttpClient.newHttpClient();
	private static final ObjectMapper mapper = new ObjectMapper();

	/**
	 * Servlet/controller handler for account discovery.
	 */
	public void handleAccountDiscovery(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		// Parse incoming request body (pseudo-code, adapt as per your framework)
		// Example: Map<String, Object> incomingRequestBody = ...
		Map<String, Object> incomingRequestBody = new HashMap<>(); // Replace with actual parsing logic

		// Fetch account details from the incoming request
		Map<String, Object> discoveredAccount = fetchAccountFromRequestBody(incomingRequestBody);
		if (discoveredAccount == null) {
			resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
			resp.setContentType("application/json");
			resp.getWriter().write("{\"error\":\"Account not found\"}");
			return;
		}

		// Build the account discovery response body
		Map<String, Object> responseBody = new HashMap<>();
		responseBody.put("ver", "2.0.0");
		responseBody.put("timestamp", System.currentTimeMillis().toString()); // Use current timestamp
		responseBody.put("txnid", "f35761ac-4a18-11e8-96ff-0277a9fbfedcs");
		responseBody.put("DiscoveredAccounts", java.util.List.of(discoveredAccount));

		// Prepare the Request Body for /response/header 
		Map<String, Object> responseHeaderRequestBody = new HashMap<>();
		responseHeaderRequestBody.put("rebitAPIEndpoint", "/accounts/discover");
		// Optionally extract customerId from incomingRequestBody if available
		responseHeaderRequestBody.put("customerId", "9977336577@aa_simulator");
		responseHeaderRequestBody.put("recipientId", RECIPIENT_ID);
		responseHeaderRequestBody.put("additionalAttributes", new HashMap<>());
		responseHeaderRequestBody.put("responseBody", responseBody);


		// Call /response/header to get the full response
		Map<String, Object> responseHeaderResp = routerIntegrationHelper(responseHeaderRequestBody);
		Object xResponseMeta = responseHeaderResp.get("x-response-meta");
		if (xResponseMeta != null && xResponseMeta instanceof String && !((String)xResponseMeta).isEmpty()) {
			// Set x-response-meta in outgoing response header only if present
			resp.setHeader("x-response-meta", (String)xResponseMeta);
		}

		// Write the account discovery response body as JSON
		resp.setContentType("application/json");
		resp.getWriter().write(mapper.writeValueAsString(responseBody));
	}

	/**
	 * Calls /response/header to get the full response map (timestamp, x-response-meta, baseurl, etc).
	 */
	private static Map<String, Object> routerIntegrationHelper(Map<String, Object> requestBody) throws Exception {
		String json = mapper.writeValueAsString(requestBody);
		HttpRequest request = HttpRequest.newBuilder()
				.uri(URI.create(ROUTER_RESPONSE_HEADER_URL))
				.header("Content-Type", "application/json")
				.POST(HttpRequest.BodyPublishers.ofString(json))
				.build();
		HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
		// The response is expected to be a JSON with x-response-meta field (and possibly others)
		return mapper.readValue(response.body(), Map.class);
	}

	/**
	 * Fetches account details from the request body by searching for the Customer object
	 * with Identifiers (category: STRONG, type: AADHAAR, value: ...).
	 * Returns a dummy account for demonstration.
	 */
	private Map<String, Object> fetchAccountFromRequestBody(Map<String, Object> requestBody) {
		if (requestBody == null) return null;
		Object customerObj = requestBody.get("Customer");
		if (!(customerObj instanceof Map)) return null;
		Map<String, Object> customer = (Map<String, Object>) customerObj;
		Object identifiersObj = customer.get("Identifiers");
		if (!(identifiersObj instanceof java.util.List)) return null;
		java.util.List<?> identifiers = (java.util.List<?>) identifiersObj;
		for (Object idObj : identifiers) {
			if (idObj instanceof Map) {
				Map<String, Object> idMap = (Map<String, Object>) idObj;
				String category = (String) idMap.getOrDefault("category", "");
				String type = (String) idMap.getOrDefault("type", "");
				String value = (String) idMap.getOrDefault("value", "");
				if ("STRONG".equals(category) && "AADHAAR".equals(type) && value != null && !value.isEmpty()) {
					// Found the matching identifier, return dummy account
					Map<String, Object> account = new HashMap<>();
					account.put("FIType", "DEPOSIT");
					account.put("accType", "SAVINGS");
					account.put("accRefNumber", "BANK11111111");
					account.put("maskedAccNumber", "XXXXXXX3468");
					return account;
				}
			}
		}
		return null;
	}
}


```

</details>


# JavaScript

<details>

<summary>Without Router - Current Approach</summary>

```javascript
// Assuming this as previous logic without Router
const axios = require('axios');

const entityMetadataFromCR = {
    baseUrl: 'http://fip-1.dev.sahamati.org.in/fip-simulate',
    id: "FIP-SIMULATOR"
}

const getHttpConfig = ({ baseUrl, route, headers, data, methodType }) => {
    return { url: `${baseUrl}${route}`, headers: headers, data, methodType };
};

const executeDiscoveryRequest = () => {
    const route = '/v2/Accounts/discover';

    const config = getHttpConfig({ baseUrl: entityMetadataFromCR.baseUrl, route, headers: {}, data: {}, methodType: 'POST' });

    axios.request(config)
        .then(response => response.data)
        .catch(error => {
            console.error('Error making discovery request:', error.message);
            throw error;
        });

};

const performAnotherOperations = async (accountDiscoverResponse) => {
    console.log('Perform another operations with the response', accountDiscoverResponse);
}

executeDiscoveryRequest()
    .then(performAnotherOperations)
    .then(() => console.log('Account discovery successful.'))
    .catch(() => console.log('Account discovery failed.'))
    .finally(() => console.log('Account discovery completed.'));

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```javascript
const axios = require('axios');

// Entity metadata (from CR)
const entityMetadataFromCR = {
    baseUrl: 'http://fip-1.sandbox.sahamati.org.in/fip-simulate',
    id: 'FIP-SIMULATOR'
};

// Router Integration Helper URL
const ROUTER_INTEGRATION_HELPER_URL = 'https://api.sandbox.sahamati.org.in/router-helper/v1/request/header';

/**
 * Builds a base axios config
 */
const getHttpConfig = ({ baseUrl, route, headers = {}, data = {}, methodType = 'POST' }) => {
    return {
        url: `${baseUrl}${route}`,
        method: methodType,
        headers: {
            'Content-Type': 'application/json',
            ...headers
        },
        data
    };
};

/**
 * Calls Router Integration Helper Service to get host + x-request-meta
 */
const routerIntegrationHelper = async (route, rebitRequestBody) => {
    const payload = {
        rebitAPIEndpoint: route,
        recipientId: entityMetadataFromCR.id,
        customerId: '9875438980@AA_SIMULATOR',
        requestBody: rebitRequestBody
    };

    const response = await axios.post(ROUTER_INTEGRATION_HELPER_URL, payload, {
        headers: { 'Content-Type': 'application/json' }
    });

    return response.data; // { host, x-request-meta }
};

/**
 * Adds Sahamati Router headers + updates URL
 */
const addSahamatiConfiguration = async ({ config, route, rebitRequestBody }) => {
    const headerResponse = await routerIntegrationHelper(route, rebitRequestBody);

    const host = headerResponse.host;
    const xRequestMeta = headerResponse['x-request-meta'];

    config.url = `${host}${route}`;
    config.headers['x-request-meta'] = xRequestMeta;

    return config;
};

/**
 * Executes account discovery
 */
const executeDiscoveryRequest = async () => {
    const route = '/Accounts/discover';
    const rebitRequestBody = {}; // ReBIT defined request body

    let config = getHttpConfig({
        baseUrl: entityMetadataFromCR.baseUrl,
        route,
        headers: {},
        data: rebitRequestBody,
        methodType: 'POST'
    });

    // Add Sahamati configuration
    config = await addSahamatiConfiguration({ config, route, rebitRequestBody });

    const response = await axios.request(config);
    return response.data;
};

/**
 * Example: further operations after discovery
 */
const performAnotherOperations = async (accountDiscoverResponse) => {
    console.log('Next steps with response:', accountDiscoverResponse);
};

// Run discovery flow
(async () => {
    try {
        const response = await executeDiscoveryRequest();
        console.log('Account discovery successful:', response);

        await performAnotherOperations(response);
    } catch (error) {
        console.error('Account discovery failed. Error:', error.message);
    } finally {
        console.log('Account discovery completed.');
    }
})();

```

</details>

<details>

<summary>With Router Integration - Response</summary>

```javascript
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

const ROUTER_RESPONSE_HEADER_URL = 'https://api.sandbox.sahamati.org.in/router-helper/v1/response/header';
const RECIPIENT_ID = 'AA-SIMULATOR';

function fetchAccountFromRequestBody(requestBody) {
    if (!requestBody) return null;
    const customer = requestBody.Customer;
    if (!customer || typeof customer !== 'object') return null;
    const identifiers = customer.Identifiers;
    if (!Array.isArray(identifiers)) return null;
    for (const idObj of identifiers) {
        if (typeof idObj !== 'object') continue;
        const { category, type, value } = idObj;
        if (category === 'STRONG' && type === 'AADHAAR' && value) {
            return {
                FIType: 'DEPOSIT',
                accType: 'SAVINGS',
                accRefNumber: 'BANK11111111',
                maskedAccNumber: 'XXXXXXX3468',
            };
        }
    }
    return null;
}

async function routerIntegrationHelper(requestBody) {
    const resp = await axios.post(ROUTER_RESPONSE_HEADER_URL, requestBody, {
        headers: { 'Content-Type': 'application/json' },
        timeout: 30000,
    });
    return resp.data;
}

app.post('/accounts/discover', async (req, res) => {
    const incomingRequestBody = req.body;
    const discoveredAccount = fetchAccountFromRequestBody(incomingRequestBody);
    if (!discoveredAccount) {
        return res.status(404).json({ error: 'Account not found' });
    }
    const responseBody = {
        ver: '2.0.0',
        timestamp: new Date().toISOString(), // Use current timestamp
        txnid: 'f35761ac-4a18-11e8-96ff-0277a9fbfedcs',
        DiscoveredAccounts: [discoveredAccount],
    };
    const responseHeaderRequestBody = {
        rebitAPIEndpoint: '/accounts/discover',
        customerId: '9977336577@aa_simulator', // Optionally extract from incomingRequestBody
        recipientId: RECIPIENT_ID,
        additionalAttributes: {},
        responseBody,
    };
    try {
        const responseHeaderResp = await routerIntegrationHelper(responseHeaderRequestBody);
        const xResponseMeta = responseHeaderResp['x-response-meta'];
        if (xResponseMeta) {
            res.set('x-response-meta', xResponseMeta);
        }
    } catch (err) {
        // Optionally log error or handle as needed
    }
    res.json(responseBody);
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});


```

</details>


# GoLang

<details>

<summary>Without Router - Current Approach</summary>

```go
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {

	urlStr := "https://fip-1.dev.sahamati.org.in/v2/Accounts/discover"

	body := []byte(fmt.Sprintf(`{
        "ver": "2.0.0",
        "timestamp": "%s",
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "customer_identifier@AA_identifier",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": [
            "DEPOSIT"
        ]
    }`, time.Now().UTC().Format(time.RFC3339)))

	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer(body))
	if err != nil {
		fmt.Printf("Error creating request: %v\n", err)
		return
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-jws-signature", "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshW...")
	req.Header.Set("x-simulate-res", "Ok")
	req.Header.Set("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A")

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error executing request: %v\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error reading response body: %v\n", err)
		return
	}

	fmt.Printf("Status: %s\n", resp.Status)
	fmt.Printf("Headers: %v\n", resp.Header)
	fmt.Printf("Response Body: %s\n", string(respBody))

	if resp.StatusCode >= 400 {
		fmt.Printf("Error response received - Status Code: %d\n", resp.StatusCode)
	}
}

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

const (
	baseURL                    = "http://fip-1.sandbox.sahamati.org.in/fip-simulate"
	routerIntegrationHelperURL = "https://api.sandbox.sahamati.org.in/router-helper/v1/request/header"
	recipientID                = "FIP-SIMULATOR"
)

var httpClient = &http.Client{Timeout: 30 * time.Second}

func main() {
	// Step 1: Execute discovery request
	response, err := executeDiscoveryRequest()
	if err != nil {
		fmt.Printf("Account discovery failed. Error: %v\n", err)
		return
	}

	fmt.Println("Account discovery successful:", response)

	// Step 2: Do something with response
	performAnotherOperations(response)
}

/**
 * Executes account discovery:
 *  - Builds request
 *  - Adds router headers via Integration Helper
 *  - Sends request
 */
func executeDiscoveryRequest() (string, error) {
	route := "/Accounts/discover"

	// ReBIT defined request body
	rebitRequestBody := map[string]interface{}{
		"ver":      "2.0.0",
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"txnid":    "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
		"Customer": map[string]interface{}{
			"id": "9766334467@aa_simulator",
			"Identifiers": []map[string]interface{}{
				{
					"category": "STRONG",
					"type":     "AADHAAR",
					"value":    "XXXXXXXXXXXXXXXX",
				},
			},
		},
		"FITypes": []string{"DEPOSIT"},
	}

	// Step 1: Build initial request (with base URL)
	url := baseURL + route
	req, err := buildHttpRequest(url, map[string]string{}, rebitRequestBody)
	if err != nil {
		return "", fmt.Errorf("failed to build request: %w", err)
	}

	// Step 2: Add Sahamati router configuration (helper API call)
	req, err = addSahamatiConfiguration(req, route, rebitRequestBody)
	if err != nil {
		return "", fmt.Errorf("failed to add router configuration: %w", err)
	}

	// Step 3: Execute request
	resp, err := httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("request execution failed: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read response body: %w", err)
	}

	return string(respBody), nil
}

/**
 * Builds a basic POST request with headers + JSON body
 */
func buildHttpRequest(url string, headers map[string]string, body map[string]interface{}) (*http.Request, error) {
	jsonData, err := json.Marshal(body)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json")
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	return req, nil
}

/**
 * Adds Sahamati Router headers by calling the Router Integration Helper API
 */
func addSahamatiConfiguration(req *http.Request, route string, rebitRequestBody map[string]interface{}) (*http.Request, error) {
	// Call router integration helper
	headerResponse, err := routerIntegrationHelper(route, rebitRequestBody)
	if err != nil {
		return nil, err
	}

	baseurl, ok := headerResponse["baseurl"].(string)
	if !ok || baseurl == "" {
		return nil, fmt.Errorf("Router Helper response missing required field 'baseurl'")
	}

	// Build new URL
	newURL := baseurl + route

	// Clone body (req.Body cannot be reused after read, so re-marshal)
	var originalBody map[string]interface{}
	json.NewDecoder(req.Body).Decode(&originalBody)
	req.Body.Close()
	jsonBody, _ := json.Marshal(rebitRequestBody)

	newReq, err := http.NewRequest(req.Method, newURL, bytes.NewBuffer(jsonBody))
	if err != nil {
		return nil, err
	}

	// Copy headers from old request
	for k, v := range req.Header {
		for _, vv := range v {
			newReq.Header.Add(k, vv)
		}
	}

	// Add x-request-meta header only if it exists
	if xRequestMeta, ok := headerResponse["x-request-meta"].(string); ok && xRequestMeta != "" {
		newReq.Header.Set("x-request-meta", xRequestMeta)
	}

	return newReq, nil
}

/**
 * Calls Router Integration Helper Service
 */
func routerIntegrationHelper(route string, rebitRequestBody map[string]interface{}) (map[string]interface{}, error) {
	payload := map[string]interface{}{
		"rebitAPIEndpoint": route,
		"recipientId":      recipientID,
		"customerId":       "9766334467@aa_simulator",
		"requestBody":      rebitRequestBody,
	}

	payloadBytes, _ := json.Marshal(payload)
	req, err := http.NewRequest("POST", routerIntegrationHelperURL, bytes.NewBuffer(payloadBytes))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var responseMap map[string]interface{}
	if err := json.Unmarshal(respBody, &responseMap); err != nil {
		return nil, err
	}
	return responseMap, nil
}

/**
 * Example: Further operations with the discovery response
 */
func performAnotherOperations(accountDiscoverResponse string) {
	fmt.Println("Next steps with response:", accountDiscoverResponse)
}


```

</details>

<details>

<summary>With Router Integration - Response</summary>

```go
package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

const (
	ROUTER_RESPONSE_HEADER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/response/header"
	RECIPIENT_ID               = "AA-SIMULATOR"
)

type Account struct {
	FIType          string `json:"FIType"`
	AccType         string `json:"accType"`
	AccRefNumber    string `json:"accRefNumber"`
	MaskedAccNumber string `json:"maskedAccNumber"`
}

type CustomerIdentifier struct {
	Category string `json:"category"`
	Type     string `json:"type"`
	Value    string `json:"value"`
}

type Customer struct {
	ID          string               `json:"id"`
	Identifiers []CustomerIdentifier `json:"Identifiers"`
}

type DiscoverRequest struct {
	Customer Customer `json:"Customer"`
}

func fetchAccountFromRequestBody(requestBody map[string]interface{}) *Account {
	customerObj, ok := requestBody["Customer"].(map[string]interface{})
	if !ok {
		return nil
	}
	identifiersObj, ok := customerObj["Identifiers"].([]interface{})
	if !ok {
		return nil
	}
	for _, idObj := range identifiersObj {
		idMap, ok := idObj.(map[string]interface{})
		if !ok {
			continue
		}
		category, _ := idMap["category"].(string)
		typeVal, _ := idMap["type"].(string)
		value, _ := idMap["value"].(string)
		if category == "STRONG" && typeVal == "AADHAAR" && value != "" {
			return &Account{
				FIType:          "DEPOSIT",
				AccType:         "SAVINGS",
				AccRefNumber:    "BANK11111111",
				MaskedAccNumber: "XXXXXXX3468",
			}
		}
	}
	return nil
}

func routerIntegrationHelper(requestBody map[string]interface{}) (map[string]interface{}, error) {
	jsonData, _ := json.Marshal(requestBody)
	resp, err := http.Post(ROUTER_RESPONSE_HEADER_URL, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)
	return result, nil
}

func handleAccountDiscovery(w http.ResponseWriter, r *http.Request) {
	var incomingRequestBody map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&incomingRequestBody); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(`{"error":"Invalid request"}`))
		return
	}
	discoveredAccount := fetchAccountFromRequestBody(incomingRequestBody)
	if discoveredAccount == nil {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte(`{"error":"Account not found"}`))
		return
	}
	responseBody := map[string]interface{}{
		"ver":                "2.0.0",
		"timestamp":          time.Now().Format(time.RFC3339),
		"txnid":              "f35761ac-4a18-11e8-96ff-0277a9fbfedcs",
		"DiscoveredAccounts": []Account{*discoveredAccount},
	}
	responseHeaderRequestBody := map[string]interface{}{
		"rebitAPIEndpoint":     "/accounts/discover",
		"customerId":           "9977336577@aa_simulator",
		"recipientId":          RECIPIENT_ID,
		"additionalAttributes": map[string]interface{}{},
		"responseBody":         responseBody,
	}
	responseHeaderResp, err := routerIntegrationHelper(responseHeaderRequestBody)
	if err == nil {
		if xResponseMeta, ok := responseHeaderResp["x-response-meta"].(string); ok && xResponseMeta != "" {
			w.Header().Set("x-response-meta", xResponseMeta)
		}
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(responseBody)
}

func main() {
	http.HandleFunc("/accounts/discover", handleAccountDiscovery)
	log.Println("Server running on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}


```

</details>


# C\#

<details>

<summary>Without Router - Current Approach</summary>

```csharp
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace AAEcosystem
{
    public class AccountDiscoveryClient
    {
        private const string API_URL = "https://fip-1.dev.sahamati.org.in/v2/Accounts/discover";
        private const string JWS_SIGNATURE = "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshWBhWeY-bLBeSmxkU5VpH-lQjBjGFW_2opX3ZK5XfF7oPc3wkp-Qj7-qVfgTg53YvGyS3oLbKvkMRHtKa33x5I-0b8BmlMzojtnA_zFfubOJoqZVPpz7BQ4qrazizaF2Z6m3FygNGuAkdbdqtnCgPCjBZ6ibkpyiKR_n_g5FcTOq7fa7JgE6IoMD0R575ssdFbHzcT-IZs0DDqc_DJ0pR7m56z9IlmRZ6kUg99kaYVl6GUHSYPwY9OCbmHa7EbgE5vUdIJjhF3vJDZhYMWCojpbh9KLGSpbHkWG4OY19S-YNJv85FtXZe0Q";
        private const string BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A";
        private const string FIP_ID = "FIP-SIMULATOR";

        private static readonly string REQUEST_BODY = @"{
            ""ver"": ""2.0.0"",
            ""timestamp"": ""2023-06-26T06:41:54.904+0000"",
            ""txnid"": ""f35761ac-4a18-11e8-96ff-0277a9fbfedc2"",
            ""Customer"": {
                ""id"": ""customer_identifier@AA_identifier"",
                ""Identifiers"": [
                    {
                        ""category"": ""STRONG"",
                        ""type"": ""AADHAAR"",
                        ""value"": ""XXXXXXXXXXXXXXXX""
                    }
                ]
            },
            ""FITypes"": [
                ""DEPOSIT""
            ]
        }";

        public static async Task Main(string[] args)
        {
            try
            {
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);

                var request = new HttpRequestMessage(HttpMethod.Post, API_URL);
                request.Headers.Add("x-jws-signature", JWS_SIGNATURE);
                request.Headers.Add("x-simulate-res", "Ok");

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", BEARER_TOKEN);
                request.Content = new StringContent(REQUEST_BODY, Encoding.UTF8, "application/json");

                var response = await httpClient.SendAsync(request);
                var responseBody = await response.Content.ReadAsStringAsync();

                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.StatusCode}");
                Console.WriteLine($"Response Body: {responseBody}");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Error occurred: {ex.Message}");
                Console.Error.WriteLine(ex.StackTrace);
            }
        }
    }
}

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```csharp
import requests
import json
from datetime import datetime
from typing import Dict, Any

# ==============================
#  Config Metadata
# ==============================
ENTITY_METADATA_FROM_CR = {
    "baseUrl": "http://fip-1.sandbox.sahamati.org.in/fip-simulate",
    "id": "FIP-SIMULATOR"
}
ROUTER_INTEGRATION_HELPER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/request/header"


# ==============================
#  Core Functions
# ==============================
def build_discovery_request_body() -> Dict[str, Any]:
    """Creates the ReBIT-defined account discovery request body."""
    return {
        "ver": "2.0.0",
        "timestamp": datetime.utcnow().isoformat(),
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "9766334467@aa_simulator",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": ["DEPOSIT"]
    }


def get_http_config(base_url: str, route: str, headers: Dict[str, str], data: Dict[str, Any], method_type: str) -> Dict[str, Any]:
    """Builds base HTTP config."""
    return {
        "url": f"{base_url}{route}",
        "headers": headers,
        "json": data,
        "method": method_type
    }


def router_integration_helper(route: str, rebit_request_body: Dict[str, Any]) -> Dict[str, Any]:
    """Calls Router Integration Helper service to get host and x-request-meta."""
    payload = {
        "rebitAPIEndpoint": route,
        "recipientId": ENTITY_METADATA_FROM_CR["id"],
        "customerId": "9766334467@aa_simulator",
        "requestBody": rebit_request_body
    }

    response = requests.post(
        ROUTER_INTEGRATION_HELPER_URL,
        json=payload,
        headers={"Content-Type": "application/json"},
        timeout=30
    )
    response.raise_for_status()
    return response.json()


def add_sahamati_configuration(config: Dict[str, Any], route: str, rebit_request_body: Dict[str, Any]) -> Dict[str, Any]:
    """Updates config with router URL and adds x-request-meta header by calling Router Helper API."""
    header_response = router_integration_helper(route, rebit_request_body)

    baseurl = header_response.get("baseurl")
    if not baseurl:
        raise RuntimeError("Router Helper response missing required field 'baseurl'")

    # Update URL
    config["url"] = f"{baseurl}{route}"
    config.setdefault("headers", {})

    # Add x-request-meta header only if it exists
    x_request_meta = header_response.get("x-request-meta")
    if x_request_meta:
        config["headers"]["x-request-meta"] = x_request_meta

    return config


def execute_discovery_request() -> Dict[str, Any]:
    """Executes account discovery request via Sahamati Router (helper API flow)."""
    route = "/Accounts/discover"
    rebit_request_body = build_discovery_request_body()

    # Step 1: Base config
    config = get_http_config(
        base_url=ENTITY_METADATA_FROM_CR["baseUrl"],
        route=route,
        headers={},
        data=rebit_request_body,
        method_type="POST"
    )

    # Step 2: Add Router configuration (call helper API)
    config = add_sahamati_configuration(config, route, rebit_request_body)

    # Step 3: Execute request
    response = requests.request(**config, timeout=30)
    response.raise_for_status()
    return response.json()


def perform_another_operations(account_discover_response: Dict[str, Any]) -> None:
    """Placeholder for next steps."""
    print("Next steps with response:")
    print(json.dumps(account_discover_response, indent=2))


# ==============================
#  Main Runner
# ==============================
if __name__ == "__main__":
    try:
        response = execute_discovery_request()
        perform_another_operations(response)
        print("✅ Account discovery successful.")
    except Exception as e:
        print(f"❌ Account discovery failed. Reason: {e}")
    finally:
        print("ℹ️ Account discovery completed.")

```

</details>

<details>

<summary>With Router Integration - Response</summary>

```csharp
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

const string ROUTER_RESPONSE_HEADER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/response/header";
const string RECIPIENT_ID = "AA-SIMULATOR";

async Task<Dictionary<string, object>> routerIntegrationHelper(Dictionary<string, object> requestBody)
{
    using var client = new HttpClient();
    var json = JsonSerializer.Serialize(requestBody);
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    var resp = await client.PostAsync(ROUTER_RESPONSE_HEADER_URL, content);
    resp.EnsureSuccessStatusCode();
    var respJson = await resp.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<Dictionary<string, object>>(respJson);
}

Dictionary<string, object> FetchAccountFromRequestBody(Dictionary<string, object> requestBody)
{
    if (requestBody == null || !requestBody.TryGetValue("Customer", out var customerObj) || customerObj is not JsonElement customerElem || customerElem.ValueKind != JsonValueKind.Object)
        return null;
    if (!customerElem.TryGetProperty("Identifiers", out var identifiersElem) || identifiersElem.ValueKind != JsonValueKind.Array)
        return null;
    foreach (var idElem in identifiersElem.EnumerateArray())
    {
        if (idElem.ValueKind != JsonValueKind.Object) continue;
        var category = idElem.GetProperty("category").GetString();
        var type = idElem.GetProperty("type").GetString();
        var value = idElem.GetProperty("value").GetString();
        if (category == "STRONG" && type == "AADHAAR" && !string.IsNullOrEmpty(value))
        {
            return new Dictionary<string, object>
            {
                ["FIType"] = "DEPOSIT",
                ["accType"] = "SAVINGS",
                ["accRefNumber"] = "BANK11111111",
                ["maskedAccNumber"] = "XXXXXXX3468"
            };
        }
    }
    return null;
}

app.MapPost("/accounts/discover", async (HttpRequest req, HttpResponse res) =>
{
    var incomingRequestBody = await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(req.Body);
    var discoveredAccount = FetchAccountFromRequestBody(incomingRequestBody);
    if (discoveredAccount == null)
    {
        res.StatusCode = 404;
        await res.WriteAsJsonAsync(new { error = "Account not found" });
        return;
    }
    var responseBody = new Dictionary<string, object>
    {
        ["ver"] = "2.0.0",
        ["timestamp"] = "2023-06-26T06:45:54.904+0000",
        ["txnid"] = "f35761ac-4a18-11e8-96ff-0277a9fbfedcs",
        ["DiscoveredAccounts"] = new[] { discoveredAccount }
    };
    var responseHeaderRequestBody = new Dictionary<string, object>
    {
        ["rebitAPIEndpoint"] = "/accounts/discover",
        ["customerId"] = "9977336577@aa_simulator",
        ["recipientId"] = RECIPIENT_ID,
        ["additionalAttributes"] = new Dictionary<string, object>(),
        ["responseBody"] = responseBody
    };
    var responseHeaderResp = await routerIntegrationHelper(responseHeaderRequestBody);
    if (responseHeaderResp.TryGetValue("x-response-meta", out var xResponseMetaObj) && xResponseMetaObj is JsonElement xMetaElem && xMetaElem.ValueKind == JsonValueKind.String && !string.IsNullOrEmpty(xMetaElem.GetString()))
    {
        res.Headers["x-response-meta"] = xMetaElem.GetString();
    }
    res.ContentType = "application/json";
    await res.WriteAsJsonAsync(responseBody);
});

app.Run();


```

</details>


# Observability through Router

While the SahamatiNet Router was introduced to simplify interoperability across the AA ecosystem, its centralized role also creates an opportunity to implement comprehensive observability features.

To move beyond connectivity, the AA ecosystem also needs **visibility**. Observability ensures that FIUs, AAs, FIPs, and Sahamati can measure performance, identify bottlenecks, and generate reliable metrics across the network.

#### Approaches for Passing Attributes to Router

There were two possible ways to capture and pass the required observability attributes:

1. **Directly by Entities**\
   Each entity (FIU, FIP, or AA) could add the required fields to the `x-request-meta` or `x-response-meta` headers while routing through the Router.

   * **Challenge**: Any addition or removal of fields would require **every entity** to update their implementation, leading to high coordination effort, delays, and resource overhead.

2. **Router Integration Helper (RIH) – Chosen Approach**\
   To avoid this complexity, Sahamati designed the **Router Integration Helper (RIH)**.

   * The RIH is a containerized service that each entity can deploy within their infrastructure.
   * Before making an API call to the Router, the entity makes an API call to the **RIH**, passing the following inputs:
     * `rebitAPIEndpoint`&#x20;
     * `rebitRequestBody`  or `rebitResponseBody`
     * `recipient-id`&#x20;
     * `customer-id`&#x20;
   * The RIH extracts the required header fields, enriches them, and returns an encrypted response. This enriched payload is then passed to the Router.
   * If the required fields ever change in the future, entities simply update their **RIH container** instead of modifying their own application code.

   ####

#### Integration with Central Registry (CR)

After a call is made to the RIH, it queries the **Central Registry (CR)** to fetch the **host URL**. This determines whether the recipient entity is on the Router network. The host URL returned by the CR is then used to forward the enriched request via the Router.

#### Deployment Model

* **MVP Phase**: Sahamati will host and manage the RIH centrally in its infrastructure.
* **Production Phase**: Each entity will deploy and maintain the RIH container in their own infrastructure

<figure><img src="/files/XtciN1jQiYNzLodWwBVU" alt=""><figcaption></figcaption></figure>

For the complete list of captured fields and their mapping, see [Observability attributes](/sahamatinet-mvp/integration-steps/integration-with-router/observability-through-router/observability-attributes)


# Router Integration Helper API

## Generate Request Header

> This API generates request headers required to call Router.<br>

```json
{"openapi":"3.0.3","info":{"title":"Router Integration Helper APIs","version":"1.0.0"},"servers":[{"url":"https://api.sandbox.sahamati.org.in/router-helper/v1"}],"paths":{"/request/header":{"post":{"summary":"Generate Request Header","description":"This API generates request headers required to call Router.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rebitAPIEndpoint","recipientId","customerId","requestBody"],"properties":{"rebitAPIEndpoint":{"type":"string"},"recipientId":{"type":"string"},"customerId":{"type":"string"},"additionalAttributes":{"type":"object"},"requestBody":{"type":"object","required":["ver","timestamp","txnid","Customer","FITypes"],"properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnid":{"type":"string"},"Customer":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"Identifiers":{"type":"array","items":{"type":"object","required":["category","type","value"],"properties":{"category":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"}}}}}},"FITypes":{"type":"array","items":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"Successfully generated request header","content":{"application/json":{}}},"401":{"description":"Unauthorized – invalid or missing Bearer token","content":{"application/json":{}}},"404":{"description":"Bad request – invalid payload","content":{"application/json":{}}}}}}}}
```

## Generate Response Header

> This API generates response headers that can be used while sending data back to Router APIs.<br>

```json
{"openapi":"3.0.3","info":{"title":"Router Integration Helper APIs","version":"1.0.0"},"servers":[{"url":"https://api.sandbox.sahamati.org.in/router-helper/v1"}],"paths":{"/response/header":{"post":{"summary":"Generate Response Header","description":"This API generates response headers that can be used while sending data back to Router APIs.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rebitAPIEndpoint","recipientId","responseBody"],"properties":{"rebitAPIEndpoint":{"type":"string"},"recipientId":{"type":"string"},"additionalAttributes":{"type":"object"},"responseBody":{"type":"object","required":["ver","timestamp","txnid","DiscoveredAccounts"],"properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnid":{"type":"string"},"DiscoveredAccounts":{"type":"array","items":{"type":"object","required":["FIType","accType","accRefNumber","maskedAccNumber"],"properties":{"FIType":{"type":"string"},"accType":{"type":"string"},"accRefNumber":{"type":"string"},"maskedAccNumber":{"type":"string"}}}}}}}}}}},"responses":{"200":{"description":"Successfully generated response header","content":{"application/json":{}}},"401":{"description":"Unauthorized – invalid or missing Bearer token","content":{"application/json":{}}},"404":{"description":"Bad request – invalid payload","content":{"application/json":{}}}}}}}}
```


# Observability Attributes

Based on the attributes listed in the subsections of this page ([**FIP API Attributes**](/sahamatinet-mvp/integration-steps/integration-with-router/observability-through-router/observability-attributes/fip-api-attributes), [**AA API Attributes**](/sahamatinet-mvp/integration-steps/integration-with-router/observability-through-router/observability-attributes/aa-api-attributes), and [**FIU API Attributes**](/sahamatinet-mvp/integration-steps/integration-with-router/observability-through-router/observability-attributes/fiu-api-attributes)), the following mappings define which values must be captured and included in the `x-request-meta` and/or `x-response-meta` headers

<table><thead><tr><th width="221">Field Path</th><th width="181.33331298828125">Header Key</th><th>Source</th></tr></thead><tbody><tr><td>Customer.id</td><td>cust-id</td><td>Both</td></tr><tr><td>RefNumber</td><td>acc-ref-num</td><td>Response</td></tr><tr><td>AccountDetails</td><td>acc-discovered-count</td><td>Response</td></tr><tr><td>AccountLinkStatusNotification.customerAddress</td><td>cust-id</td><td>Request</td></tr><tr><td>AccountLinkStatusNotification.linkRefNumber</td><td>acc-ref-num</td><td>Request</td></tr><tr><td>AccLinkDetails.0.status</td><td>acc-link-status</td><td>Response</td></tr><tr><td>AccLinkDetails.0.customerAddress</td><td>cust-id</td><td>Response</td></tr><tr><td>ConsentDetail.Customer.id</td><td>cust-id</td><td>Request</td></tr><tr><td>consentId</td><td>consent-id</td><td>Both</td></tr><tr><td>ConsentDetail.Purpose.code</td><td>purpose-code</td><td>Request</td></tr><tr><td>ConsentDetail.Purpose.text</td><td>purpose-text</td><td>Request</td></tr><tr><td>ConsentDetail.FIDataRange.from</td><td>datarange-from</td><td>Request</td></tr><tr><td>ConsentDetail.FIDataRange.to</td><td>datarange-to</td><td>Request</td></tr><tr><td>ConsentDetail.Frequency.unit</td><td>frequency-unit</td><td>Request</td></tr><tr><td>ConsentDetail.Frequency.value</td><td>frequency-value</td><td>Request</td></tr><tr><td>ConsentHandle</td><td>consent-handle</td><td>Response</td></tr><tr><td>sessionId</td><td>session-id</td><td>Both</td></tr><tr><td>ConsentStatusNotification.consentId</td><td>consent-id</td><td>Request</td></tr><tr><td>ConsentStatusNotification.consentStatus</td><td>consent-status</td><td>Request &#x26; Response</td></tr><tr><td>FIStatusNotification.sessionId</td><td>session-id</td><td>Request</td></tr><tr><td>FIStatusNotification.sessionStatus</td><td>session-status</td><td>Request</td></tr></tbody></table>


# AA API Attributes

Here, the API requests are invoked by the Financial Information Provider (FIP) or Financial Information User (FIU) as the sender, targeting the respective AA endpoints.

#### /Consent

* **Request Attributes**:
  * `hash(ConsentDetail.Customer.id)` – A hashed identifier of the customer generated during the registration with AA, ensuring privacy while identifying the user.
  * `ConsentDetail.Purpose.code` – Code representing the purpose for which consent is being created.
  * `ConsentDetail.Purpose.text` – Human-readable description of the consent purpose.
  * `ConsentDetail.FIDataRange.from` – Start date of the financial data being requested.
  * `ConsentDetail.FIDataRange.to` – End date of the financial data being requested.
  * `ConsentDetail.Frequency.unit` – Unit of frequency (e.g. HOUR, DAY, MONTH, YEAR, INF) for data fetch.
  * `ConsentDetail.Frequency.value` – Numeric value indicating how often data should be fetched.
* **Response Attributes**:
  * `ConsentHandle` – A ID generated until the consent is fully approved and a consent ID is issued.

#### /Consent/handle

* **Request Attributes**:
  * `ConsentHandle` – Handle provided when the consent request was created.
* **Response Attributes**:
  * `ConsentStatus.id` – Unique identifier for the consent.
  * `ConsentStatus.status` – Current status of the consent (e.g. PAUSED, ACTIVE, REVOKED, EXPIRED).

#### /Consent/fetch

* **Request Attributes**:
  * `consentId` – The permanent identifier of the consent whose details are being fetched.
* **Response Attributes**: None.

#### /FI/request

* **Request Attributes**:
  * `Consent.id` – Identifier of the consent under which financial information is requested.
* **Response Attributes**:
  * `consentId` – Same consent identifier (used interchangeably in some implementations).
  * `sessionId` – Unique identifier for the FI data request session.

#### /FI/fetch

* **Request Attributes**:
  * `sessionId` – Unique identifier of the session created during the FI request, used to fetch the data.
* **Response Attributes**: None.

#### /Consent/Notification

* **Request Attributes**:
  * `ConsentStatusNotification.consentId` – Identifier of the consent being updated.
  * `ConsentStatusNotification.consentStatus` – Current status of the consent (e.g.PAUSED, ACTIVE, REVOKED, EXPIRED).
* **Response Attributes**: None.

#### /FI/Notification

* **Request Attributes**:
  * `FIStatusNotification.sessionId` – Identifier of the session for which financial information status is being notified.
  * `FIStatusNotification.sessionStatus` – Current status of the FI session (e.g., COMPLETED, FAILED, PARTIAL).
* **Response Attributes**: None.

#### /Account/link/Notification

* **Request Attributes**:
  * `AccountLinkStatusNotification.customerAddress` – Identifier of the Customer generated during the registration with AA.
  * `AccountLinkStatusNotification.linkRefNumber` – Reference number assigned as part of Account Linking Process.
  * `AccountLinkStatusNotification.linkStatus` – Current status of the account linkage (e.g., LINKED,).
* **Response Attributes**: None.


# FIU API Attributes

Here, the API requests are invoked by the Financial Information User (FIU) as the sender, targeting the respective AA endpoints.

#### /Consent/Notification

* **Request Attributes**:
  * `ConsentStatusNotification.consentId` – Identifier of the consent approved by the customer and issued by the AA.
  * `ConsentStatusNotification.consentHandle` – AA-generated consent handle created on receiving a consent request, used to track status and obtain the consent ID after customer approval.
  * `ConsentStatusNotification.consentStatus` – Current status of the consent (e.g. ACTIVE, PENDING, REVOKED, PAUSED, REJECTED, EXPIRED).
* **Response Attributes**: None.

#### /FI/Notification

* **Request Attributes**:
  * `FIStatusNotification.sessionId` – Base64-encoded UUID issued by the AA as a session identifier for each financial information access request, returned to the FIU or AA client.
  * `FIStatusNotification.sessionStatus` – Current status of the FI session (e.g. ACTIVE, COMPLETED, EXPIRED, FAILED).
* **Response Attributes**: None.

####


# FIP API Attributes

Here, the API requests are invoked by the Account Aggregator (AA) as the sender, targeting the respective FIP endpoints.

#### /Accounts/discover

* **Request Attributes**:&#x20;
  * `hash(Customer.id)` – A hashed identifier of the customer generated during the registration with AA, ensuring privacy while identifying the user.
* **Response Attributes**:&#x20;
  * `Count(DiscoveredAccounts)` – The count of accounts discovered for the customer.

#### /Accounts/link

* **Request Attributes**:&#x20;
  * `hash(Customer.id)` – A hashed identifier of the customer generated during the registration with AA, ensuring privacy while identifying the user..
* **Response Attributes**:&#x20;
  * `RefNumber` – A Temporary reference number generated by FIP for the account linking request.

#### /Accounts/delink

* **Request Attributes**:&#x20;
  * `hash(Account.customerAddress)` – A hashed identifier of the Customer generated during the registration with AA.
* **Response Attributes**:

  * `AccLinkDetails.linkRefNumber` – Link reference number associated with the account linkage assigned by FIP.
  * `AccLinkDetails.status` – Current status of the account linkage (e.g. DELINKED).
  * `AccLinkDetails.customerAddress` – Identifier of the Customer generated during the registration with AA.

#### /Accounts/link/verify

* **Request Attributes**:
  * `refNumber` – The reference number of the account linking request.
* **Response Attributes**:
  * `Count(AccLinkDetails)` – Number of linked accounts details.
  * `AccLinkDetails[*].linkRefNumber` – Link reference numbers of individual accounts.
  * `AccLinkDetails[*].status` – Status of each linked account.
  * `hash(Customer.id)` – Hashed identifier of the customer.

#### /Consent

* **Request Attributes**:
  * `consentId` – Unique identifier of the consent being created or managed.
  * `status` – Current state of the consent (e.g., PAUSED, ACTIVE, REVOKED, EXPIRED).
* **Response Attributes**: None.

#### /Consent/Notification

* **Request Attributes**:
  * `ConsentStatusNotification.consentId` – Identifier of the consent whose status is being notified.
  * `ConsentStatusNotification.consentStatus` – Current status of the consent (e.g. PAUSED, ACTIVE, REVOKED, EXPIRED).
* **Response Attributes**: None.

#### /FI/request

* **Request Attributes**:
  * `Consent.id` – Identifier of the consent under which the FI request is made.
* **Response Attributes**:
  * `consentId` – Unique identifier for the consent, returned as part of the response.
  * `sessionId` – Unique identifier for the FI data request session created.

#### /FI/fetch

* **Request Attributes**:
  * `sessionId` – Unique identifier of the FI data request session, used to fetch the financial information.
* **Response Attributes**: None.


# Router APIs Specifications

The Router, currently in the Sandbox environment for the POC, implements all ReBIT API specifications as detailed in [ReBIT API Documentation](https://api.rebit.org.in).

The following pages provide an overview of these API implementations.

* [Financial Information User (FIU) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/fiu-api-specification)
* [Account Aggregator (AA) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/aa-api-specification)
* [Financial Information Provider (FIP) API Specification](/no-longer-relevent/technical-specifications/router-api-specs/open-api-specification/fip-api-specification)


# FIU API Specification

{% openapi src="/files/heipCgFMvnZhqwHwZhSd" path="/Consent/Notification" method="post" %}
[FIU-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ZRUmmdEwrRF1xyatcLgz/FIU-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/heipCgFMvnZhqwHwZhSd" path="/FI/Notification" method="post" %}
[FIU-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/ZRUmmdEwrRF1xyatcLgz/FIU-v2-latest.yaml)
{% endopenapi %}


# AA API Specification

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/handle" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/fetch" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/request" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/fetch" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Consent/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/FI/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Account/link/Notification" method="post" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/B8HcrQxGGuhf2UAMkWQ1" path="/Heartbeat" method="get" %}
[AA-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/eCy3A9IKILx6QO5efU05/AA-v2-latest.yaml)
{% endopenapi %}


# FIP API Specification

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/discover" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/link" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/delink" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Accounts/link/verify" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/FI/request" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/FI/fetch" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Consent/Notification" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Consent" method="post" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}

{% openapi src="/files/ctUOxXV6pvmjQNT93XUQ" path="/Heartbeat" method="get" %}
[FIP-v2-latest.yaml](https://content.gitbook.com/content/CKUjTKikPLYOjZEtClEd/blobs/5ZsG7VbDcqrnaghWPtSK/FIP-v2-latest.yaml)
{% endopenapi %}


# ReBIT Workflows using Router

In the Account Aggregator (AA) ecosystem, secure data sharing is facilitated through three key workflows, each governed by standardized ReBIT APIs. The process begins with **User Login to AA for Account Discovery & Linking**, where users provide identifiers such as mobile numbers to identify and connect their financial accounts across multiple institutions; the linking is authorized via a One-Time Password (OTP). Following this, the **Consent Workflow** enables Financial Information Users (FIUs) to obtain explicit user consent for accessing their financial data from various Financial Information Providers (FIPs), ensuring compliance with stringent privacy standards. Finally, once consent is granted, the **Financial Information (FI) Request Workflow** allows FIUs to securely request financial data from FIPs through the AA, ensuring that only authorized data is retrieved and shared, thereby maintaining privacy and data integrity throughout the process.

## [**Account Discovery & Linking**](/no-longer-relevent/buildaathon-2024/network-scenarios/account-discovery-and-linking)

**Account Discovery & Linking** allows users to identify and link their accounts across multiple financial institutions. This process is initiated when a user provides their mobile number or other identification, which the Account Aggregator uses to query Financial Information Providers (FIPs) for linked accounts. Upon identification, the user is prompted to authorize the linking via an OTP (One-Time Password). ReBIT APIs facilitate the communication and data flow between the AA, FIU, and FIP during the discovery and linking phases.

## [**Consent Workflow**](/no-longer-relevent/buildaathon-2024/network-scenarios/consent-workflow)

The **Consent Workflow** is at the core of the Account Aggregator (AA) ecosystem. It governs how a Financial Information User (FIU) obtains explicit consent from the user to access their financial data held by various Financial Information Providers (FIPs). This workflow ensures that data sharing is fully authorized by the user, adhering to stringent data privacy regulations. The consent mechanism follows a standardized flow, involving the FIU, AA, and FIP, where ReBIT APIs are used to securely request, manage, and process user consent.

## [**Financial Information (FI) Request Workflow**](/no-longer-relevent/buildaathon-2024/network-scenarios/fi-request-workflow)

The **FI Request Workflow** outlines how a Financial Information User (FIU) requests data from Financial Information Providers (FIPs) via the Account Aggregator. Once consent is granted, the FIU can initiate a financial information request, and the AA retrieves the required data from the FIP. ReBIT APIs are integral in transmitting these requests securely and ensuring that only authorized data is shared with the FIU.

## Router Integration Changes

The following sections provide a detailed explanation of these above mentioned workflows, including a diagram illustrating API interactions (Reference) within the AA ecosystem. The diagram also highlights changes related to the Router. Review these sections carefully to understand the modifications and the necessary updates to your code.


# Account Discovery & Linking

The Account Discovery & Linking process involves identifying the financial accounts a user holds across various institutions (FIPs) and linking them to the Account Aggregator for easy management and data access.

### **Steps Involved in Account Discovery & Linking:**

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfjISSEpnWOqjy8C0B1W4uVSxf548B1ti73BbudIHK4wleC0JkB-MyEZuBfbs8ZyxiKQ5hNKz-IxVXUhp99kXMQS8j7u8B7IIf46iIR38-eVwkbN5eSYDdLN3A80sk71QJPnDD2DA?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>Account Discovery &#x26; Linking</p></figcaption></figure>

#### **1. User Login and Identity Verification:**

The user logs into the AA application and provides their mobile number or other identity verification details. The AA then queries the FIPs to discover accounts associated with the user.

***API (Internal API Spec):*** ***/user/send-otp (POST)*****:** The user login process after entering the phone number sends an OTP for login.

***API (Internal API Spec):*** ***/user/verify-otp (POST)*****:** The user enters the OTP sent in the previous step to verify and login.

#### **2. Request to FIPs for Account Discovery&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The Account Discovery request is routed to the FIP via the Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

Upon receiving the request, each FIP searches its records for accounts associated with the provided identity (e.g., mobile number or email).

***ReBIT API:*****&#x20;/Accounts/discover (POST) with 'x-request-meta' header**: The FIP returns details about the user's accounts to the AA.

#### **3. User Confirms Accounts to Link:**

Once the AA receives the list of accounts from various FIPs, it presents this information to the user. The user selects the accounts they wish to link with the AA. To authorize the linking, the user receives a One-Time Password (OTP).

***ReBIT API:*****&#x20;/Accounts/link (POST) with 'x-request-meta' header**: The AA sends a request to FIP through Router with request header (`x-request-meta`) to initiate linking of the account with the AA customer account.

***ReBIT API:*****&#x20;/Accounts/link/verify (POST) with 'x-request-meta' header**: The user needs to provide the OTP sent with the previous step to complete the account linking. The AA send the OTP as token to FIP through Router with request header (`x-request-meta`) to verify the account link.

#### **4. Accounts Linked Successfully:**

After successful OTP verification, the user’s selected accounts are linked to the AA. The FIP will send a notification to the AA on successful OTP verification for the account linking. These accounts can now be used for data sharing in future consent workflows.

***ReBIT API:*****&#x20;/Account/link/Notification (POST) with 'x-request-meta' header**: The FIP sends a notification about status of account linking to AA through Router. The AA confirms that the accounts have been successfully linked and communicates this to the user.

### Reference Implementation Guide & Using Simulator

For the above use case implementation, AA need to implement a few internal APIs for hanlding the user registration, login and accounts data along with the ReBIT API Specification.

In this scenario, the AA need to have a mock FIP to support the integration testing with mock response for the API requests to FIP. Please use the "FIP-SIMULATOR" for the integration testing with mock data. Please refer to [Testing with Simulator](/sahamatinet-poc/integration-with-simulators) for more details.


# Consent Workflow

The consent workflow is a fundamental part of the Account Aggregator (AA) ecosystem. It ensures that Financial Information Users (FIUs) can access user data from Financial Information Providers (FIPs) only after obtaining explicit consent from the user. This workflow is governed by a series of secure and standardized interactions using the ReBIT APIs.

### **Steps Involved in Consent Workflow:**

#### Pre-requisites:

The [Account Discovery & Linking](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking) is handled by the user to execute the Consent workflow.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfldUHurAqJFFUH1yDIOAEoxa2n666KTxfbGkOHF3XeDubtIhV0stST_y65hQEC1jYNxSbFRfsn_I-IHBqe9vkFIAHMRNK48ni2m0xjTKTe-ezJAQyys4rr2t1Uo-0KXfizZi7_Dw?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>Consent Workflow</p></figcaption></figure>

#### **1. FIU Initiates Consent Request&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The FIU initiates the process by sending a consent request to the Account Aggregator (AA). The request specifies the type of financial data, the duration, and the purpose for which it is being requested. This consent request is made by the FIU to the AA through Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

***ReBIT API: /Consent (POST)*****&#x20;with 'x-request-meta' header***:* The FIU sends the consent request to the AA using this API through Router. The request includes the data access requirements, purpose, and duration for which access is required.

***API (AA Internal Spec): /Consent/create (POST):*** The AA create the consent artefact and stores for future use with pending status.

#### **2. AA Presents Consent to User:**

After receiving the consent request, the AA communicates with the user via its mobile app or web portal, presenting the consent details. The user reviews and either approves or denies the request.

***API (AA Internal Spec): /Consent/read (GET)**:* The AA retrieves the consent artefact details to present to the user for approval.

#### **3. User Grants Consent:**

If the user approves the consent request, the AA generates a consent artefact. This artefact is a formal document containing all the details of the user’s consent, such as the scope, purpose, and validity.

***API (AA Internal Spec): /Consent/accept (POST)**:* The AA update the status and stores the consent artefact after the user grants approval.

#### **4. AA Shares Consent with FIU & FIP&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once consent is granted, the AA sends the consent artefact to both the FIU and the relevant FIP. The FIP uses this consent artefact to validate requests for financial data.

***ReBIT API: /Consent/Notification (POST)*****&#x20;with 'x-request-meta' header***:* The FIU & FIP is notified about the granted consent via this API. It helps,&#x20;

* FIU to fetch the consent artefact from AA and use it for FI request.
* FIP to validate the future FI data requests from the FIU.

***ReBIT API: /Consent/fetch (POST)*****&#x20;with 'x-request-meta' header***:* The FIU fetches the Consent artefact from AA through Router to use it for future FI data requests.

#### **5. Consent Revocation (Optional):**

The user has the ability to revoke consent at any time, cutting off access to their data.

***API (AA Internal Spec): /Consent/revoke (POST)**:* This API allows the user to revoke previously granted consent.


# FI Request Workflow

The Financial Information (FI) Request Workflow allows a Financial Information User (FIU) to request data from a Financial Information Provider (FIP) via the Account Aggregator (AA), based on user consent.

### **Steps Involved in FI Request Workflow:**

#### Pre-requisites:

The [Account Discovery & Linking](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/account-discovery-and-linking), [Consent Workflow](/sahamatinet-poc/integration-steps/rebit-workflows-using-router/consent-workflow) are handled by the user to execute the FI request.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdl6CUYF1NKze5myGSxCUWeaQshiLP3mNgdIDHLcOI9zDHm_mixEBp9G-TB0D2qHuvDYCZMq9QWgJ57OepHr2s4omoQE4FAvBRtVgsIvp9VvIRR95an-9WU2cIde6LLi0ws12Cz?key=bdSmp_LkiJMKaUQLHEN9__RS" alt=""><figcaption><p>FI Request Workflow</p></figcaption></figure>

#### **1. FIU Sends FI Request to AA&#x20;**<mark style="color:green;">**through Router**</mark>**:**

After the user’s consent is obtained, the FIU sends a Financial Information (FI) request to the AA to retrieve the data from the relevant FIPs. This request contains the details of the data required (such as bank account statements, loan details, etc.).

***ReBIT API:*****&#x20;/FI/Request (POST) with 'x-request-meta' header**: The FIU sends the FI request to the AA specifying the type of financial data required and the consent artefact through Router, following these steps:

* Retrieve the FIP identifier from the Central Registry.
* Construct the request header (`x-request-meta`) using the retrieved identifier for Router compatibility.
* Transmit the request to the Router along with the prepared header.

#### **2. AA Forwards FI Request to FIP&#x20;**<mark style="color:green;">**through Router**</mark>**:**

The AA validates the request against the consent artefact and forwards it to the relevant FIP through Router. The FIP retrieves the requested data from its system.

***ReBIT API:*****&#x20;/FI/Request (POST) with 'x-request-meta' header**: The AA forwards the FI request to the FIP, including the consent artefact and data requirements.

#### **3. FIP Shares the Session Id with AA:**

Upon receiving the request and validating it against the consent artefact, the FIP provides a session Id to use as reference to fetch the data once it is ready.

#### **4. FIP sends a Notification to AA&#x20;**<mark style="color:green;">**through Router**</mark>**:**

FIP asyncronously compose the requested FI data and sends a notification to AA about the readiness to trigger the FI fetch request to get the data.

***ReBIT API:*****&#x20;/FI/Notification (POST) with 'x-request-meta' header**: The FIP sends a notification to AA through Router once the FI data composed and available to fetch.

#### **5. AA Fetches FI data from FIP & Sends a Notification to FIU&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once the AA receives the notification from the FIP, it fetches the financial information from the FIP through Router. This data is provided in the agreed format and scope as per the consent.

Once the FI data is ready, AA sends a notification to FIU about the readiness of FI data to fetch by FIU from AA.

***ReBIT API:*****&#x20;/FI/fetch (POST) with 'x-request-meta' header**: The AA sends a FI fetch request to FIP through Router to receive the FI data for the specific Session Id.

***ReBIT API:*****&#x20;/FI/Notification (POST) with 'x-request-meta' header**: The AA sends a notification to FIU through Router once the FI data available to fetch.

#### **4. AA Delivers Data to FIU&#x20;**<mark style="color:green;">**through Router**</mark>**:**

Once the AA receives the data from the FIP, it delivers the financial information to the FIU. This data is provided in the agreed format and scope as per the consent.

***ReBIT API:*****&#x20;/FI/fetch (POST) with 'x-request-meta' header**: The AA delivers the financial information to the FIU through Router based on the initial request.

#### **5. FI Request Completion:**

After the FIU receives the data, the FI request workflow is marked as complete. The FIU can now process the data in line with the consent provided by the user.


# Integration with Simulators

## Overview

SahamatiNet has developed Response **Simulators** for each type of entity in the AA ecosystem. These simulators replicate the behaviour of AA, FIU, or FIP while interacting with ReBIT APIs for Router integration, enabling seamless testing and validation.

By mimicking real Entity Protocol APIs, the **Response Simulator provides a controlled environment where developers can test the router service** independently without relying on a live entity.

The sample workflow diagram below illustrates the usage of the Response Simulator by including a simulated response with the expected response.

<figure><img src="/files/pOueLGo6jwe7Du8gDGz6" alt=""><figcaption><p>Entity Integration with Router using "Response Simulator"</p></figcaption></figure>

The following two details are required in the request to use the APIs with Response **Simulator**:

* **recipient-id:** This is specified in the **x-request-meta** header through which the router that will route the request to the respective response simulator.&#x20;
  * Based on the respective use case you can use the following Entity ID as `recipient-id`, which are mapped to the respective Response Simulators in Sandbox environment,
    * **AA-SIMULATOR**
    * **FIU-SIMULATOR** and
    * **FIP-SIMULATOR**
* **x-simulate-res:** This header should contain a hint for the expected response from the response simulator. It can be any of the options listed in the specific entity tables. If this is not included, the response simulator will default to returning a 200 OK response.

#### Sample Request Headers:

<pre class="language-javascript"><code class="lang-javascript">x-request-meta: [Base64 of {"recipient-id": "AA-SIMULATOR"}]
<strong>x-simulate-res: DataGone
</strong></code></pre>

## OTP Scenario:

The **FIP's Accounts/link/verify** API is the only one that utilizes the OTP received from the customer. This API is responsible for submitting the token/OTP back to the FIP to complete the account linkage process. The Response Simulator is set up to accept a predefined list of OTPs for successful account linkage. If an OTP outside of this list is used, the account linkage will fail. This is the default behavior of the Response Simulator, functioning without the need for the **x-simulate-res** header.

#### List of OTPs accepted by Response Simulator

<table data-header-hidden data-full-width="false"><thead><tr><th width="103"></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>1234</td><td>123456</td><td>654321</td><td>999999</td><td>223344</td><td>567890</td><td>456789</td><td>234567</td><td>345678</td><td>555444</td><td>222333</td></tr></tbody></table>

The sample workflow diagram below illustrates the usage of the valid OTP &#x20;

<figure><img src="/files/OJijhZBfBmI6eJOsMY4B" alt=""><figcaption></figcaption></figure>

The sample workflow diagram below illustrates the usage of the invalid OTP&#x20;

<figure><img src="/files/I53R2CHIyXWYyroDhloH" alt=""><figcaption></figcaption></figure>


# AA Simulator

## AA - Response Simulator:

This AA response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/AA_2_1_0.yaml>

<table><thead><tr><th width="110">API</th><th width="262">Expected Response</th><th>x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>FI/fetch</td><td><p>403 Forbidden</p><p>(DataFetchRequestInProgress)</p></td><td>Forbidden</td></tr><tr><td>FI/fetch</td><td>410 Data Gone</td><td>DataGone</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

Sample FI/fetch workflow using AA-SIMULATOR:

<figure><img src="/files/1V85rd7lKcE1OVAyln3p" alt=""><figcaption></figcaption></figure>

#### Preloaded Scenarios

The AA Response Simulator (AA-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the AA Simulator.

| API Requests               | Scenario Id                             | Details                                  |
| -------------------------- | --------------------------------------- | ---------------------------------------- |
| /Consent                   | ConsentDeposit\_Success                 | Successful consent request               |
| /Consent/handle            | ConsentHandleDeposit\_Approved          | Consent response with status as Approved |
| /Consent/handle            | ConsentHandleDeposit\_Ready             | Consent response with status as Ready    |
| /Consent/handle            | ConsentHandleDeposit\_Rejected          | Consent response with status as Rejected |
| /Consent/handle            | ConsentHandleDeposit\_Expired           | Consent response with status as Expired  |
| /Consent/handle            | ConsentHandleDeposit\_Failed            | Consent response with status as Failed   |
| /Consent/handle            | ConsentHandleDeposit\_Pending           | Consent response with status as Pending  |
| /Consent/fetch             | ConsentFetchDeposit\_Active             | Consent fetch with status as Active      |
| /Consent/fetch             | ConsentFetchDeposit\_Paused             | Consent fetch with status as Paused      |
| /Consent/fetch             | ConsentFetchDeposit\_Revoked            | Consent fetch with status as Revoked     |
| /Consent/fetch             | ConsentFetchDeposit\_Expired            | Consent fetch with status as Expired     |
| /FI/request                | FIRequestDeposit\_Success               | Successful FI request                    |
| /FI/request                | FIRequestDeposit\_Expired               | FI request with expired consent          |
| /FI/fetch                  | FIFetchDeposit\_Success\_1              | Successful FI fetch from Bank 1          |
| /FI/fetch                  | FIFetchDeposit\_Success\_2              | Successful FI fetch from Bank 2          |
| /Consent/Notification      | ConsentNotificationDeposit\_Success     | Successful consent notification          |
| /FI/Notification           | FINotificationDeposit\_Success          | Successful FI notification               |
| /Account/link/Notification | AccountLinkNotificationDeposit\_Success | Successful Account Link notification     |


# FIP Simulator

### FIP Response Simulator:

This FIP response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/FIP_2_1_0.yaml>

<table><thead><tr><th>API</th><th>Expected Response</th><th width="340">x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>FI/fetch</td><td><p>403 Forbidden</p><p>(DataFetchRequestInProgress)</p></td><td>Forbidden</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

#### Preloaded Scenarios

The FIP Response Simulator (FIP-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the FIP Simulator.

| API Requests          | Scenario Id                         | Details                                                                  |
| --------------------- | ----------------------------------- | ------------------------------------------------------------------------ |
| /Accounts/discover    | DiscoveryFlowDeposit\_Success       | Successful account discovery                                             |
| /Accounts/discover    | DiscoveryFlowDeposit\_NotFoundMatch | Not found any accounts                                                   |
| /Accounts/discover    | DiscoveryFlowDeposit\_Multiple      | <p>Successful account discovery with 2 accounts<br>- Bank 1 & Bank 2</p> |
| /Accounts/link        | LinkFlowDeposit\_Success\_1         | Successful account link for Bank 1                                       |
| /Accounts/link        | LinkFlowDeposit\_Success\_2         | Successful account link for Bank 2                                       |
| /Accounts/delink      | DeLinkFlowDeposit\_Success\_1       | Successful account de-link for Bank 1                                    |
| /Accounts/delink      | DeLinkFlowDeposit\_Success\_2       | Successful account de-link for Bank 2                                    |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_Success\_1   | Successful account verification for Bank 1                               |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_Success\_2   | Successful account verification for Bank 1                               |
| /Accounts/link/verify | LinkVerifyFlowDeposit\_InvalidOTP   | Invalid OTP for account verification                                     |
| /Consent              | ConsentDeposit\_Success             | Successful consent response                                              |
| /FI/request           | FIRequestDeposit\_Success           | Successful FI request                                                    |
| /FI/request           | FIRequestDeposit\_Expired           | FI request with expired consent                                          |
| /FI/fetch             | FIFetchDeposit\_Success\_1          | Successful FI fetch from Bank 1                                          |
| /FI/fetch             | FIFetchDeposit\_Success\_2          | Successful FI fetch from Bank 2                                          |
| /Consent/Notification | ConsentNotificationDeposit\_Success | Successful consent notification                                          |


# FIU Simulator

### FIU Response Simulator

This FIU response simulator will support all the APIs listed under this ReBIT Spec - <https://api.rebit.org.in/viewSpec/FIU_2_0_0.yaml>

<table><thead><tr><th width="145">API</th><th width="176">Expected Response</th><th width="354">x-simulate-res Header Options</th></tr></thead><tbody><tr><td>All</td><td>200 OK</td><td>Ok</td></tr><tr><td>All</td><td>400 Bad Request</td><td>BadRequest</td></tr><tr><td>All</td><td>401 Unauthorized Access</td><td>Unauthorized</td></tr><tr><td>All</td><td>404 Not Found</td><td>NotFound</td></tr><tr><td>All</td><td>409 Conflict</td><td>Conflict</td></tr><tr><td>All</td><td>412 Precondition failed</td><td>PreconditionFail</td></tr><tr><td>All</td><td>501 Not Implemented</td><td>NotImplemented</td></tr><tr><td>All</td><td>503 Service Unavailable</td><td>ServiceUnavailable</td></tr><tr><td>All</td><td><p>Timeout Scenario</p><p>(delay in sending response)</p></td><td>TimeOut</td></tr></tbody></table>

#### Preloaded Scenarios

The FIU Response Simulator (FIU-SIMULATOR) includes preloaded scenarios that can be accessed by sending the corresponding scenario ID in the **x-scenario-id** header. The table below lists the scenarios available from the FIU Simulator.

| API Requests          | Scenario Id                         | Details                         |
| --------------------- | ----------------------------------- | ------------------------------- |
| /Consent/Notification | ConsentNotificationDeposit\_Success | Successful consent notification |
| /FI/Notification      | FINotificationDeposit\_Success      | Successful FI notification      |


# Validation of Integration

For the MVP integration, there are two key validation steps to be completed:

1. **Validation with Simulators**: The first step involves validating your Application/APIs with the respective simulators based on your Entity Type. If you are an FIU, you will test the integration with the AA Simulator. If you are an AA, you will validate with both the FIU and FIP Simulators. If you are an FIP, you will validate with the AA Simulator. This ensures that all APIs are functioning correctly and the response codes align with the ReBIT Specification Response Codes.
2. **Validation with REs:** The second step occurs once other respective REs (Registered Entities) have onboarded and completed their validation with the simulators. You will then test your integration with these REs to ensure that your application works seamlessly with other participants in the ecosystem.

The Sahamati team will share the list of test cases for API testing based on the ReBIT specification. We will collaborate with you to evolve these test cases throughout the MVP, refining and improving them to ensure they comprehensively cover all aspects of the integration and make the process more streamlined and effective.

In both of these validation steps, you are required to share the results with the Sahamati team as evidence to confirm that the integration meets the necessary standards.

More details on these validations will be provided as we progress through the MVP.


# Release Calendar

## AA Ecosystem Release Calendar by Sahamati

The Release Calendar outlines the updates and improvements introduced by Sahamati in the common services provided to the Account Aggregator (AA) ecosystem. It highlights key feature deployments and their scheduled timelines for both UAT and Production environments, enabling participants to stay aligned with regulatory and ecosystem-related enhancements. By adhering to the deployment dates, participants can seamlessly integrate these updates into their own release cycles, ensuring they stay up to date with the evolving changes.

**2024 - Q4**

<table data-full-width="true"><thead><tr><th width="204">Release Item</th><th>Description</th><th>Details</th></tr></thead><tbody><tr><td><strong>Customisable Client Secret Expiry Duration</strong></td><td>Ecosystem members can specify the expiry duration for secrets' rotation within regulator-defined boundaries.</td><td>Members can set expiry duration value via the API request, with a default value of 180 days or a customised value using the <strong><code>secretExpiryDays</code></strong> parameter defined by the entity itself.</td></tr><tr><td><strong>Grace Period for Expired Secrets</strong></td><td>A grace period allows access token generation with expired secrets, accompanied by a warning.</td><td>Tokens can still be generated during the 5-day grace period after expiry, with a warning that the secret has expired.</td></tr><tr><td><strong>Error Reduction in Automated Secret Reset</strong></td><td>Changes to reduce errors in the automated secret reset process, even if environment configurations change.</td><td>Reduces errors during the secret reset process, ensuring compatibility with updated expiry durations or other configuration changes.</td></tr><tr><td><strong>Human Readable Expiry Date Format</strong></td><td>The expiry date is now visible in a human-readable ISO format.</td><td>The expiry date is now provided in the response attribute <strong><code>expirationDate</code></strong> along with <code>expiresOn</code> in the secret API, formatted in an easily readable ISO format.</td></tr></tbody></table>

For detailed information on the API changes, do refer to the API documentation [link here](https://developer.sahamati.org.in/technical-specifications/identity-and-access-management#member-secret-management-apis)

**2024 - Q3**

<table><thead><tr><th width="415">Description</th><th width="147">UAT Status</th><th width="186">Production Status</th></tr></thead><tbody><tr><td><a href="/pages/BUAwhIkWGEAQHx3mNQZ4">Deprecation of V1 API Endpoint URLs in Base URL of Entities in Central Registry</a> </td><td>Deployed<br>(August 2024)</td><td>Deployed<br>(Oct 2024)</td></tr><tr><td><a href="/pages/LczVYLYb1bRJhJ6DGtvm">Client Secret Rotation for Participants in Token Service (Identity &#x26; Access Management)</a></td><td>Deployed<br>(August 2024)</td><td>Deployed<br>(Oct 2024)</td></tr><tr><td><a href="/pages/v4RgNGx78AUrfoBJPnCQ">Deactivation of deprecated V1 APIs of Central Registry</a></td><td>Deployed<br>(July 2024)</td><td>Deployed<br>(Oct 2024)</td></tr></tbody></table>

**Update on Client Secret Rotation:**

Based on the UAT feedback regarding client secret rotation, we will be updating the validity period for newly generated tokens to 180 days. As a result, the planned deployment, **originally scheduled for 3rd October 2024, has been deployed on 16th October 2024**, following the next round of UAT.

The next release will also include changes that allow entities to parameterise and configure the expiry period themselves, based on their respective regulatory guidelines.


# Deprecation of V1 API Endpoint URLs

This is to inform all participants of the Account Aggregator (AA) ecosystem about the deprecation of the ReBIT API V1 in the Central Registry and the necessary steps for transitioning to the V2 API.

### Key Updates:

* **Deprecation of ReBIT API V1:**\
  As per the notification from ReBIT on 12th May 2024, the ReBIT V1 API has been officially deprecated. All ecosystem participants, including FIPs, FIUs, and AAs, must complete their transition to the ReBIT V2 API by 30th June 2024.
* **For Participants Using V1:**\
  You are required to update your API Endpoint URLs to V2 in the Central Registry. Please share your V2 endpoint details with the Sahamati Services team.
* **For Participants Supporting Both V1 and V2:**\
  To ensure a smooth transition, it is recommended to deprecate the V1 endpoint URL by updating it to **/v1/nonexistent-resource** in the Central Registry. This will signal to users that the V1 endpoint is no longer valid, ensuring they switch to V2 seamlessly.
* **Best Practices:**\
  As a best practice, participants should refresh the Entities Endpoint URL from the Central Registry daily. This ensures that any updates made by other participants transitioning to V2 are reflected in your system, helping avoid miscommunication or errors.

### Implementation Timelines:

* The ReBIT V1 API deadline has already passed. Participants must ensure that their V1 API Base URLs are updated in the Central Registry to V2 to avoid disruptions.

### Action Required:

* **Update your Base URLs**\
  Please reach out to **<services@sahamati.org.in>** to update your application Endpoint Base URLs from V1 to V2 in the Central Registry.


# Client Secret Rotation

This is to inform all participants in the Account Aggregator (AA) ecosystem about the new Client Secret Rotation policy, following the recommendations from market participants.

### Key Updates

* **Best Practice Recommendation:**\
  Following feedback from market participants, it was recommended that the Client Secret Token used for authentication of Token Service should be rotated periodically to enhance security and mitigate risks related to token misuse or compromise.
* **Current Observations:**\
  A substantial number of participants have not rotated the Client Secret provided during their initial onboarding with the Central Registry (CR). To address this, Sahamati is introducing a Client Secret Rotation feature that enables participants to rotate their secrets efficiently and securely.
* **Designated Authorised Users:**\
  Each participant organisation must designate an authorised user who will be responsible for managing the Client Secret rotation. This user will be onboarded into the **Token Service (Identity & Access Management)** and tasked with rotating the secret using new APIs. The SPOC (Single Point of Contact) must also ensure that the newly generated secret token is securely integrated into their organisation's systems. It is recommended to use a **service account email** associated with the **participant organisation.** This ensures the account remains under the organisation's control for long-term management, providing consistency and seamless operation over time.
* **Secret Token Expiration:**\
  Moving forward, Client Secret Tokens set by Entities will expire every 180 days. All participants are required to rotate their Client Secrets before the expiration date to ensure uninterrupted access to the network. This regular rotation is essential to maintaining the security of the AA ecosystem.

### Implementation Timelines

* **UAT Environment:**\
  The Client Secret Rotation feature is now live in the UAT environment, allowing participants to begin testing the process immediately.
* **Production Environment:**\
  The feature is now available in the Production environment post deployment on 16th October 2024.

### Action Required

1. **Onboard Your Designated User:**\
   Each participant must onboard a designated user to the Central Registry, ensuring they are responsible for secret rotations. You can share the designated user's details, along with your current entity information in the Central Registry, with **<services@sahamati.org.in>**.
2. **Generate and Rotate Client Secrets:**\
   Once the designated user is onboarded by Sahamati, they will receive an email to set a password. Using this email and the newly set password, the designated user can generate a user token for the **Token Service (IAM)** through [User Token Generate API](https://developer.sahamati.org.in/technical-specifications/identity-and-access-management#user-token-generate). They can retrieve the existing secret using the[ Secret - Read API ](https://developer.sahamati.org.in/technical-specifications/identity-and-access-management#entity-secret-read)and reset it using the [Secret - Reset API](https://developer.sahamati.org.in/technical-specifications/identity-and-access-management#entity-secret-reset) to generate a new client secret. The new secret should be rotated into your application. Please refer to the [API documentation](https://developer.sahamati.org.in/technical-specifications/identity-and-access-management) for further details.
3. **Update Systems for Token Expiration:**\
   Ensure that your systems and applications are prepared to handle the periodic 180-day token expiration. Implement a token rotation mechanism using the new APIs to automate this process.
4. **Manual Rotation Option:**\
   If automation is not yet ready, you can still rotate the token manually by directly calling Sahamati’s API.

Please ensure these changes are incorporated into your applications and processes by the given deadlines to maintain uninterrupted access to the AA ecosystem.

**Update on Client Secret Rotation:**

Based on feedback from UAT on client secret rotation, we have extended the validity period for newly generated tokens to **180 days**. Consequently, the deployment, initially scheduled for 3rd October 2024, was completed on **16th October 2024**.

Please note that there will be **NO automatic expiration** of existing secret tokens in the Central Registry. Entities must **initiate and set** the expiration themselves, using the process outlined above.

In the upcoming release, entities will also be able to **parameterise and configure** the expiry period of their secrets, in line with their specific regulatory guidelines.


# Deactivation of Deprecated V1 APIs

As part of Sahamati’s ongoing enhancements, the Central Registry APIs have transitioned to Version 2 (V2), following the ReBIT V2 standard. The V2 APIs upgrades done in Jan 2024 are aimed to improve the discovery of entities and streamline the retrieval of endpoints and certificates.

&#x20;The v1 APIs of Central Registry had been deprecated since Jan 2024.

### Key Update:

* **Transition to V2 APIs:**\
  While most ecosystem participants have successfully migrated to the V2 APIs of Central Registry, some are still using the now deprecated V1 APIs. To enforce this transition, V1 APIs are scheduled for decommissioning with this release.&#x20;
* **Impact on V1 API Users:**\
  Starting from the decommissioning date, any requests made to the deprecated V1 APIs will return a 410 HTTP Status Code, indicating that the requested resource is no longer available and that users must switch to the V2 endpoint.

### Implementation Timelines:

* **UAT Environment:**\
  These changes have already been deployed in the UAT environment.
* **Production Environment:**\
  The decommissioning will take effect in the Production environment post deployment in October 2024.

### Action Required:

* **For Participants Still Using V1 APIs:**\
  If you are among the participants still using the V1 API to access the Central Registry, you need to transition to the V2 APIs of Central Registry immediately.\
  Any attempt to use the V1 version after decommissioning will result in a 410 HTTP response code.
* **Update your application** accordingly to ensure compatibility with the V2 APIs.


# Onboarding to Saans

Saans stands for “Swasthya of AA Network as a Service”.

This AA API health dashboard service aims to provide a transparent view into the real-time health of “Live” AA APIs offered by each network participant.

#### How does Saans v1.0.0 work? <a href="#h-how-does-saans-v1-0-0-work" id="h-how-does-saans-v1-0-0-work"></a>

Saans is based on AAs streaming real-time statistically-derived health metrics of each FIP to a central time-series database managed by Sahamati, for the community.

Each AA computes these real-time metrics by summarising individual request-response health signals, typically over a duration of 10 minutes, and then applying appropriate statistical measures on the aggregate (such as percentile functions).

Saans collects such statistical measures from each live AA. It then further applies a statistical interpretation across all the health signals thus collected, to provide an “aggregated” view of the health of each API.

#### Does Saans provide an AA-wise view of the health measured? <a href="#h-does-saans-provide-an-aa-wise-view-of-the-health-measured" id="h-does-saans-provide-an-aa-wise-view-of-the-health-measured"></a>

No. Saans aggregates health signals from all the AAs into a common database. It then treats each signal received as equally representative of an FIP’s health. A statistical measure is applied across all the signals collected over time. There is no way to filter signals by AA once it is aggregated into the common database.

We have no reason to believe that an FIP’s health will show up as significantly different between one AA and the other – given the standard protocol followed in the AA specs for AA-FIP integration.

#### Does Saans collect counts of transactions or individual transaction details from AAs?

No. Saans only collects summaries of health metrics from AAs, by design. It does not collect counts or individual transaction details from AAs.

#### What are the health metrics that Saans v1.0.0 collects and presents? <a href="#h-what-are-the-health-metrics-that-saans-v1-0-0-collects-and-presents" id="h-what-are-the-health-metrics-that-saans-v1-0-0-collects-and-presents"></a>

In the first version of Saans (v1.0.0), it offers a transparent view of the health of each FIP’s APIs’ health, plotted as two dashboards.

#### **What are the metrics covered under AA SLAs?**

Draft [AA SLAs v0.9.1](https://sahamati.org.in/wp-content/uploads/2023/06/AA-Ecosystem-SLAs_-Version-0.9.1-draft-07-04-23.pdf) can be found here for all AA network participants.

#### What are the APIs hosted by the FIPs? <a href="#h-what-are-the-apis-hosted-by-the-fips" id="h-what-are-the-apis-hosted-by-the-fips"></a>

FIPs host the following APIs, and Saans provides the performance indicators for these APIs:

* Consent Post Response: Used by AAs to send a copy of signed consent to the FIP
* FI Fetch Response: Used by AA to receive the encrypted data from the FIP
* FI Request Response: Used by the AA to request the encrypted FI Data
* User Confirm LInking Response: Used by AAs to submit the linking OTPs the customer received from the FIP
* User Discovery Response: AAs pass the identifier and FIP returns the list of masked account numbers
* User Linking Response: This is used by AAs to communicate with the FIP about the intent of the customer to link their account.
* User UnLinking Response: Used by AAs to notify the FIP about the act of delinking of accounts of the customer


# Publish Data to Sahamati

How is data to be created by the AA:

AAs are expected to report two forms of data called events:

* Each synchronous API call such as FIP Discovery, FIP Linking, FI request etc. are to be reported every 10 min. .
* Async functions such as FI notifications for FIPs are to be reported every 10 mins

Each report is referred to as signals. Signals contain multiple events- Sync API call data aggregated every 10 mins for each FIP.

For Sync API:

**NOTE**: If there are no events that take place in the 10 min duration for an API , do not send a signal. It can be completely omitted. Do not send 0 or any value other than null if you do not have the data. Sending 0 will skew the charts.

**Base URL**

```
https://api.sahamati.org.in/saans/v1/push
```

**Error Codes**

| Type             | Status    | Action                      |
| ---------------- | --------- | --------------------------- |
| Authentication   | 401       | Refresh token               |
| Validation       | 400       | Fix request payload         |
| External Service | 400 / 500 | Retry / Disable integration |
| Internal Error   | 500       | Restart service             |

<br>


# Push metric

### Input Parameters

| Parameter                                                                | Description                                                                                                                                                                                                   |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| aa\_id                                                                   | entity ID (Same as CR entry)                                                                                                                                                                                  |
| timestamp                                                                | The date and time when the events occurred. The format must follow ISO 8601 (YYYY-MM-DDTHH:MM:SS.mmmZ).                                                                                                       |
| headers                                                                  | The headers of the events data.                                                                                                                                                                               |
| events                                                                   | <p>FIP:AA:UserDiscoveryResponse - User account discover API call                                                                                                                                              |
| <br>FIP:AA:UserLinkingResponse - Account linking API call                |                                                                                                                                                                                                               |
| <br>FIP:AA:UserConfirmLinkingResponse - Confirm Account linking API call |                                                                                                                                                                                                               |
| <br>FIP:AA:ConsentPostResponse - Consent creation API call               |                                                                                                                                                                                                               |
| <br>FIP:AA:FIRequestResponse - FI data request creation API call         |                                                                                                                                                                                                               |
| <br>FIP:AA:FIFetchResponse - Get FI data API call                        |                                                                                                                                                                                                               |
| <br>FIP:AA:UserUnLinkingResponse - User unlinking API call</p>           |                                                                                                                                                                                                               |
| fip\_id                                                                  | The unique identifier for the financial information provider (FIP) that generated the event.                                                                                                                  |
| latency\_avg\_ms                                                         | The average latency for the event, in milliseconds.                                                                                                                                                           |
| success\_percent                                                         | The percentage of successful API calls made in that 10 min time period. Exclude 4xx errors from the total number of API calls when reporting.                                                                 |
| timeout\_percent                                                         | The percentage of API Calls that take longer than 30 seconds to respond.                                                                                                                                      |
| notfound\_percent                                                        | The percentage of events that resulted in a "not found" error. This will be passed ONLY for the discover API. Percent of 404 status codes. For the rest of the events it should be ‘null’                     |
| server\_error\_percent                                                   | The percentage of events that resulted in a server error.                                                                                                                                                     |
| client\_error\_percent                                                   | The percentage of events that resulted in a client error. Exclude 404 error for discover API event (since 404 is being counted as notfound\_percent)                                                          |
| latencyP99\_ms                                                           | Lets say the AA made 100 calls to an FIP in the past 10 mins. Arrange the response times for these calls in ascending order and share the 99th percentile response time(i.e. 99th response time in this case) |
| latencyP95\_ms                                                           | Lets say the AA made 100 calls to an FIP in the past 10 mins. Arrange the response times for these calls in ascending order and share the 95th percentile response time(i.e. 95th response time in this case) |
| latencyP50\_ms                                                           | Lets say the AA made 100 calls to an FIP in the past 10 mins. Arrange the response times for these calls in ascending order and share the 50th percentile response time(i.e. 50thresponse time in this case)  |


# Push notification metric

For FI notifications,

The event is setup with the name: FIP:AA:FINotificationResponse

Default to null wherever the metric is not applicable.

### Input Parameters

| Parameter                  | Description                                                                                                                                                                                                                                                                 |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| aa\_id                     | entity ID (Same as CR entry)                                                                                                                                                                                                                                                |
| timestamp                  | The date and time when the events occurred. The format must follow ISO 8601 (YYYY-MM-DDTHH:MM:SS.mmmZ).                                                                                                                                                                     |
| headers                    | The headers of the events data.                                                                                                                                                                                                                                             |
| fip\_id                    | The unique identifier for the financial information provider (FIP) that generated the event.                                                                                                                                                                                |
| notification\_event\_name  | The name of the notification event.: FIP:AA:FINotificationResponse                                                                                                                                                                                                          |
| success\_response\_percent | The percentage of FI Request calls for which the FI Notification is received and FI Status is marked as Ready. That is, total number of success notifications by total number of notifications received in the last 10 min.                                                 |
| failure\_response\_percent | The percentage of FI Request calls for which the FI Notification is received and FI Status is marked as DENIED or TIMEOUT. That is, total number of failure notifications by total number of notifications received in the last 10 min.                                     |
| no\_response\_percent      | The percentage of FI Request calls for which the FI Notification is not received. That is, total number of notifications received per FIP by total number of data requests created per FIP. NOTE: This metric is sent only once in 24hrs at midnight. It is null otherwise. |
| latency\_avg\_ms           | Average time taken between receiving 200 OK and FI Notification across all transactions                                                                                                                                                                                     |
| latencyP99\_ms             | 99th percentile of time taken between 200 OK and FI Notification, calculated from all values recorded in the time window.                                                                                                                                                   |
| latencyP95\_ms             | 95th percentile of time taken between 200 OK and FI Notification, calculated from all values recorded in the time window                                                                                                                                                    |
| latencyP50\_ms             | 50th percentile of time taken between 200 OK and FI Notification, calculated from all values recorded in the time window.                                                                                                                                                   |

Note: Latency should be calculated using the FI Notification in which all associated FIStatus entries have reached terminal states (**READY**, **DENIED**, or **TIMEOUT**), while excluding notifications that contain accounts still in transient states such as **DELIVERED** or **PENDING**.


# Access Aggregated Data from Sahamati

## FIP Health API V1.0.0

### Introduction

FIUs want to access SAANS Data during their user journeys. This allows them to manage the user expectations and Lending FIUgate the user through the AA flow depending upon the health status of the APIs. This could lead to a higher success percentage by only raising a consent request when the likelihood of the consent's success is much higher.

### Target Users

* FIUs
* AA Client apps
* FIP Health monitoring systems
* Real-time alert systems - both central and FIP specific

### How the solution works

The solution requires a system that can identify FIUs that have subscribed to the service. These FIUs will expose endpoints that receive data from the API on a 30 min frequency. This data will be calculated based on the performance of FIP over the last 30 min. The data will be pushed to the exposed endpoint.

### API Broad Specs

API Specs: [View Specs](https://github.com/Sahamati/FIP-Health-API-Specs/blob/main/Health%20API%20Specs.json)

Sample JSON: [View Sample](https://github.com/Sahamati/FIP-Health-API-Specs/blob/main/Sample%20response.json)

SLAs: [View SLAs](https://docs.google.com/spreadsheets/d/1T4qzwGPfqCxM-910HTZDkkikEezxUrU1/edit?usp=sharing\&ouid=102688648237312172000\&rtpof=true\&sd=true)

\
**Status Criteria**&#x20;

The status value is derived from two metrics, Success % and P50 Latency, using the following logic:

| Status   | Condition                                                       |
| -------- | --------------------------------------------------------------- |
| `GOOD`   | `Success %` **> 95%** AND `P50 Latency` **< 5000 ms**           |
| `BAD`    | `Success %`**≤ 95%** OR `P50 Latency`**≥ 5000 ms**              |
| `UNSURE` | No data available or metrics are incomplete for the time window |


# How to access the SAANS API

1. **Create a public endpoint:** Set up an endpoint to receive notifications from the SAANS Health API service as per the specs mentioned below.
2. **Whitelist IPs on your Firewall:** Whitelist the following IP addresses on your Firewall:
   * "20.204.209.246"
   * "13.71.48.89"
3. **Authenticate the Request:** To further authenticate the request from the SAANS health API:
   * The API sends an `Authorization` header in the request with a bearer token.
   * Validate the token with the Sahamati token service’s public certificate. The validation works same way as the signing of the API request body in the AA Specs
   * Refer to [this guide](https://github.com/Sahamati/FIP-Health-API-Specs/blob/main/Release%20Note.md#link-to-validation-guide) for instructions on validating JWT with a public key.
4. **Fill in the Form:** Complete the information in the following form: [Form Link](https://forms.gle/F3fhxHzQzeEZUKBx6)
5. After filling the form send email to <memberservices@sahamati.org.in>
6. **Deploy on your endpoint:** You will start receiving notifications on your configured endpoint on a T+1 basis.


# Glossary

**Member / Entity**

* **Definition**: Refers to a Financial Information User (FIU), Financial Information Provider (FIP), or Account Aggregator (AA) within the Account Aggregator ecosystem and Sahamati Network.


# Guidelines

* [Security Standards](https://sahamati.gitbook.io/security-standards/layered-security)
* [AA Redirection Guidelines](https://sahamati.gitbook.io/aa-redirection-guidelines)
* [AA Common Service](https://sahamati.gitbook.io/aa-common-service)


# Frequently Asked Questions

This FAQ section summarises the key aspects of the SahamatiNet Router and its integration process in a clear, concise manner.

## SahamatiNet Router Overview

**Q. What is the SahamatiNet Router, and what role does it play in the AA ecosystem?**

* The SahamatiNet Router is a network service that streamlines and secures interactions between Financial Information Providers (FIPs), Account Aggregators (AAs), and Financial Information Users (FIUs). It simplifies communication by reducing integration complexity, ensuring interoperability, and enabling secure data exchange.

**Q. How does the SahamatiNet Router enhance integration and collaboration within the AA Ecosystem?**

* The Router provides a standardised network interface, eliminating the need for multiple custom integrations. It handles backend tasks like traffic routing and load balancing, simplifying data exchange and promoting better collaboration among participants in the AA ecosystem.

**Q. How does the Router handle scalability as the AA ecosystem grows?**

* The Router is designed for scalability and can manage increased traffic and participants as the ecosystem expands. It supports horizontal scaling, multiple availability zones, and multi-region cloud deployments, ensuring high performance and availability.

**Q. How does observability in the SahamatiNet Router benefit participants?**

* The Router offers real-time observability, allowing participants to monitor API call frequency, response times, and error rates. This enables optimised system performance, easier issue diagnosis, and improved operational efficiency.

## Integration Process and Onboarding

**Q. Is the additional onboarding process for FIUs, AAs, and FIPs still required by the AA Ecosystem application when integrating with the SahamatiNet Router?**

* Once onboarded to the SahamatiNet Router, there is no additional onboarding required for FIUs, AAs, or FIPs in their respective applications. All participants will have already undergone the necessary compliance and validation through SahamatiNet, ensuring this step is covered for all entities. This process aligns with current participant interactions.

**Q. Will this change impact the integration process?**

* Yes, this change simplifies the integration process by eliminating the need for extra code or configuration for additional onboarding in your application. It enhances the ease of connection and overall efficiency across the AA ecosystem.

## Technical Aspects

**Q. Are there any data size limits or timeout considerations?**

* Yes, there are defined data size limits and timeout rules outlined in the integration guidelines. These values will be finalised and standardised during the Proof Of Concept (POC), with a consensus process involving all participants.

**Q. What about the delay in using the integration?**

* The integration is designed to be sub-second, ensuring minimal delay. The Router ensures fast, efficient communication between entities, facilitating seamless interactions.

## Testing and Compliance

**Q. Is integration with SahamatiNet mandatory?**

* No, integrating with SahamatiNet via the Router is not mandatory for participating in the AA ecosystem. However, integration simplifies interactions and ensures secure, standardised, and efficient communication between REs (Registered Entities).
* For example, if an AA gets onboarded to SahamatiNet, it gets access to all the onboarded FIPs without having to integrate individually with each FIP. Similarly, when an FIU gets onboarded to SahamatiNet, technically, it has access to all AAs who are onboarded. AA will still need the bilateral commercial agreement with the FIUs.

**Q. What is the purpose of the SahamatiNet Router sandbox environment?**

* The sandbox environment allows participants to test integrations in a risk-free setting that mimics real-world conditions. For the Proof of Concept (POC), the SahamatiNet Sandbox is used for validation and troubleshooting before transitioning to UAT and production environments.
* **Note:** The Sandbox environment is independent of the UAT and Production environments of SahamatiNet.

## Base URLs for Each Environment

| **Environment** | **Base URL**                          |
| --------------- | ------------------------------------- |
| **Sandbox**     | <https://api.sandbox.sahamati.org.in> |
| **UAT**         | <https://api.uat.sahamati.org.in>     |
| **Production**  | <https://api.sahamati.org.in>         |


# How To Guides

This section offers simple instructions for performing essential tasks within the Sahamati ecosystem. These guides aim to help participants easily navigate and complete key technical processes

* [How To Onboard to Sandbox ? ](/how-to-guides/how-to-onboard-to-sandbox)
* [How To Decide on an Entity ID ?](/how-to-guides/do-not-use-old-format-how-to-decide-on-an-entity-id)
* [How To Create a Certificate ? ](/how-to-guides/how-to-generate-a-certificate)
* [How To Generate Tokens ?](/how-to-guides/how-to-generate-tokens)


# How To Onboard to Sandbox ?

**Steps for Onboarding to SahamatiNet Router in Sandbox:**&#x20;

**1. What You Need to Provide:**

* **Organisation Details**: For onboarding your organisation as an Entity (FIP, AA, or FIU) in the Central Registry.
  * **Entity ID** for your organisation
  * **Base URL** Endpoint to your application
  * **RSA Public Key**
  * **IP Address**, **inbound and outbound ports** \[optional for UAT, required for Production environment for whitelisting]
* **Designated User**: Provide required contact details of a representative responsible for generating and managing the client secret key for your entity in IAM(Token Service).
  * Name, Email address of the designated email account from your organisation.
  * &#x20;It is recommended to use a **service account email** associated with the **participant organisation.** This ensures the account remains under the organisation's control for long-term management, providing consistency and seamless operation over time.

**2. Where to Find Onboarding Details:**

* Full onboarding instructions and required JSON details can be found[ here](/sahamatinet-poc/integration-steps/sandbox-onboarding).

**3. Submission Process:**

* For regulated entities in AA ecosystem, do send the required details to **<sandbox@sahamati.org.in>.**
* The Sahamati team will review your submission and provide access credentials to your designated user via an email.&#x20;
* Do note, this step will be moved to a registration page on a self service portal for SahamatiNet Router going forward.&#x20;

**4. Client Secret Token Generation:**

* Once the designated user is onboarded by Sahamati, they will receive an email to set a password.
* Using this email and the newly set password, the designated user can:
  * Generate a user token for the Token Service (IAM) through the [User Token Generate API](/sahamatinet-poc/integration-steps/iam-apis#user-token-generate).
  * Reset the secret using the [Secret - Reset API](/sahamatinet-poc/integration-steps/iam-apis#entity-secret-reset) to generate a new client secret.
  * Retrieve the existing entity secret using the [Secret - Read API](/sahamatinet-poc/integration-steps/iam-apis#entity-secret-read).
  * Using this entity secret, you can [Generate the Entity Secret](/sahamatinet-poc/integration-steps/iam-apis#entity-token-generate).&#x20;

Refer to the [API documentation](/sahamatinet-poc/integration-steps/iam-apis) for more details.


# \[Do Not Use - Old Format] - How To Decide on an Entity ID ?

Note: This page is outdated. Please refer to the new Entity ID Naming Convention https\://membersuccess.sahamati.org.in/member-services/cr-pre-onboarding-guide/entity-id-naming-convention

**How To create or decide on an Entity ID value in the onboarding request ?**

* An **Entity ID** is a unique identifier that represents a specific entity such as an FIU (Financial Information User), AA (Account Aggregator), or FIP (Financial Information Provider). It should follow a clear, readable naming convention that helps identify the entity.
* Best practice for naming Entity IDs:\
  Use a suffix-based naming convention like:
  * **For FIUs: XYZ\_FIU**
  * **For AAs: ABC\_AA**
  * **For FIPs: AXBYCZ\_FIP**
* For Lower environments you can even add the environment name as well&#x20;
  * **For FIU : XYZ\_UAT\_FIU or XYX\_SANDBOX\_FIU**
  * **For AA : ABC\_UAT\_AA or ABC\_SANDBOX\_AA**
  * **For FIP : AXBYCZ\_UAT\_FIP or AXBYCZ\_SANDBOX\_FIP**
* Ensure that the Entity ID is a unique and easily recognisable name of the organisation that is getting onboarded. It can include letters, numbers, or symbols, but a simple and meaningful string is recommended.
* **Do note,** the above examples and recommendations **use an underscore** ( \_ ) as the **delimiter**. You **can also use hyphens** ( - ) if preferred.


# How To Generate a Certificate ?

**How to create a certificate using**[ **https://mkjwk.org/**](https://mkjwk.org/)

To generate a certificate, follow these steps:

* **Go to**[ **https://mkjwk.org/**](https://mkjwk.org/)
* **Select the required fields:**
  * **Key Use** (**use**): Choose sig (for signature).
  * **Algorithm** (**alg**): Select RS256 (RSA Signature with SHA-256).
  * **Key ID** (**kid**): This is a unique identifier for the key. You can enter any random string or a specific identifier that you would like to use.
  * **Key Type** (**kty**): RSA is recommended, so ensure RSA is selected.
  * **Modulus** (**n**): This will be automatically generated when you create the key.
  * **Exponent** (**e**): This will also be generated automatically.
* **Generate the Key Pair:**
  * Click the “**Generate**” button to create your public and private key pair. Make sure to save both the public and private keys securely as the private key will be required later for signing requests.
* **Validate the certificate**: Ensure the generated certificate contains the following properties:
  * **kty**: Key Type (e.g., RSA)
  * **e**: Exponent (e.g., AQAB)
  * **use**: Key Use (e.g., sig)
  * **kid**: Key ID (your unique key identifier)
  * **alg**: Algorithm (e.g., RS256)
  * **n**: Modulus (the base64 encoded string representing the modulus of the RSA key)

Example **json** output:

```
{
  "kty": "RSA",
  "e": "AQAB",
  "use": "sig",
  "kid": "<your-key-id>",
  "alg": "RS256",
  "n": "<your-modulus>"
}
```

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXepNbN8q89iGGbWnOQ38HCWdzAwIGEyz4rCiCK_J6kN_-YBpb48RDNSwCyygiMvok0NC7nKU9RkT0AnMPQR-4bHTBNA5v_iH4TqtVu-R5yrEJhKG6VuLX43gsy6A-UyoT-KZ1Q1AW5sB92UuD0btnH4lpnq?key=oovCSK4Ia9I56Bv9KLxKzQ" alt=""><figcaption></figcaption></figure>

Screenshot for your reference


# How To Generate Tokens ?

**How to generate and validate tokens using APIs (using curl)**

To generate and validate access tokens from Sahamati, here are sample curl commands for User Token and Entity Token APIs. It is recommended to use Postman for quicker and more efficient testing. However, the following curl commands are helpful for direct implementation within code.

**User Access Token API:**\
This API generates a token for a user (email/password-based authentication). To generate a User Access Token, the user must provide their username (email) and the password configured during the account activation process. **This access token is necessary for interacting with the member's secret management APIs**. The access token has an expiry of 24 hrs.

Example curl &#x20;

```
curl -X 'POST' \
  'https://api.sandbox.sahamati.org.in/iam/v1/user/token/generate' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=<your-email>&password=<your-password>
```

**Entity Access Token API**:\
This API generates a token for an entity based on its ID and secret. The generation of a Member (Entity) Access Token requires the ID (client ID) and the Secret. **This access token is used for the interaction with other members**. The access token has an expiry of 24 hrs.

Example curl

```
curl -X 'POST' \
  'https://api.sandbox.sahamati.org.in/iam/v1/entity/token/generate' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'id=<entityId>&secret=<entitySecret>'
```

Ensure you replace `<your-email>`, `<your-password>`, `<entityId>`, and `<entitySecret>` mentioned in above curl with actual values when running these commands.

**Postman Collection**:\
You can also download the [**Postman collection**](/sahamatinet-poc/integration-steps/iam-apis#api-postman-collection) from the Sahamati developer portal. The Postman collection includes pre-configured API requests and is ideal for rapid testing and validation of token generation.


# How to Rotate Entity Secret

This is to inform all participants in the Account Aggregator (AA) ecosystem about the Client Secret Rotation policy that has been in existence since October 2024. The participants are mandated to implement this policy.

### Key Updates

* **Best Practice Recommendation:**\
  Following feedback from market participants, it was recommended that the Client Secret used for authentication on Token Service should be rotated periodically to enhance security and mitigate risks related to token misuse or compromise.
* **Current Observations:**\
  A substantial number of participants have not rotated the Client Secret provided during their initial onboarding with the Central Registry (CR). To address this, Sahamati provides a Client Secret Rotation feature that enables participants to rotate their secrets efficiently and securely.
* **Designated Authorised Users:**\
  Each participant organisation must designate an authorised user who will be responsible for managing the Client Secret rotation. This user will be onboarded into the **Token Service (Identity & Access Management)** and tasked with rotating the secret using APIs. The SPOC (Single Point of Contact) must also ensure that the newly generated secret token is securely integrated into their organisation's systems. It is recommended to use a **service account email** associated with the **participant organisation.** This ensures the account remains under the organisation's control for long-term management, providing consistency and seamless operation over time.
* **Secret Token Expiration:**\
  Client Secrets set by entities will expire every 180 days. All participants are required to rotate their Client Secrets before the expiration date to ensure uninterrupted access to the network. This regular rotation is essential to maintaining the security of the AA ecosystem.

### <mark style="color:$success;">Do I need to rotate my secret?</mark>

1. Before proceeding with the rotation steps, please verify whether your Entity Secret requires rotation.
2. You can log in to the [Check Secret Status](https://data.sahamati.org.in/self-service/check-secret-status) page using your Entity ID and Entity Secret to check the current secret expiry date.
3. If your secret is nearing expiry or has expired, you should proceed with rotating the secret.
4. If rotation is required, follow the steps below to rotate the secret either through the API method or through the Portal.

### Action Required

1. **Onboard Your Designated User:**\
   The "AA program SPOC" of your entity will be the "designated user" to rotate the secret. In case you want to update the SPOC, please reach out to **<memberservices@sahamati.org.in>**.

   Once the designated user is onboarded by Sahamati, they will receive an email to set a password.

2. **Generate and Rotate Entity Secrets:**

{% hint style="info" %}
**Important Note:** Before proceeding with the secret reset, ensure that your technical team is informed and prepared to update and start using the new secret in the system immediately after rotation.
{% endhint %}

### Rotating the Secret

There are two methods to rotate the secret. One is via the web portal (Method 1), and the other is using the API (Method 2).

#### Method 1: Rotate Secret Using the Portal

You can also rotate the entity secret directly through the portal.

1. Visit the Sahamati [Self Service Portal](https://data.sahamati.org.in/self-service/welcome)
2. Click on Login to Self Service Portal.&#x20;
3. Enter your Entity ID.
4. Enter the SPOC Email ID registered with the entity.
5. Enter the OTP received on the SPOC email ID.
6. Enter the SPOC Password to log in to the portal.

After logging in, navigate to the "**Reset Secret**" section and proceed with the Secret Rotation. Once the secret is rotated, copy the new secret from the “**View Secret**” section after the reset. Share the new secret with your technical team to update it in your system configuration.

#### Method 2: Rotate Secret Using API

{% hint style="info" %}
**Important Note:** The APIs referred below must be accessed from your entity's network IPs registered with Sahamati.&#x20;
{% endhint %}

1. **Step-1**: Generate a User-Token

   Use the email and the newly set password to generate a user token from the Token Service through the [User Token Generate API](https://developer.sahamati.org.in/how-to-guides/token-service-apis-production#post-user-token-generate).&#x20;
2. **Step-2**: Read existing secret (if needed)

   Use the user-token to read the secret of your entity using the [Secret - Read API ](https://developer.sahamati.org.in/how-to-guides/token-service-apis-production#post-entity-secret-read)
3. **Step-3**: Reset the entity secret

   Use the user-token to reset the secret of your entity using the [Secret - Reset API](https://developer.sahamati.org.in/how-to-guides/token-service-apis-production#post-entity-secret-reset).&#x20;
4. **Step-4**: The new secret should be applied to your system. Please refer to the [API documentation](https://developer.sahamati.org.in/how-to-guides/token-service-apis-production) for further details.
5. **Update Systems for Token Expiration:**\
   Ensure that your systems and applications are prepared to handle the periodic 24-hour token expiration. Implement a token rotation mechanism using the [Entity Token Generation API](https://developer.sahamati.org.in/how-to-guides/token-service-apis-production#post-entity-token-generate) to automate this process.
6. **Manual Rotation Option:**\
   If automation is not yet ready, you can still rotate the token manually by directly calling Sahamati’s API.

Please ensure these changes are incorporated into your applications and processes by the given deadlines to maintain uninterrupted access to the AA ecosystem.


# Token Service APIs - Production

Identity and Access Management ( Token Service) APIs

Each member of the Sahamati Network will be onboarded with a designated user who holds an admin role to manage the entity’s profile and secret.

* During the onboarding process, the designated user will receive an email containing a verification link. After email verification, **the user will be prompted to set a password**, completing the account activation process.
* Once the password is set, **the user can generate the User Access Token** by providing their email and the new password. This token is used for authenticating the entity’s secrets.
* The designated user can then use the User Access Token to **access the entity’s secret** and, if necessary, **reset the secret**.
* Finally, the entity secret is used to **generate the Entity Access Token**, which is needed for interactions with the ReBIT APIs within the AA network.

### Entity Token Generation use case&#x20;

The Regulated Entities (REs) should generate the Access Token using the Token API from Sahamati for accessing and authentication of any APIs in the AA ecosystem including Sahamati APIs.

Here is the sequence diagram for the Token Generation Process.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdc4HeMCiC89Fdmj_Xf0Nv3AZZKB6BuqMxBUGRt41o73HkYfBchfZOQ9S_a5dg6nK32KXqo44LBDV1AhjU_IyorOrAk0PFyphQuHLr0k3ilJwrjo2xbHH6XFFhwJB0hZWZuW62-0Q?key=3aTz-3SKYP0rOCX7DFnLglx6" alt=""><figcaption><p>Token Generation use case diagram</p></figcaption></figure>

Below are the Base URL of each environment to use IAM APIs.

<table><thead><tr><th width="213.489501953125">Environment</th><th>Base URL</th></tr></thead><tbody><tr><td>Production</td><td>https://api.sahamati.org.in/iam</td></tr></tbody></table>

Please note that the following documentation displays the Base URLs from the Production environment. Ensure you use the appropriate Base URLs depending on the environment you are working in.

## Generate User Access Token API

> To generate a User Access Token, the user must provide their username (email) and the password configured during the account activation process. This access token is necessary for interacting with the member's secret management APIs. The access token has an expiry of 180 days. Below is the API specification.<br>

```json
{"openapi":"3.0.0","info":{"title":"Token Service APIs","version":"2.1.0"},"tags":[{"name":"User APIs"}],"servers":[{"url":"https://api.sahamati.org.in/iam/v1"}],"paths":{"/user/token/generate":{"post":{"tags":["User APIs"],"summary":"Generate User Access Token API","description":"To generate a User Access Token, the user must provide their username (email) and the password configured during the account activation process. This access token is necessary for interacting with the member's secret management APIs. The access token has an expiry of 180 days. Below is the API specification.\n","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"User email."},"password":{"type":"string","description":"The password associated with the user."}},"required":["username","password"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}}}}}},"components":{"schemas":{"TokenResponse":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"accessToken":{"type":"string"},"expiresIn":{"type":"integer"},"tokenType":{"type":"string"}}}}}}
```

## Read Secret API

> The Read Secret API enables admin to retrieve the current secret for a specific member. To access this information, a user access token with administrative rights must be provided. Below is the API specification.<br>

```json
{"openapi":"3.0.0","info":{"title":"Token Service APIs","version":"2.1.0"},"tags":[{"name":"Entity APIs"}],"servers":[{"url":"https://api.sahamati.org.in/iam/v1"}],"paths":{"/entity/secret/read":{"post":{"tags":["Entity APIs"],"summary":"Read Secret API","description":"The Read Secret API enables admin to retrieve the current secret for a specific member. To access this information, a user access token with administrative rights must be provided. Below is the API specification.\n","parameters":[{"name":"Authorization","in":"header","required":true,"description":"User Bearer token for authorization","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitySecretReadRequest"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitySecretReadResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}}}}}},"components":{"schemas":{"EntitySecretReadRequest":{"type":"object","required":["entityId"],"properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"entityId":{"type":"string"}}},"EntitySecretReadResponse":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"entityId":{"type":"string"},"secret":{"type":"string"},"expiresOn":{"type":"number"},"expirationDate":{"type":"string"},"oldSecretValidity":{"type":"number"},"oldSecretExpirationDate":{"type":"string"}}}}}}
```

## Reset Secret API

> The Reset Secret API is used to reset the entity’s secret.  To perform this action, a user access token with administrative privileges must be provided.  Once reset, the generated secret will have a validity period (default and max value of 180 days) as specified in the request payload.  The SPOC will have to ensure that it is renewed well before the expiry.\
> An entity’s secret can be reset up to 5 times per day. There will be a waiting period of 5 mins applied after each reset API call.\
> Below is the API specification.<br>

```json
{"openapi":"3.0.0","info":{"title":"Token Service APIs","version":"2.1.0"},"tags":[{"name":"Entity APIs"}],"servers":[{"url":"https://api.sahamati.org.in/iam/v1"}],"paths":{"/entity/secret/reset":{"post":{"tags":["Entity APIs"],"summary":"Reset Secret API","description":"The Reset Secret API is used to reset the entity’s secret.  To perform this action, a user access token with administrative privileges must be provided.  Once reset, the generated secret will have a validity period (default and max value of 180 days) as specified in the request payload.  The SPOC will have to ensure that it is renewed well before the expiry.\nAn entity’s secret can be reset up to 5 times per day. There will be a waiting period of 5 mins applied after each reset API call.\nBelow is the API specification.\n","parameters":[{"name":"Authorization","in":"header","required":true,"description":"User Bearer token for authorization","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitySecretResetRequest"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitySecretResetResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}}}}}},"components":{"schemas":{"EntitySecretResetRequest":{"type":"object","required":["entityId"],"properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"entityId":{"type":"string"},"secretExpiryDays":{"type":"integer","description":"Specifies the number of days before the secret expires. This field is optional; if not provided, a default value will be used."},"oldSecretValidity":{"type":"integer","description":"Specifies the number of days (a max of 7) for which the previous secret remains valid.  The old and new secret, both, can be used to generate token during this period.  This field is optional. If not provided or set to 0, the old secret will be invalidated immediately.   We advise the REs to use this judiciously."}}},"EntitySecretResetResponse":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"entityId":{"type":"string"},"secret":{"type":"string"},"expiresOn":{"type":"number"},"expirationDate":{"type":"string"},"oldSecretValidity":{"type":"number"}}}}}}
```

## Generate Entity Access Token API

> To generate a Member (Entity) Access Token, the client ID and Secret are required. The API generates the token with a warning if the secret is within the grace period, but it will fail once the grace period has ended. This token is used for interactions with other members and has a validity of 24 hours. The API specification is detailed below.<br>

```json
{"openapi":"3.0.0","info":{"title":"Token Service APIs","version":"2.1.0"},"tags":[{"name":"Entity APIs"}],"servers":[{"url":"https://api.sahamati.org.in/iam/v1"}],"paths":{"/entity/token/generate":{"post":{"tags":["Entity APIs"],"summary":"Generate Entity Access Token API","description":"To generate a Member (Entity) Access Token, the client ID and Secret are required. The API generates the token with a warning if the secret is within the grace period, but it will fail once the grace period has ended. This token is used for interactions with other members and has a validity of 24 hours. The API specification is detailed below.\n","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The entity ID."},"secret":{"type":"string","description":"The secret associated with the entity."}},"required":["id","secret"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"errorCode":{"type":"string"},"errorMsg":{"type":"string"}}}}}}}}}},"components":{"schemas":{"TokenResponse":{"type":"object","properties":{"ver":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"txnId":{"type":"string"},"accessToken":{"type":"string"},"expiresIn":{"type":"integer"},"tokenType":{"type":"string"}}}}}}
```

## Token Generation APIs:

#### API Postman Collection:&#x20;

{% hint style="info" %}
We recommend you to use below postman collection to try out our Token-Service\[IAM] APIs
{% endhint %}

{% file src="/files/LrPZkvetWRM9Un9XGz41" %}

## Member Secret Management APIs

#### API Collection:

{% file src="/files/nymDUvFE3Ay3pAtIgcs4" %}
Token-Service\[IAM] - API Collection
{% endfile %}


# Central Registry JSON Template

## CR Entity Registration

**API Parameter Reference · FIP / FIU / AA**

This document describes every parameter in the Central Registry entity registration JSON payload. Fields marked **Required** must be present for all entity types. Fields marked **FIP only** / **AA only** apply exclusively to that entity type. Fields marked **Ignore** are reserved for future use.

### Root-Level Parameters

<table><thead><tr><th width="152.111083984375">Field / Parameter</th><th width="132.111083984375">Type</th><th>Required</th><th>Description</th><th>Example Value</th></tr></thead><tbody><tr><td><code>ver</code></td><td>String</td><td><strong>Required</strong></td><td>Version of the API/schema being used.</td><td><code>2.0</code></td></tr><tr><td><code>timestamp</code></td><td>String (ISO 8601)</td><td><strong>Required</strong></td><td>UTC timestamp of the request in ISO 8601 format.</td><td><code>2026-03-18T08:04:50.314Z</code></td></tr><tr><td><code>txnid</code></td><td>String (UUID)</td><td><strong>Required</strong></td><td>Unique transaction ID for tracking this request.</td><td><code>407a70dd-88dd-423d-97a6-edbc0d0694da</code></td></tr><tr><td><code>type</code></td><td>String (Enum)</td><td><strong>Required</strong></td><td>Entity type being registered. One of: <code>FIP</code>, <code>FIU</code>, <code>AA</code>.</td><td><code>FIU</code></td></tr></tbody></table>

### `requester` — Identifies the party submitting the request

<table><thead><tr><th width="151.66668701171875">Field / Parameter</th><th width="104.5555419921875">Type</th><th width="122.666748046875">Required</th><th>Description</th><th>Example Value</th></tr></thead><tbody><tr><td><code>requester.name</code></td><td>String</td><td><strong>Required</strong></td><td>Display name of the entity submitting the request.</td><td><code>Sahamati FIU Test</code></td></tr><tr><td><code>requester.id</code></td><td>String</td><td><strong>Required</strong></td><td>Unique ID of the requesting entity as registered in the CR.</td><td><code>sahamati-fiu-test-new</code></td></tr></tbody></table>

### `entityinfo` — Core entity registration details

<table><thead><tr><th width="149">Field / Parameter</th><th width="105.44439697265625">Type</th><th width="131.111083984375">Required</th><th width="202.3333740234375">Description</th><th>Example Value</th></tr></thead><tbody><tr><td><code>entityinfo.tags</code></td><td>String</td><td>Optional</td><td>Environment tag for the entity (e.g. <code>Sandbox</code>, <code>Production</code>).</td><td><code>Sandbox</code></td></tr><tr><td><code>entityinfo.name</code></td><td>String</td><td><strong>Required</strong></td><td>Name of the entity as submitted while listing itself in the CR. <br>Note: <strong>Ensure this matches exactly as mentioned in your Certificate of Registration (CoR) issued by your regulator</strong>.</td><td><code>Sahamati Foundation</code></td></tr><tr><td><code>entityinfo.id</code></td><td>String</td><td><strong>Required</strong></td><td>Unique ID issued by the CR to the entity.<br>Note: <strong>Please refer to</strong> <a href="https://membersuccess.sahamati.org.in/member-services/cr-pre-onboarding-guide/entity-id-naming-convention"><strong>this page</strong></a> <strong>for your Entity ID naming convention.</strong></td><td><code>sahamati-fiu-test-new</code></td></tr><tr><td><code>entityinfo.code</code></td><td>String</td><td><strong>Required</strong></td><td>ID issued by the financial sector regulator governing this entity.<br>Note: <strong>Ensure this matches exactly as mentioned in your Certificate of Registration (CoR) issued by your regulator.</strong></td><td></td></tr><tr><td><code>entityinfo.entityhandle</code></td><td>String</td><td>AA only</td><td>Handle suffix for user profiles managed by the AA (e.g. <code>@aa</code>). Leave blank for FIU/FIP.</td><td></td></tr></tbody></table>

### `entityinfo.Identifiers` — Account discovery identifiers

*(FIP only; present here for schema completeness)*

| Field / Parameter        | Type          | Required | Description                                                                                   | Example Value |
| ------------------------ | ------------- | -------- | --------------------------------------------------------------------------------------------- | ------------- |
| `Identifiers[].category` | String (Enum) | FIP only | Category of identifier accepted for account discovery. Values: `STRONG`, `WEAK`, `ANCILLARY`. | `STRONG`      |
| `Identifiers[].type`     | String (Enum) | FIP only | Type of identifier (e.g. `MOBILE`, `PAN`, `DOB`). At least one must be `STRONG`.              | `MOBILE`      |

### `entityinfo` — Connectivity & Endpoints

| Field / Parameter          | Type           | Required     | Description                                                                                                            | Example Value                                       |
| -------------------------- | -------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `entityinfo.baseurl`       | String (URL)   | **Required** | URL hosting all ReBIT-compliant API endpoints. Prefix with version e.g. `v2:` for versioned URLs.                      | `v2:https://data.sahamati.com/fiu/sahamati-test/v2` |
| `entityinfo.webviewurl`    | String (URL)   | AA only      | URL of the AA web app for FIUs to redirect users to. `null` for FIU/FIP.                                               | `null`                                              |
| `entityinfo.fitypes`       | Array\<String> | FIP only     | Financial information types from the ReBIT master list that the entity supports. Present here for schema completeness. | `DEPOSIT, MUTUAL_FUNDS, EQUITIES...`                |
| `entityinfo.inboundports`  | Array\<String> | **Required** | Ports on the entity that counterparties (AA/FIP/FIU) can connect to.                                                   | `["443"]`                                           |
| `entityinfo.outboundports` | Array\<String> | **Required** | Ports from which the entity will make outbound requests.                                                               | `["443"]`                                           |
| `entityinfo.ips`           | Array\<String> | **Required** | IP addresses counterparties may send and receive requests to/from.                                                     | `["13.127.138.226"]`                                |

### `entityinfo.certificate` — Public key in JSON Web Key (JWK) format

| Field / Parameter | Type   | Required     | Description                                              | Example Value                          |
| ----------------- | ------ | ------------ | -------------------------------------------------------- | -------------------------------------- |
| `certificate.alg` | String | **Required** | Algorithm used. Typically `RS256`.                       | `RS256`                                |
| `certificate.kty` | String | **Required** | Key type. Must be `RSA`.                                 | `RSA`                                  |
| `certificate.use` | String | **Required** | Intended use of the key. `sig` = signature verification. | `sig`                                  |
| `certificate.kid` | String | **Required** | Key ID — unique identifier for this key.                 | `ed9c4269-96de-4a62-b057-e2dd628d359c` |
| `certificate.e`   | String | **Required** | RSA public exponent (Base64url encoded).                 | `AQAB`                                 |
| `certificate.n`   | String | **Required** | RSA modulus — the public key value (Base64url encoded).  | `ngB4ScutfK6776QK...`                  |

### `entityinfo.gsp` — Gateway Service Provider

(Leave these Field/Parameter values as null — Reserved for future use)

| Field / Parameter | Type | Required | Description                                                                                    | Example Value |
| ----------------- | ---- | -------- | ---------------------------------------------------------------------------------------------- | ------------- |
| `gsp`             | null | null     | GSP details when a gateway sits between AAs and the FIP (e.g. GSTN). Set to `null` for FIU/AA. | `null`        |

### `entityinfo.tokeninfo` — Token issuance details

(Leave these Field/Parameter values as empty — Reserved for future use)

| Field / Parameter | Type         | Required   | Description                                                          | Example Value |
| ----------------- | ------------ | ---------- | -------------------------------------------------------------------- | ------------- |
| `tokeninfo.url`   | String (URL) | Keep Empty | URL of the entity's Token Issuance Service. Reserved for future use. | `""`          |
| `tokeninfo.desc`  | String       | Keep Empty | Description field. Reserved for future use.                          | `""`          |

### `entityinfo.signature` — Request signature

(Leave these Field/Parameter values as empty — Reserved for future use)

| Field / Parameter     | Type   | Required   | Description                                                              | Example Value |
| --------------------- | ------ | ---------- | ------------------------------------------------------------------------ | ------------- |
| `signature.signValue` | String | Keep Empty | Cryptographic signature of the request payload. Reserved for future use. | `""`          |

***

### Notes

* `baseurl` will be prefixed with a version tag (e.g. v2:https\://...) to indicate the supported API version.
* `certificate` fields follow the JSON Web Key (RFC 7517) specification.
* `tokeninfo` and `signature` fields are present in the schema but should be left empty / ignored until further notice.
* `gsp` must be set to `null` for FIU and AA entity types.
* `entityhandle` and `webviewurl` are AA-specific and should be omitted or set to null/blank for FIP and FIU.

### Template

> **Note**: The base JSON structure is identical for all RE types. The tabs below are provided for clarity — each view highlights the relevant fields and example values as applicable to that entity type (FIU, FIP, or AA).

{% tabs %}
{% tab title="FIU" %}

```json
{
  "ver": "1.0",
  "timestamp": "2026-03-18T08:04:50.314Z",
  "txnid": "407a70dd-88dd-423d-97a6-edbc0d0694da",
  "type": "FIU",
  "requester": {
    "name": "Sahamati FIU Test",
    "id": "sahamati-fiu-test-new"
  },
  "entityinfo": {
    "tags": "Sandbox",
    "name": "Sahamati FIU Test",
    "id": "sahamati-fiu-test-new",
    "code": "sahamati-fiu-test-new",
    "entityhandle": "",
    "Identifiers": [],
    "baseurl": "v2:https://data.sahamati.com/fiu/sahamati-test/v2",
    "webviewurl": null,
    "fitypes": [],
    "certificate": {
      "e": "AQAB",
      "n": "<RSA modulus here>",
      "alg": "RS256",
      "kid": "<key-id-uuid>",
      "kty": "RSA",
      "use": "sig"
    },
    "tokeninfo": {
      "url": "",
      "desc": ""
    },
    "gsp": null,
    "signature": {
      "signValue": ""
    },
    "inboundports": ["443"],
    "outboundports": ["443"],
    "ips": ["<ip-address>"]
  }
}

```

{% endtab %}

{% tab title="FIP" %}

<pre class="language-json"><code class="lang-json">{
  "ver": "1.0",
  "timestamp": "2026-03-18T08:04:50.314Z",
  "txnid": "407a70dd-88dd-423d-97a6-edbc0d0694da",
  "type": "FIP",
  "requester": {
    "name": "Sahamati FIP Test",
<strong>    "id": "sahamati-fip-test"
</strong>  },
  "entityinfo": {
    "tags": "Sandbox",
    "name": "Sahamati FIP Test",
    "id": "sahamati-fip-test",
    "code": "sahamati-fip-test",
    "entityhandle": "",
    "Identifiers": [
      { "category": "STRONG", "type": "MOBILE" },
      { "category": "STRONG", "type": "PAN" }
    ],
    "baseurl": "v2:https://data.sahamati.com/fip/sahamati-test/v2",
    "webviewurl": null,
    "fitypes": [
      "DEPOSIT", "TERM_DEPOSIT", "RECURRING_DEPOSIT", "SIP", "CP",
      "EQUITIES", "MUTUAL_FUNDS"
    ],
    "certificate": {
      "e": "AQAB",
      "n": "&#x3C;RSA modulus here>",
      "alg": "RS256",
      "kid": "&#x3C;key-id-uuid>",
      "kty": "RSA",
      "use": "sig"
    },
    "tokeninfo": {
      "url": "",
      "desc": ""
    },
    "gsp": null,
    "signature": {
      "signValue": ""
    },
    "inboundports": ["443"],
    "outboundports": ["443"],
    "ips": ["&#x3C;ip-address>"]
  }
}
</code></pre>

{% endtab %}

{% tab title="AA" %}

```json
{
  "ver": "1.0",
  "timestamp": "2026-03-18T08:04:50.314Z",
  "txnid": "407a70dd-88dd-423d-97a6-edbc0d0694da",
  "type": "AA",
  "requester": {
    "name": "Sahamati AA Test",
    "id": "sahamati-aa-test"
  },
  "entityinfo": {
    "tags": "Sandbox",
    "name": "Sahamati AA Test",
    "id": "sahamati-aa-test",
    "code": "sahamati-aa-test",
    "entityhandle": "@sahamati-aa-test",
    "Identifiers": [],
    "baseurl": "v2:https://data.sahamati.com/aa/sahamati-test/v2",
    "webviewurl": "https://webview.sahamati.com/aa/sahamati-test",
    "fitypes": [],
    "certificate": {
      "e": "AQAB",
      "n": "<RSA modulus here>",
      "alg": "RS256",
      "kid": "<key-id-uuid>",
      "kty": "RSA",
      "use": "sig"
    },
    "tokeninfo": {
      "url": "",
      "desc": ""
    },
    "gsp": null,
    "signature": {
      "signValue": ""
    },
    "inboundports": ["443"],
    "outboundports": ["443"],
    "ips": ["<ip-address>"]
  }
}

```

{% endtab %}
{% endtabs %}


# Overview

SahamatiNet Agent (SNA) is a lightweight, standalone agent developed by Sahamati and deployed within an Account Aggregator's (AA's) own infrastructure. SNA is responsible for aggregating and sending required metrics to Sahamati's endpoint on behalf of the AA, without requiring the AA's to write or maintain code that implements complex metric-capture logic.

### Key Capabilities

* Runs entirely within the AA's infrastructure; no data leaves unless pushed to Sahamati's endpoint.
* Captures request and notification metrics across all FIP-side AA APIs.
* Aggregates data and pushes structured JSON payloads to Sahamati every 10 minutes.
* Is versioned and upgradeable; AAs simply redeploy a new Helm chart version; no code changes needed.
* Provides uniform, schema-consistent data across all AAs for fair SLA benchmarking.

### Current Phase of Deployment

Sahamati is currently requesting all AAs to:

1. Deploy SNA to their UAT environment and validate the integration.
2. Deploy SNA to their Production environment once UAT validation is complete.
3. Integrate at the AA-FIP interface side (integration points A, B, C, D, see Section 4).

> 📌 For this phase, SLA and SaaNs data capture is required at the AA-FIP interface only.


# Why SNA?

Sahamati evaluated two options for how AAs should report SLA metrics. The following comparison, agreed upon with the AA community, guided the decision to build and distribute SNA:

| Option 1: AA Gathers & Reports Independently          | Option 2: AA Uses SNA (Recommended)              |
| ----------------------------------------------------- | ------------------------------------------------ |
| ✔ AA-controlled changes                               | ✔ Uniform interpretation across all AAs          |
| ✘ Interpretations may vary across AAs                 | ✔ Minimal integration effort for AAs             |
| ✘ Each AA must implement all reporting logic          | ✔ Future changes: redeploy SNA, no code changes  |
| ✘ Future schema changes require AA engineering effort | \~ AAs maintain one additional cluster component |

The SNA approach ensures that Sahamati can centrally update calculation logic, definitions, schema, and all AAs benefit immediately by simply deploying the new version of SNA.

This leads to:

* Faster ecosystem-level consistency
* Lower engineering burden on individual AAs.


# How SNA Works

SNA is deployed as a microservice within the AA's Kubernetes cluster. It receives API requests and response data from the AA's service, aggregates SLA metrics according to Sahamati's schema, and pushes aggregated JSON payloads to the Sahamati SLA endpoint every 10 minutes.

### High-Level Data Flow

The data flows through the following stages:

1. AA's service sends and receives API calls to/from FIPs and FIUs.
2. The AA service captures key metadata for every request and response at each integration point (A-H)
3. It sends this information to the SNA running in its cluster.
4. SNA aggregates the required metrics (counts, response times, percentiles, statuses) for each 10-minute window.
5. SNA pushes two JSON payloads to the Sahamati SLA endpoint every 10 minutes: one for Request metrics and one for Notification metrics.

### What SNA Aggregates

| Category             | Type             | Description                                                            |
| -------------------- | ---------------- | ---------------------------------------------------------------------- |
| Request Metrics      | Counts           | Total requests sent per API type, response code counts (2xx, 4xx, 5xx) |
| Request Metrics      | Response Times   | Percentiles (p50, p95, p99, p100) per API type in milliseconds         |
| Request Metrics      | Data Size        | Sum of FI/fetch encrypted data packet sizes                            |
| Notification Metrics | Counts           | Total notifications received per type (FI, Account Link, Consent)      |
| Notification Metrics | Status Breakdown | Ready, Delivered, Denied, Timeout, Pending count for FI notifications  |


# Integration Guide

This section covers everything you need to integrate your AA service with SNA — from understanding integration points to deploying the Helm chart and adding the snalib library to your service.

### In This Section

* **Integration Points** — understand the 8 integration points (A–H) and which ones are required for the current phase.
* **Step-by-Step Integration** — a guided walkthrough of all integration steps.
* **Deploying SNA** — how to deploy and upgrade SNA using the Helm chart.
* **SNA Library (snalib)** — how to add snalib to your AA service code.


# Integration Points

SNA defines 8 integration points, labeled A through H, corresponding to the 4 interface points: one on the AA-FIP side and one on the AA-FIU side of AA's service. Each point represents a direction of data flow that SNA monitors.

<figure><img src="/files/Y2f5E2IM6xAm5WDv0xZP" alt=""><figcaption></figcaption></figure>

### Integration Points Summary

| Point | Direction   | Side   | SLA        | SaaNs      | MIS        |
| ----- | ----------- | ------ | ---------- | ---------- | ---------- |
| A     | requestOut  | AA-FIP | ✔ Required | ✔ Required | ✔ Required |
| B     | responseIn  | AA-FIP | ✔ Required | ✔ Required | ✔ Required |
| C     | requestIn   | AA-FIP | ✔ Required | ✔ Required | ✔ Required |
| D     | responseOut | AA-FIP | ✔ Required | ✔ Required | ✔ Required |
| E     | requestOut  | AA-FIU |            |            | ✔ Required |
| F     | responseIn  | AA-FIU |            |            | ✔ Required |
| G     | requestIn   | AA-FIU |            |            | ✔ Required |
| H     | responseOut | AA-FIU |            |            | ✔ Required |

> 📌 For the current phase, AAs are required to integrate at points A, B, C, and D (AA-FIP side). Points E–H (AA-FIU side) will be required in later phases for MIS reporting.

### Integration Point Details (AA-FIP Side)

<table><thead><tr><th width="145.66668701171875">Point</th><th width="124">Direction</th><th>What to Capture</th></tr></thead><tbody><tr><td>A) requestOut</td><td>AA → FIP</td><td>Capture outgoing request data: API type, timestamp, target FIP ID, request size</td></tr><tr><td>B) responseIn</td><td>FIP → AA</td><td>Capture incoming response data: HTTP status code, response time (ms), response body size</td></tr><tr><td>C) requestIn</td><td>FIP → AA</td><td>Capture incoming FIP notifications: API type, timestamp, source FIP ID</td></tr><tr><td>D) responseOut</td><td>AA → FIP</td><td>Capture outgoing response data: HTTP status code, timestamp</td></tr></tbody></table>


# Step-by-Step Integration

Follow these steps to integrate your AA service with SNA. The integration is designed to be minimal.

The AA application communicates with SNA via HTTP APIs. Sahamati will share a library, snalib, that AAs can use to set up the interface with SNA and perform the API calls.

### Step 1: Deploy SNA to your cluster

Deploy the SNA Helm chart into your Kubernetes cluster. Refer to Deploying SNA for detailed deployment instructions.

### Step 2: Add snalib to your service

Include the snalib library in your AA service code. The library is available for Node, Go, and Java on Sahamati's GitHub. Refer to SNA Library (snalib) for integration steps.

### Step 3: Instrument your AA-FIP interface

#### Set up a connection with SNA

As part of the AA application initialization, call the snalib function to initialize the connection to SNA.

#### Push transaction metadata to SNA

Add snalib method calls at each of the 4 integration points (A, B, C, D) in your AA-FIP service logic:

* **Point A (requestOut):** Call snalib before sending a request to a FIP, with the required parameters.
* **Point B (responseIn):** Call snalib after receiving a response from a FIP, with the required parameters. Ensure that if a Point-A call was made to SNA, a call is made at Point-B. All cases, including client failures, server timeouts, and connection failures, need to be handled.
* **Point C (requestIn):** Call snalib when your AA service receives an incoming notification from a FIP, with the required parameters.
* **Point D (responseOut):** Call snalib after your AA service sends a response back to a FIP, with the required parameters.

> 📌 SNA is designed to be non-blocking and has minimal performance impact. All aggregation is done asynchronously inside the SNA agent. It is not done in your service.

### Step 4: Configure the SNA endpoint

Ensure your SNA deployment is configured with the correct Sahamati SLA endpoint (see Endpoints & Authentication).

### Step 5: Validate in UAT

Before deploying to Production, validate the integration in your UAT environment:

* Confirm that SNA is running and healthy in the cluster.
* Trigger a few AA-FIP API calls and verify that SNA is receiving the data.
* After 10 minutes, check with Sahamati's team to confirm that metric payloads are being received at the UAT endpoint.
* Review the response from the endpoint for any validation errors or warnings.

### Step 6: Deploy to Production

Once UAT validation is complete, deploy SNA to your Production cluster and point it at the Production SLA endpoint.


# Deploying SNA

SNA is distributed as a Helm chart and is designed to be deployed inside the AA's own Kubernetes cluster. The Helm chart, along with all downloadable resources, is available on GitHub.

### GitHub Repository

The SNA downloadables repository contains the Helm chart and the snalib distribution:

<https://github.com/Sahamati/sahamatinet-agent-downloadables>

### Helm Chart Deployment Steps

1. Download the contents from the repository: <https://github.com/Sahamati/sahamatinet-agent-downloadables.git>
2. Refer to the README.md file in the repository root for an overview.
3. Follow the instructions in the SETUP.md file for deployment of the container. This includes configuring the required settings and running the Helm charts.
4. After installation, test the ping API to confirm the SNA container is up and running.

### Upgrading SNA

When Sahamati releases a new version of SNA (e.g., to update schema definitions or metric logic), the upgrade process is straightforward:

1. Download the new Helm chart version from the GitHub repository.
2. Run a Helm upgrade command:


# SNA Library (snalib)

Sahamati provides sna libraries to reduce the integration effort with SNA. The snalib-dist directory in the GitHub repository can be used by your AA service to push the api transaction details to the SNA agent. Libraries for Node, Go and Java are available, along with example source code and a Java JAR.

### Steps to Integrate

1. Pull the latest main branch from the repository:

<https://github.com/Sahamati/sahamatinet-agent-downloadables>

2. Find the snalib source code, example source, and Java JAR under the following path in the repository:

sahamatinet-agent-downloadables/snalib-dist

3. Use the Go library source from snalib-dist/go/ or the Java library source and JAR from snalib-dist/java/, depending on your AA service stack.
4. Refer to the example source code in the repository to understand how to call the snalib methods at each of the 4 integration points (A–D) in your AA-FIP service handler code.

> 📌 SNA is designed to be non-blocking. Metric data is sent asynchronously to the SNA agent to avoid adding latency to your AA service's API response times.


# SLA

This section covers the SLA data that SNA captures and submits to Sahamati on behalf of the AA, including the API endpoints, payload schemas, and response codes.

### In This Section

* **SLA Overview** — what SLA data SNA captures and how it is reported.
* **Endpoints & Authentication** — the Sahamati SLA endpoint URLs and how authentication works.
* **SLA Request Payload** — schema reference for the request metrics payload.
* **SLA Notification Payload** — schema reference for the notification metrics payload.
* **Response Codes** — HTTP responses returned by the Sahamati SLA endpoint.


# API Reference

This section covers the Sahamati SLA endpoint that SNA pushes data to, including endpoint URLs, authentication, payload schemas, and response codes.

### In This Section

* **Endpoints & Authentication** — the Sahamati SLA endpoint URLs and how authentication works.
* **SLA Request Payload** — schema reference for the request metrics payload.
* **SLA Notification Payload** — schema reference for the notification metrics payload.
* **Response Codes** — HTTP responses returned by the Sahamati SLA endpoint.


# Endpoints & Authentication

SNA pushes data to a Sahamati-hosted HTTPS endpoint. Sahamati provides two variants of this endpoint, one for UAT (for testing your integration) and one for Production.

### SLA Push Endpoints

| Environment | Endpoint URL                                            |
| ----------- | ------------------------------------------------------- |
| Production  | <https://api.sahamati.org.in/sla-inputs/aa/v1/push>     |
| UAT         | <https://api.uat.sahamati.org.in/sla-inputs/aa/v1/push> |

### Authentication

The SLA push endpoint uses token-based authentication. The authentication token will be generated by SNA and stored securely. As part of the SNA deployments the admin will have to configure the entityId and the secret as a Kubernetes secret file for the SNA to generate the token. SNA handles the token injection into request headers automatically.

> 📌 Authentication credentials are issued per AA by Sahamati. Tokens must be stored securely in your cluster and must not be committed to version control.


# SLA Request Payload

SNA pushes a Request metrics payload to the Sahamati endpoint every 10 minutes. This payload captures all API calls sent by the AA to each FIP, including counts and response time percentiles. The tag for this payload is req-fipMetrics-aa.

### Schema Reference

| Field                                     | Type        | Description                                                                                            |
| ----------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------ |
| agentVersion                              | string      | Version of the SNA agent generating this payload                                                       |
| jsonVersion                               | string      | Version of the JSON schema (e.g. "1.0.0")                                                              |
| tag                                       | string      | "req-fipMetrics-aa" identifies this as a request-metrics payload from AA perspective of FIP            |
| txnId                                     | string      | Unique transaction ID for this push request                                                            |
| fromDateTime                              | string      | Start of the 10-minute reporting window (ISO 8601, UTC). E.g. 2023-11-08T15:30:00Z                     |
| toDateTime                                | string      | End of the 10-minute reporting window (ISO 8601, UTC). E.g. 2023-11-08T15:40:00Z                       |
| duration                                  | int         | Duration in seconds of the reporting window (600 for 10 minutes)                                       |
| aaId                                      | string      | Entity ID of the Account Aggregator                                                                    |
| fips\[].fipId                             | string      | Entity ID of the FIP for which metrics are reported in this block                                      |
| fips\[].metrics\[].type                   | string      | Metric type code (e.g. adisc, alink, adlink, alinkv, cns, cnot, fireq, sfireqnot, ffireqnot, fif, hbt) |
| fips\[].metrics\[].pxx                    | array\[int] | Response time percentiles in milliseconds: \[p50, p95, p99, p100]                                      |
| fips\[].metrics\[].counts                 | array\[int] | Count values aligned to countFields enum in the payload                                                |
| fips\[].metrics\[].sumOfSizeOfDataPackets | string      | Sum of encrypted FI/fetch packet sizes (only for type "fif")                                           |

### Metric Types (metricTypes enum)

| Code      | Full Name                                  | Description                                                                                              |
| --------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
| adisc     | accountsDiscoverSent\_adisc                | Account discovery requests sent to FIP (POST /Accounts/discover)                                         |
| alink     | accountsLinkSent\_alink                    | Account link requests sent (POST /Accounts/link)                                                         |
| adlink    | accountsDelinkSent\_adlink                 | Account delink requests sent (POST /Accounts/delink)                                                     |
| alinkv    | accountsLinkVerifySent\_alinkv             | Account link verification requests sent (POST /Accounts/link/verify)                                     |
| cns       | consentSent\_cns                           | Consent requests sent to FIP (POST /Consent)                                                             |
| cnot      | consentNotificationSent\_cnot              | Consent notification messages sent (POST /Consent/Notification)                                          |
| fireq     | fiReqSent\_fireq                           | FI requests sent (POST /FI/request)                                                                      |
| sfireqnot | fiReq200OkToFISuccNotifTimeDiff\_sfireqnot | Time difference from FI request 200 OK to success notification (at least one account READY or DELIVERED) |
| ffireqnot | fiReq200OkToFIFailNotifTimeDiff\_ffireqnot | Time difference from FI request 200 OK to failure notification (all accounts DENIED or TIMEOUT)          |
| fif       | fiFetchSent\_fif                           | FI fetch requests sent (POST /FI/Fetch)                                                                  |
| hbt       | heartBeatSent\_hbt                         | Heartbeat messages sent to check FIP connectivity (GET /Heartbeat)                                       |

### Count Fields (countFields enum)

The counts array in each metric entry is positionally aligned to the following fields in this exact order:

| Position | Field Name                    | Description                                                  |
| -------- | ----------------------------- | ------------------------------------------------------------ |
| 1        | totalSentCnt                  | Total number of requests sent                                |
| 2        | 200OKRecdCnt                  | HTTP 200 OK responses received                               |
| 3        | 400BadReqRecdCnt              | HTTP 400 Bad Request responses received                      |
| 4        | 401UnauthorizedReqRecdCnt     | HTTP 401 Unauthorized responses received                     |
| 5        | 403ForbiddenReqRecdCnt        | HTTP 403 Forbidden responses received                        |
| 6        | 404NotFoundRecdCnt            | HTTP 404 Not Found responses received                        |
| 7        | 409IdempotencyErrorReqRecdCnt | HTTP 409 Idempotency Error responses received                |
| 8        | 412Pre-ConditionFailedRecdCnt | HTTP 412 Precondition Failed responses received              |
| 9        | 429TooManyReqsRecdCnt         | HTTP 429 Too Many Requests (rate limited) responses received |
| 10       | 4xxOtherErrorsRecdCnt         | All other 4xx error responses received                       |
| 11       | 500InternalServerErrorRecdCnt | HTTP 500 Internal Server Error responses received            |
| 12       | 502BadGatewayRecdCnt          | HTTP 502 Bad Gateway responses received                      |
| 13       | 503ServiceUnavailableRecdCnt  | HTTP 503 Service Unavailable responses received              |
| 14       | 504GatewayTimeoutRecdCnt      | HTTP 504 Gateway Timeout responses received                  |
| 15       | 5xxOtherErrorsRecdCnt         | All other 5xx error responses received                       |


# SLA Notification Payload

SNA also pushes a Notification metrics payload to the Sahamati endpoint every 10 minutes. This payload captures incoming notification traffic from FIPs to the AA, including notification counts and FI notification status breakdowns. The tag for this payload is not-fipMetrics-aa.

### Schema Reference

<table><thead><tr><th width="166">Field</th><th width="141.666748046875">Type</th><th>Description</th></tr></thead><tbody><tr><td>agentVersion</td><td>string</td><td>Version of the SNA agent generating this payload</td></tr><tr><td>jsonVersion</td><td>string</td><td>Version of the JSON schema (e.g. "1.0.0")</td></tr><tr><td>tag</td><td>string</td><td>"not-fipMetrics-aa" identifies this as a notification-metrics payload from AA perspective of FIP</td></tr><tr><td>txnId</td><td>string</td><td>Unique transaction ID for this push request</td></tr><tr><td>fromDateTime</td><td>string</td><td>Start of the 10-minute reporting window (ISO 8601, UTC)</td></tr><tr><td>toDateTime</td><td>string</td><td>End of the 10-minute reporting window (ISO 8601, UTC)</td></tr><tr><td>duration</td><td>int</td><td>Duration in seconds of the reporting window (600 for 10 minutes)</td></tr><tr><td>aaId</td><td>string</td><td>Entity ID of the Account Aggregator</td></tr><tr><td>fips[].fipId</td><td>string</td><td>Entity ID of the FIP for which notification metrics are reported</td></tr><tr><td>fips[].metrics[].type</td><td>string</td><td>Metric type code: finot, alnot, or cnot</td></tr><tr><td>fips[].metrics[].counts</td><td>array[int]</td><td>Count values aligned to countFields enum in the notification payload</td></tr><tr><td>fips[].metrics[].status</td><td>array[int]</td><td>Status values (only for type "finot"): [succRecdCnt, failRecdCnt, readyRecdCnt, deniedRecdCnt, deliveredRecdCnt, timeoutRecdCnt, intermediateRecdCnt]</td></tr></tbody></table>

### Notification Metric Types

<table><thead><tr><th width="89.66668701171875">Code</th><th>Full Name</th><th>Description</th></tr></thead><tbody><tr><td>finot</td><td>fiNotificationRecd_finot</td><td>FI notifications received from FIP counts and status breakdown (READY, DELIVERED, DENIED, TIMEOUT, PENDING)</td></tr><tr><td>alnot</td><td>accountLinkNotificationRecd_alnot</td><td>Account link notifications received from FIP</td></tr><tr><td>cnot</td><td>consentNotificationRecd_cnot</td><td>Consent notifications received from FIP</td></tr></tbody></table>

### Notification Count Fields

The counts array is positionally aligned to these fields:

<table><thead><tr><th width="101.6666259765625">Position</th><th width="264.666748046875">Field Name</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>totalRecdCnt</td><td>Total notifications received. For FI notifications: count only the last /FI/Notification where all FIStatus states are terminal (READY, DELIVERED, DENIED, TIMEOUT).</td></tr><tr><td>2</td><td>200OKSentCnt</td><td>HTTP 200 OK responses sent back</td></tr><tr><td>3</td><td>400BadReqSentCnt</td><td>HTTP 400 Bad Request responses sent</td></tr><tr><td>4</td><td>401UnauthorizedReqSentCnt</td><td>HTTP 401 Unauthorized responses sent</td></tr><tr><td>5</td><td>403ForbiddenReqSentCnt</td><td>HTTP 403 Forbidden responses sent</td></tr><tr><td>6</td><td>404NotFoundSentCnt</td><td>HTTP 404 Not Found responses sent</td></tr><tr><td>7</td><td>409IdempotencyErrorReqSentCnt</td><td>HTTP 409 Idempotency Error responses sent</td></tr><tr><td>8</td><td>412PreConditionFailedSentCnt</td><td>HTTP 412 Precondition Failed responses sent</td></tr><tr><td>9</td><td>429TooManyReqsSentCnt</td><td>HTTP 429 Too Many Requests responses sent</td></tr><tr><td>10</td><td>4xxOtherErrorsSentCnt</td><td>All other 4xx error responses sent</td></tr><tr><td>11</td><td>500InternalServerErrorSentCnt</td><td>HTTP 500 Internal Server Error responses sent</td></tr><tr><td>12</td><td>502BadGatewaySentCnt</td><td>HTTP 502 Bad Gateway responses sent</td></tr><tr><td>13</td><td>503ServiceUnavailableSentCnt</td><td>HTTP 503 Service Unavailable responses sent</td></tr><tr><td>14</td><td>504GatewayTimeoutSentCnt</td><td>HTTP 504 Gateway Timeout responses sent</td></tr><tr><td>15</td><td>5xxOtherErrorsSentCnt</td><td>All other 5xx error responses sent</td></tr></tbody></table>

### FI Notification Status Fields

The status array is only present for the "finot" metric type and is positionally aligned to these fields:

| Position | Field Name          | Description                                                                                                      |
| -------- | ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 1        | succRecdCnt         | Notifications with at least one READY or DELIVERED state in final /FI/Notification                               |
| 2        | failRecdCnt         | Notifications where all accounts are DENIED or TIMEOUT (none READY or DELIVERED) does not include 4xx/5xx errors |
| 3        | readyRecdCnt        | Notifications with terminal state READY in final /FI/Notification                                                |
| 4        | deniedRecdCnt       | Notifications with terminal state DENIED in final /FI/Notification                                               |
| 5        | deliveredRecdCnt    | Notifications with terminal state DELIVERED in final /FI/Notification                                            |
| 6        | timeoutRecdCnt      | Notifications with terminal state TIMEOUT in final /FI/Notification                                              |
| 7        | intermediateRecdCnt | Notifications still in non-terminal state PENDING                                                                |

> 📌 Time difference between FIReq 200 OK and failure notification (Note: All accounts are marked as DENIED or TIMEOUT in the final /FI/Notification, i.e., none of the states are READY.)


# Response Codes

The Sahamati SLA endpoint returns the following HTTP responses for each push request made by SNA:

<table><thead><tr><th width="96.3333740234375">Code</th><th width="143.6666259765625">Status</th><th>Response Body</th></tr></thead><tbody><tr><td>200</td><td>OK</td><td>{ "success": true, "message": "Successfully pushed metric", "warning": "Agent upgrade available..." }</td></tr><tr><td>400</td><td>Bad Request</td><td>{ "errorCode": "Bad request", "errorMsg": "JSON validation failed" }</td></tr><tr><td>401</td><td>Unauthorized</td><td>{ "errorCode": "Unauthorized", "errorMsg": "Auth token is invalid/expired" }</td></tr><tr><td>404</td><td>Not Found</td><td>{ "errorCode": "Not Found", "errorMsg": "Agent version incompatible" }</td></tr><tr><td>500</td><td>Server Error</td><td>{ "errorCode": "Server Error", "errorMsg": "Internal Server Error" }</td></tr></tbody></table>


# GitHub Resources

All SNA resources are hosted in a single GitHub repository. This repository contains all the artifacts you need to deploy and integrate with SNA.

<table><thead><tr><th width="157.6666259765625">Resource</th><th width="288.6666259765625">Description</th><th>Location in Repo</th></tr></thead><tbody><tr><td>SNA Helm Chart</td><td>Kubernetes Helm chart for deploying SNA to your cluster</td><td>helmchart/</td></tr><tr><td>snalib Go</td><td>Go client library for integrating your AA service with SNA</td><td>snalib-dist/go/</td></tr><tr><td>snalib Java</td><td>Java client library for integrating your AA service with SNA</td><td>snalib-dist/java/</td></tr><tr><td>snalib Node</td><td>Node client library for integrating your AA service with SNA</td><td>snalib-dist/node/</td></tr><tr><td>README</td><td>Overview, setup, and quick-start guide</td><td>README.md</td></tr></tbody></table>

### Repository Link

<https://github.com/Sahamati/sahamatinet-agent-downloadables>

### Access

If you are an AA and want to get access to the repository, send an email to <jithesh.kumar@sahamati.org.in>


# FAQ & Troubleshooting

**Q: Does SNA send any raw API request or response data to Sahamati?**

No. SNA sends only aggregated metric counts and percentile values. No FI payload data, consent data, customer PII, or raw request/response bodies are ever transmitted to Sahamati.

***

**Q: What if my AA serves multiple FIPs? Does SNA handle that?**

Yes. The JSON payload supports a "fips" array where you can include metrics for each FIP separately. SNA aggregates per-FIP metrics automatically once the integration points are instrumented.

***

**Q: How do we handle the case where no transaction was done with a particular FIP?**

SNA reports only for FIPs for which it has received data. If an FIP has zero interactions in a 10-minute window, it will be omitted from that window's payload.

***

**Q: What happens if SNA is down or cannot reach the Sahamati endpoint?**

SNA includes retry logic for endpoint failures. Metrics that could not be pushed will be retried. If SNA itself is down, metrics for that window will be lost. Ensure that SNA has a health check configured in your cluster's liveness/readiness probes.

***

**Q: Do we need to make code changes to our AA service when Sahamati updates the SLA schema?**

No. Schema updates and logic changes are packaged inside new SNA versions. You only need to redeploy the updated Helm chart. Your AA service code does not need to change.

In very rare cases, if there is a change that warrants an snalib upgrade, you (AA) will have to recompile your code. If there is a change in the signature of the snalib method, you may have to make a corresponding change in your code.

***

**Q: How do we know if our integration is working correctly?**

You can validate your integration in UAT by monitoring the SNA logs in your cluster for push success/failure status and checking the response from the Sahamati SLA endpoint.

***

**Q: What languages does snalib support?**

Currently, Go, Node and Java libraries are available. Additional language support may be planned based on ecosystem demand.

***

**Q: How are the synchronous transactions and asynchronous notifications correlated?**

Synchronous operations: API Request and API Response - They are correlated using a "transaction correlation id" (txnCorId). This is a uuid that the AA will have to generate for every RequestIn and RequestOut, when sending to SNA. This same correlation id will have to be included when sending the corresponding ResponseOut and ResponseIn to SNA.




---

[Next Page](/llms-full.txt/1)

