Download OpenAPI specification:Download
Download our postman collection here.
The Insights API provides developers with tools to enhance their transaction, account, and user data with deep enrichment. Although the information returned by the Insights API can be utilized in various ways and implementations may differ, the initial steps for using the API are consistent:
To use the Insights API, you need authentication credentials. These credentials can be obtained by requesting a FinGoal developer account. FinGoal developer support will send you development environment credentials within 24 hours. These credentials are required for the quickstart.
All Insights API endpoints require an Authorization
header with a Bearer
token. This token is a JSON Web Token (JWT) generated by the Insights API authentication endpoint. To generate this token, you will need the client_id
and client_secret
provided when you requested a FinGoal developer account.
The request body is a JSON object with the following structure:
{
"client_id": "{YOUR_CLIENT_ID}",
"client_secret": "{YOUR_CLIENT_SECRET}"
}
Make a POST request to the Insights API authentication endpoint using the prepared JSON object.
const body = {
"client_id": "{YOUR_CLIENT_ID}",
"client_secret": "{YOUR_CLIENT_SECRET}"
}
const requestOptions = {
method: 'POST',
body: body,
};
try {
const response = await fetch("https://findmoney-dev.fingoal.com/v3/authentication", requestOptions);
const data = response.json();
const { access_token } = data;
console.log({ access_token });
} catch(error) {
console.log('AUTHENTICATION_ERROR:', error);
}
The JavaScript code above uses the fetch
API to request an access token. If the request succeeds, it extracts the access_token from the response body. If an error occurs, it logs the error.
If the request is successful, the response body will contain a JSON object with the following structure:
access_token
: The JWT token used to authenticate requests to the Insights API.scope
: The permissions that the token has.expires_in
: The number of seconds until the token expires (always 86400 seconds, or 24 hours). token_type
: The type of token. This value is always Bearer
.{
"access_token": "eyJh...",
"scope": "read:transactions write:transactions ...",
"expires_in": 86400,
"token_type": "Bearer"
}
access_token
securely. Do not expose it in client-side code.expires_in
value to determine when to refresh the token.To authenticate your requests to the Insights API, you must include the JWT token in the Authorization
header. The header should have the following structure:
{
"Authorization": "Bearer {YOUR_ACCESS_TOKEN}"
}
This header will successfully authenticate any request to the Insights API. You can now proceed to the enrichment, tagging, or savings recommendations quickstarts to integrate the Insights API into your application.
The Insights API's transaction enrichment endpoints enable developers to clean and enhance their transaction data. This process includes standardizing merchant names, categorizing transactions, and adding additional metadata. It also supports transaction-level tagging. Transactions submitted to the enrichment endpoints contribute to the Insights API's user tagging capabilities.
The Insights API offers both synchronous and asynchronous flows. The synchronous flow is a direct request-response model intended for testing and development purposes only. All production requests should use the asynchronous historical and streaming transaction enrichment endpoints.
This quickstart requires a JWT, which can be generated following the top-level authentication quickstart. Ensure you have a valid JWT before proceeding.
The request body should be a JSON object with a single parameter, transactions
, which must be an array. Each transaction must include the following fields:
uid
: A unique user identifier.amountnum
: The transaction amount.date
: The transaction date.original_description
: The original transaction description.transactionid
: The unique transaction identifier.accountType
: The account type.settlement
: The settlement type.{
"transactions": [
{
"uid": "16432789fdsa78",
"accountid": "1615",
"amountnum": 12.41,
"date": "2024-05-11",
"original_description": "T0064 TARGET STORE",
"transactionid": "988cee06-5d36-11ec-b00b-bc8d8f2303a12733",
"accountType" : "creditCard",
"settlement": "debit"
}
]
}
Make a POST request to the Insights API cleanup endpoint using the prepared JSON object. Include the JWT in the Authorization
header.
const headers = new Headers();
headers.append("Authorization", "Bearer {YOUR_TOKEN}");
headers.append("Content-Type", "application/json");
const body = JSON.stringify({
"transactions": [
{
"uid": "16432789fdsa78",
"accountid": "1615",
"amountnum": 12.41,
"date": "2024-05-11",
"original_description": "T0064 TARGET STORE",
"transactionid": "988cee06-5d36-11ec-b00b-bc8d8f2303a12733",
"accountType" : "creditCard",
"settlement": "debit"
}
]
});
const requestOptions = {
method: 'POST',
redirect: 'follow'
headers,
body,
};
try {
const response = await fetch("https://findmoney-dev.fingoal.com/v3/cleanup", requestOptions);
const data = response.json();
console.log(data);
} catch(error) {
console.log('ERROR:', error);
}
The JavaScript code above uses the fetch
API to request transaction enrichment. If the request succeeds, it logs the response body. If an error occurs, it logs the error.
If the request is successful, the response body will contain a JSON object with a single parameter, status
. The status
object has the following structure:
transactions_received
: Whether or not the transactions were successfully enqueued for enrichment.transactions_validated
: Whether or not the transactions were successfully validated.processing
: Whether or not the transactions are currently being processed.num_transactions_processing
: The number of transactions that are currently being processed.batch_request_id
: The unique identifier for the batch request.{
"status": {
"transactions_received": true,
"transactions_validated": true,
"processing": true,
"num_transactions_processing": 1,
"batch_request_id": "988cee06-5d36-11ec-b00b-bc8d8f2303a12733"
}
}
The batch_request_id
is a unique identifier for the batch request. You will use this identifier to retrieve the enriched transactions.
To receive a webhook notification for a completed enrichment batch, you must submit a webhook URL. Use the FinGoal support email (support@fingoal.com) to submit a webhook URL for registry. Once the URL is registered, you will automatically receive all future enrichment completion webhooks.
Webhook notifications are sent as HTTP POST requests to the registered URL. The webhook URL must be publicly accessible and support HTTPS connections. The Insights API cannot send webhooks to a non-HTTPS URL.
The webhook payload contains a JSON object with the following structure:
batch_request_id
: The unique identifier for the batch request.The batch_request_id
corresponds to the batch_request_id
returned in the initial enrichment request.
{
"batch_request_id": "988cee06-5d36-11ec-b00b-bc8d8f2303a12733"
}
Every enrichment complete webhook includes an X-Webhook-Verification
header. The header contains a SHA-256 HMAC signature of the webhook payload. To verify the webhook, you must generate a SHA-256 HMAC signature using the webhook payload and your Insights API secret key. If the generated signature matches the signature in the X-Webhook-Verification
header, the webhook is valid. If not, the webhook should be discarded.
The following snippet demonstrates how to verify the webhook signature using Node.js with the crypto
and express
libraries.
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook-receiver', (req, res) => {
const { headers, body } = req;
const { 'x-webhook-verification': signature } = headers;
if (!signature) {
res.status(400).send('Reject the webhook if no verification header is present.');
return;
}
const secret = 'YOUR_CLIENT_SECRET';
const payload = JSON.stringify(body);
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(payload).digest('hex');
if (digest === signature) {
res.status(200).send('The webhook is verified. It is safe to process the payload.');
} else {
res.status(400).send('The Webhook verification is incorrect for the payload. Reject the webhook.');
}
});
With the batch_request_id
, submit a GET request to the Insights API enrichment retrieval endpoint. Include the JWT in the Authorization
header.
const headers = new Headers();
headers.append("Authorization", "Bearer {YOUR_TOKEN}");
const requestOptions = {
method: 'GET',
redirect: 'follow',
headers,
};
try {
const response = await fetch("https://findmoney-dev.fingoal.com/v3/cleanup/{batch_request_id}", requestOptions);
const data = response.json();
console.log(data);
} catch(error) {
console.log('ERROR:', error);
}
The JavaScript code above uses the fetch
API to request the enriched transactions. If the request succeeds, it logs the response body. If an error occurs, it logs the error.
If the request is successful, the response body will contain a JSON object a single parameter, enrichedTransactions
. The enrichedTransactions
array will contain all available transaction-level enrichment for the data in this batch.
uid
for optimal performance. uid
and transactionid
values for each user and transaction. These identifiers may need to be cross-referenced with your system's data in the future.uid
or transactionid
fields. We recommend using a UUID or similar anonymous identifier instead.The test transaction enrichment endpoint provides immediate enrichment on transaction data. This endpoint is ideal for testing API functionality and previewing enrichment results.
This endpoint is not intended for production use. Use the historical and streaming endpoints for production-level enrichment.
For optimal performance, adhere to the following limits:
uid
field in each transaction. Transactions
required | Array of objects |
Success
Bad request. An array of errors in the data will be returned. Fields not allowed or incorrectly formatted will be noted.
Unauthorized
{- "transactions": [
- {
- "accountType": "checking",
- "amountnum": 19.99,
- "date": "2024-05-01",
- "original_description": "Cottonwood Supermarket & Deli",
- "transactionid": "178b1f61-dafe-4d47-837b-54ce34dc82b2",
- "settlement": "debit",
- "uid": "user123"
}
]
}
{- "enrichedTransactions": [
- {
- "accountid": "string",
- "amountnum": 0,
- "category": "string",
- "categoryId": 0,
- "categoryLabel": [
- "string"
], - "client_id": "string",
- "container": "string",
- "date": "2019-08-24T14:15:22Z",
- "detailCategoryId": 0,
- "guid": "string",
- "highLevelCategoryId": 0,
- "is_physical": true,
- "is_recurring": true,
- "merchantAddress1": "string",
- "merchantCity": "string",
- "merchantCountry": "string",
- "merchantLatitude": "string",
- "merchantLogoURL": "string",
- "merchantLongitude": "string",
- "merchantName": "string",
- "merchantPhoneNumber": "string",
- "merchantState": "string",
- "merchantType": "string",
- "merchantZip": "string",
- "original_description": "string",
- "receiptDate": "2019-08-24T14:15:22Z",
- "requestId": "string",
- "simple_description": "string",
- "simpleDescription": "string",
- "sourceId": "string",
- "subType": "string",
- "transactionid": "string",
- "transactionTags": [
- "string"
], - "type": "string",
- "uid": "string"
}
]
}
The historical transaction enrichment endpoint is designed for enriching a large number of transactions. It is optimized to handle substantial payloads and efficiently process large backlogs of data.
This endpoint is asynchronous. A webhook will be sent to the provided URL when a batch of transactions has been enriched.
To maximize throughput for this endpoint, follow these guidelines:
uid
and include all transactions for a single uid
in the same payload.Transactions
required | Array of objects |
Success
Bad request. An array of errors in the data will be returned. Fields not allowed or incorrectly formatted will be noted.
Unauthorized
{- "transactions": [
- {
- "accountType": "checking",
- "amountnum": 19.99,
- "date": "2024-05-01",
- "original_description": "Cottonwood Supermarket & Deli",
- "transactionid": "178b1f61-dafe-4d47-837b-54ce34dc82b2",
- "settlement": "debit",
- "uid": "user123"
}
]
}
{- "status": {
- "transactions_received": true,
- "transactions_validated": true,
- "processing": true,
- "num_transactions_processing": 0,
- "batch_request_id": "string"
}
}
{- "batch_request_id": "5f4b1b9b-4b7d-4b7d-4b7d-4b7d4b7d4b7d"
}
FinGoal's streaming transaction enrichment endpoint is designed for enriching daily user transactions or other smaller transaction batches.
Unlike the historical transaction enrichment endpoint, the streaming transaction enrichment endpoint does not require any user segmentation. Requests that include many users (by uid) will not deteriorate the endpoint's performance.
This endpoint is asynchronous. A webhook will be sent to the provided URL when a batch of transactions has been enriched. For larger transaction sets, such as historical data, user the historical enrichment endpoint.
To maximize throughput for this endpoint, follow these guidelines:
Transactions
required | Array of objects |
Success
Bad request. An array of errors in the data will be returned. Fields not allowed or incorrectly formatted will be noted.
Unauthorized
{- "transactions": [
- {
- "accountType": "checking",
- "amountnum": 19.99,
- "date": "2024-05-01",
- "original_description": "Cottonwood Supermarket & Deli",
- "transactionid": "178b1f61-dafe-4d47-837b-54ce34dc82b2",
- "settlement": "debit",
- "uid": "user123"
}
]
}
{- "status": {
- "transactions_received": true,
- "transactions_validated": true,
- "processing": true,
- "num_transactions_processing": 0,
- "batch_request_id": "string"
}
}
{- "batch_request_id": "5f4b1b9b-4b7d-4b7d-4b7d-4b7d4b7d4b7d"
}
Developers may use this endpoint in conjunction with the asynchronous cleanup endpoints to retrieve the results of a transaction cleanup operation by its batch operation ID. The operation ID can be extracted from the webhook that the async cleanup endpoint sends when enrichment is complete.
Success
Unauthorized
No transactions found for the given request id.
{- "enrichedTransactions": [
- {
- "accountid": "string",
- "amountnum": 0,
- "category": "string",
- "categoryId": 0,
- "categoryLabel": [
- "string"
], - "client_id": "string",
- "container": "string",
- "date": "2019-08-24T14:15:22Z",
- "detailCategoryId": 0,
- "guid": "string",
- "highLevelCategoryId": 0,
- "is_physical": true,
- "is_recurring": true,
- "merchantAddress1": "string",
- "merchantCity": "string",
- "merchantCountry": "string",
- "merchantLatitude": "string",
- "merchantLogoURL": "string",
- "merchantLongitude": "string",
- "merchantName": "string",
- "merchantPhoneNumber": "string",
- "merchantState": "string",
- "merchantType": "string",
- "merchantZip": "string",
- "original_description": "string",
- "receiptDate": "2019-08-24T14:15:22Z",
- "requestId": "string",
- "simple_description": "string",
- "simpleDescription": "string",
- "sourceId": "string",
- "subType": "string",
- "transactionid": "string",
- "transactionTags": [
- "string"
], - "type": "string",
- "uid": "string"
}
], - "failedTransactions": [
- {
- "transactionid": "string",
- "amountnum": 0,
- "original_description": "string",
- "uid": "string",
- "date": "2019-08-24T14:15:22Z",
- "settlement": "string",
- "accountType": "string"
}
]
}
This endpoint runs on data sent to the Transaction Enrichment endpoints. It can take up to 30 minutes for user tagging results to appear following transaction upload. Also, in order to receive user tags, transaction dates must be within the past 90 days.
Fetches user and transaction tags for a specified user ID. Both endpoints return the same schema. Use the sync keyword to trigger a manual update on the transaction and user tags for a single user.
Success
Unauthorized
User ID could not be found
{- "user": {
- "client_id": "string",
- "id": "string",
- "uid": "string",
- "uniqueId": "string",
- "lifetimeSavings": 0,
- "registrationDate": "2019-08-24T14:15:22Z",
- "subtenantId": "string",
- "tags": [
- "string"
], - "totaltransactions": 0,
- "transactionsSinceLastUpdate": 0
}, - "transactions": [
- {
- "transaction_id": "string",
- "simple_description": "string",
- "original_description": "string",
- "category": "string",
- "amount": 0,
- "date": "2019-08-24T14:15:22Z",
- "tags": [
- "string"
]
}
]
}
This endpoint runs on data sent to the Transaction Enrichment endpoints. It can take up to 30 minutes for user tagging results to appear following transaction upload. Also, in order to receive user tags, transaction dates must be within the past 90 days.
Fetches user and transaction tags for a specified user ID. Both endpoints return the same schema. Use the sync keyword to trigger a manual update on the transaction and user tags for a single user.
Success
Unauthorized
User ID could not be found
{- "user": {
- "client_id": "string",
- "id": "string",
- "uid": "string",
- "uniqueId": "string",
- "lifetimeSavings": 0,
- "registrationDate": "2019-08-24T14:15:22Z",
- "subtenantId": "string",
- "tags": [
- "string"
], - "totaltransactions": 0,
- "transactionsSinceLastUpdate": 0
}, - "transactions": [
- {
- "transaction_id": "string",
- "simple_description": "string",
- "original_description": "string",
- "category": "string",
- "amount": 0,
- "date": "2019-08-24T14:15:22Z",
- "tags": [
- "string"
]
}
]
}
The Insights API's Savings Recommendations endpoints enable developers to provide users with personalized savings recommendations based on their transaction data. The recommendations are generated by analyzing the user's transaction history and identifying opportunities to save money. The API provides insights into potential savings opportunities, such as switching to a different credit card, opening a new savings account, or refinancing a loan.
The Savings Recommendations API requires developers to register a webhook endpoint to receive updates when new recommendations are available. Transactions submitted to the Savings Recommendations API do not contribute to the Insights API's user tagging capabilities.
This quickstart requires a JWT, which can be generated following the top-level authentication quickstart. Ensure you have a valid JWT before proceeding.
The request body should be a JSON with a single parameter, transactions
. The format of these transactions depends on which transaction schema you are using. The savings recommendations API supports mx
, plaid
, and fingoal
transaction schemas. Here is an example of a simple fingoal
schema payload:
{
"transactions": [
{
"uid": "example_user_id",
"amountnum": 10.99,
"date": "2022-10-01",
"simple_description": "Target",
"original_description": "TARGET #234 purchase ****1234 20221001",
"transactionid": "sample_transaction_id"
}
]
}
Make a POST request to the Savings Recommendations API endpoint using the prepared JSON object. Include the JWT in the Authorization
header. Set the type
header to the transaction schema you are using.
const headers = new Headers();
headers.append("Authorization", "Bearer {ACCESS_TOKEN}"
headers.append("type", "mx");
const requestOptions = {
method: 'POST',
headers: headers,
body: body,
redirect: 'follow'
}
try {
const response = await fetch("/v3/transactions", requestOptions);
const data = response.json();
console.log({ data });
} catch(error) {
console.log({ error });
}
The JavaScript code above uses the fetch
API to submit transactions to the Savings Recommendations API. If the request succeeds, it logs the response data. If an error occurs, it logs the error. The response includes metadata about the submitted transactions.
To receive a webhook notification for a new recommendation event, you must submit a webhook URL. Use the FinGoal support email (support@fingoal.com) to submit a webhook URL for registry. Once the URL is registered, you will automatically receive all future new recommendations events.
Webhook notifications are sent as HTTP POST requests to the registered URL. The webhook URL must be publicly accessible and support HTTPS connections. The Insights API cannot send webhooks to a non-HTTPS URL.
The webhook payload for savings recommednations is a JSON object with a single parameter, finsights
. The finsights
parameter is an array of objects, each representing a single savings recommendation. Each recommendation object has the following fields:
finsight_id
: A unique identifier for the recommendation.uniqueId
: A unique identifier for the recommendation that includes your client ID and transaction ID.user_id
: The user ID associated with the recommendation.transaction_id
: The transaction ID associated with the recommendation.insight_ctaurl
: A URL for the call-to-action that can be used as an HREF for the recommendation text.finsight_image
: A URL for an image relevant to the savings recommendation.insight_text
: User-facing copy that describes the savings recommendation.recommendation
: A title for the savings recommendation.amountFound
: The estimated amount the user can expect to save if they were to follow the advice.category
: The category of the savings recommendation.{
"finsights": [
{
"finsight_id": "uuidv4",
"uniqueId": "your_client_id:your_transaction_id",
"user_id": "your_uid",
"transaction_id": "your_transaction_id",
"insight_ctaurl": "http://example.com",
"finsight_image": "https://example.com/example.jpg",
"insight_text": "Get Target Red Card to save on your Target shopping!",
"recommendation": "Target Red Card",
"amountFound": 10.00,
"category": "Shopping"
}
]
}
uid
and transactionid
values for each user and transaction. Because the savings recommendations exclude fields from the orginal transaction data, it may be necessary to associate the savings recommendations back to the original transaction data in your system.finsight_id
and uniqueId
values to track the recommendations in your system.Post transaction data from your preferred aggregator.
Success
The request failed validation.
Unauthorized
{- "transactions": [
- {
- "account_id": "string",
- "amount": 0,
- "date": "2019-08-24",
- "name": "string",
- "pending": true,
- "transaction_code": "adjustment",
- "transaction_id": "string",
- "uid": "string",
- "account_owner": "string",
- "authorized_date": "2019-08-24T14:15:22Z",
- "authorized_datetime": "2019-08-24T14:15:22Z",
- "category": [
- "string"
], - "category_id": "string",
- "check_number": "string",
- "datetime": "2019-08-24T14:15:22Z",
- "iso_currency_code": "USD",
- "location": {
- "address": "string",
- "city": "string",
- "country": "string",
- "lat": 0,
- "lon": 0,
- "postal_code": "string",
- "region": "string",
- "store_number": 0
}, - "merchant_name": "string",
- "original_description": "string",
- "payment_channel": "online",
- "payment_meta": {
- "by_order_of": "string",
- "payee": "string",
- "payer": "string",
- "payment_method": "string",
- "payment_processor": "string",
- "ppd_id": "string",
- "reason": "string",
- "reference_number": "string"
}, - "pending_transaction_id": "string",
- "personal_finance_category": {
- "primary": "string",
- "detailed": "string"
}, - "transaction_type": "digital",
- "unofficial_currency_code": "string"
}
]
}
{- "message": "string"
}
{- "category": "string",
- "insight_text": "string",
- "transaction_id": "string",
- "uniqueId": "string",
- "user_id": "string",
- "amountFound": "string",
- "finsightDate": "2019-08-24",
- "recommendation": "string",
- "retries": 0,
- "webhookSent": true,
- "lastAttempt": "2019-08-24"
}
Get a specific Call to Action, associated with a specific transaction record
The Savings Recommendation was successfully returned.
Unauthorized
The requested Savings Recommendation could not be found.
{- "category": "string",
- "insight_text": "string",
- "transaction_id": "string",
- "uniqueId": "string",
- "user_id": "string",
- "amountFound": "string",
- "finsightDate": "2019-08-24",
- "recommendation": "string",
- "retries": 0,
- "webhookSent": true,
- "lastAttempt": "2019-08-24"
}
View all the savings recommendations your client have received.
Savings Recommendations successfully returned.
One or both of the 'startAt' and 'endAt' in the query were unexpected. The UNIX dates may be malformed, or the interval between them could not be defined.
Unauthorized.
{- "finsights": [
- {
- "category": "string",
- "insight_text": "string",
- "transaction_id": "string",
- "uniqueId": "string",
- "user_id": "string",
- "amountFound": "string",
- "finsightDate": "2019-08-24",
- "recommendation": "string",
- "retries": 0,
- "webhookSent": true,
- "lastAttempt": "2019-08-24"
}
]
}