Introduction
This guide explains how to deal with multi-factor authentication (MFA) while running an aggregation-type process. There’s a lot of material in here that’s quite similar to our guide on the happy aggregation path without MFA, except that it’s expanded and explained in more detail.
General steps
Aggregating account and transaction data is one of the most important features of the MX API. Seeing when, where, and how much people are spending is core not only to personal financial management, but also to hundreds of fintechs, banks, credit unions, and financial companies who seek to learn from and improve the financial lives of their customers.
It can also be a somewhat complicated process, especially when dealing with issues like multi-factor authentication (MFA). This guide will walk you through the process step-by-step so that you can see the potential pitfalls and avoid them.
In general, it involves:
- Making a request to the aggregate member endpoint;
- Repeatedly check the
member
for changes in the state of the aggregation using the read member connection status endpoint and looking at fields such asconnection_status
,is_being_aggregated
,is_authenticated
,has_processed_accounts
, etc.;
- Using the Connect widget provided by MX greatly simplifies and automates steps 2 and 3;
- If necessary, answering MFA challenges using the resume aggregation endpoint;
- Reading aggregated data using the list accounts and list transactions endpoints.
Before we get to the real step-by-step, though, there’s some things you should know that will make your development much easier.
There are multiple aggregation-type processes in the MX API
One important thing to point out up front is that there are multiple processes in the API that follow the same general steps and workflows. This guide will help you with all of them, but we’ll focus on standard aggregation in the examples here.
Aggregation-type processes include:
- Standard aggregation
- Account verification
- Identification
- Fetching an extended transaction history
- Fetching account statements
- Fetching account balances
- Fetching account rewards information
Important fields and states: connection_status
, is_being_aggregated
, and more
There are multiple fields on each member
that give you all the information you need to determine what state it is in and how to resolve that state into a successful aggregation — as well as when resolution is not possible. These all need to be weighed together in order to make an aggregation successful.
The connection_status
field indicates the current state of an aggregation in a general way. For instance, a value of CREATED
indicates that the member has just been created. A value of CHALLENGED
means the aggregation has run into MFA. FAILED
means that the aggregation was unsuccessful. Below, you’ll see exact definitions and next steps for each of the 21 connection statuses.
Another important field is the boolean is_being_aggregated
. This indicates whether an aggregation process is currently taking place on the MX platform.
These fields should be used in conjunction with several other member
fields to determine future actions. These include aggregated_at
, successfully_aggregated_at
, and is_authenticated
.
For example, when the connection_status
is CONNECTED
and the is_being_aggregated
field is false
, this means the latest aggregation attempt has finished and data for accounts and transactions can be read. You can use the field successfully_aggregated_at
to determine when the last successful aggregation occurred.
The connection statuses CREATED
, UPDATED
, DELAYED
, and RESUMED
represent transient states for different points in the aggregation process and generally do not require a specific action or end-user input. They may, however, require you to keep making read requests on the member until an actionable status or an end state shows up.
The connection statuses PREVENTED
, DENIED
, IMPEDED
, IMPAIRED
, REJECTED
, EXPIRED
, LOCKED
, IMPORTED
, DISABLED
, DISCONTINUED
, and CLOSED
, represent end states that will require a new aggregation, and possibly end-user input for future success.
But we’ll get into more detail about all these various statuses in future guides. For right now, we’ll focus on the happy path.
Member fields to pay attention to
Field Name | Data Type | Description |
---|---|---|
aggregated_at |
String | The date and time the member the last aggregation was initiated, represented in ISO 8601 format with timestamp (e.g., 2015-04-13T12:01:23-06:00). |
connection_status |
String | This field indicates the state of a member’s aggregation, provided as a string. See member connection statuses for more information on possible values. |
is_being_aggregated |
Boolean | This field will be true if the member is being aggregated at the time of the request. Otherwise, this field will be false. |
successfully_aggregated_at |
String | The date and time the account was last successfully aggregated, represented in ISO 8601 format with timestamp (e.g., 2015-04-13T12:01:23-06:00). |
Connection status definitions
Integer value | Status | Definition | Next steps | End-user message |
---|---|---|---|---|
null | null | The member exists but does not have credentials. A member that does not aggregate (e.g., a manual member) will always have this status. | None. | None. |
0 | CREATED | The member is new and has not yet been aggregated. | Aggregate the member once the end user logs in; poll for a status update. | Connecting to {…} … |
1 | PREVENTED | MX is preventing aggregation until the member’s credentials have been updated. | Display end-user message; after end user has updated their credentials, aggregate again. | The last 3 attempts to connect have failed. Please re-enter your credentials to continue importing data. |
2 | DENIED | The credentials provided for the member were invalid. | Display end-user message; after end user has updated their credentials, aggregate again. | The credentials entered do not match your credentials at this institution. Please re-enter your credentials to continue importing data. |
3 | CHALLENGED | The member has been challenged by multi-factor authentication. | Display end-user message; follow MFA pathway; after the user answers MFA, poll for a status update. | To authenticate your connection to {…}, please answer the following challenge(s). |
4 | REJECTED | An MFA challenge was answered incorrectly. | Display end-user message; another challenge may follow or aggregation may need to be restarted. | The answer or answers provided were incorrect. Please try again. |
5 | LOCKED | The financial institution is preventing authentication. The end user must contact the financial institution. | Display end-user message. | Your account is locked. Please log in to the appropriate website for {…} and follow the steps to resolve the issue. |
6 | CONNECTED | The member was successfully authenticated and data is now aggregating. | Display the account as having been connected. | Connected to […] … |
7 | IMPEDED | The end user’s attention is required at their online banking institution, e.g., there is a marketing message that must be viewed, terms and conditions that must be accepted, etc. | Display end-user message. | Your attention is needed at this institution’s website. Please log in to the appropriate website for {…} and follow the steps to resolve the issue. |
8 | RECONNECTED | The member has been migrated to a new data source and aggregation is likely to trigger one-time password MFA. MX will not perform background aggregation in order to avoid unnecessarily disruptive texts, emails, etc. The member must be re-aggregated in the foreground with the end user present. | Aggregate the member once the end user logs in; poll for a status update. | Reconnecting to {…} … |
9 | DEGRADED | Aggregation has failed at least three times within a short period of time. | Display end-user message. | We are upgrading this connection. Please try again later. |
10 | DISCONNECTED | Aggregation has failed at least three times and has not succeeded for at least two weeks. | Display end-user message. | It looks like your data from {…} cannot be imported. We are working to resolve the issue. |
11 | DISCONTINUED | The connection to this financial institution is no longer available. | Display end-user message. | Connections to this institution are no longer supported. You may create a manual account and use manual transactions to track data for this account. |
12 | CLOSED | The end user, MX, the client, or a partner has marked the member as closed. | Display end-user message. | This connection has been closed. You may track this account manually. If reopened, you may connect the institution again. |
13 | DELAYED | Aggregating the member has taken longer than expected and it has not yet been connected. | Display end-user message; poll for a status update. | Importing your data from {…} may take a while. Please check back later. |
14 | FAILED | Aggregation failed without being connected. | Display end-user message; try aggregating again later. | There was a problem validating your credentials with {…}. Please try again later. |
15 | UPDATED | The member has been updated — i.e., credentials have been updated — but it has not yet been connected. | Aggregate the member once the end user logs in; poll for a status update. | Connecting to {…} … |
16 | DISABLED | Aggregation has been momentarily paused, but the member is still connected. | Display end-user message. | Importing data from this institution has been disabled. Please contact us if you believe it has been disabled in error. |
17 | IMPORTED | MX does not have credentials and will not try to aggregate the member until the end user provides credentials. | Display end-user message; re-aggregate after the end user updates credentials. | You must re-authenticate before your data can be imported. Please enter your credentials for {…}. |
18 | RESUMED | The answer to an MFA challenge was received, but it is not yet clear whether it was correct. | Poll for a status update. | Connecting to {…} … |
19 | EXPIRED | The MFA answer was not provided within the time allotted by the financial institution. | Display end-user message; re-aggregate the member if the end user initiates it. | The answer or answers were not provided in time. Please try again. |
20 | IMPAIRED | The member is missing some or all credentials needed in order to connect. | Display end-user message; re-aggregate after the end user updates credentials. | You must re-authenticate before your data can be imported. Please enter your credentials for {…}. |
Background aggregation, automatic aggregation, and the skip_aggregation
parameter
MX aggregates each member
every 24 hours without you having to do anything. This process is called background aggregation. It ensures that end users’ data will always be up to date. This is beneficial because if a background aggregation is successful (i.e., the successfully_aggregated_at
field indicates a time within the last 24 hours) you can choose to skip manual aggregation and jump right to reading account and transaction data, which can help you load things faster in your product.
If an end user is present, you can often choose to manually run an aggregation using the general steps in this guide. End users must be present during manual aggregations because they may run into MFA, credential update requests, terms and conditions agreements, or any number of other situations requiring end-user input. Just keep in mind that you cannot run a new aggregation within three hours of a successful aggregation, whether manual or background. So pay attention to those aggregated_at
and successfully_aggregated_at
fields while you’re developing your product with the MX API.
Both manual and background aggregation may be prevented by disabling a user
. A user
must be re-enabled before any aggregation can be attempted.
MX may also suspend background aggregation on a particular member
in some circumstances, such as when several consecutive aggregation attempts fail. However, you can always attempt a manual aggregation on a suspended member
.
Automatic aggregation is a bit different. Every time a new member is successfully created or an existing member is successfully updated, an aggregation process will start automatically, without having to manually call the aggregate member endpoint. You will, however, need to follow up on the rest of the aggregation process, like looking for changes in the connection status, answering MFA, etc.
If your workflow requires that there not be any automatic aggregation, you can easily prevent it by including the skip_aggregation
body parameter and setting it to true
in either a create member or update member request.
1. Check the member's connection status
Now that you’ve got all that important information above, we can take you through the actual aggregation process step by step, including the MFA process.
The first step is to check the member’s connection_status
to see whether aggregation is either necessary or even possible. Each status indicates something different; some connection statuses mean that an aggregation will fail if attempted or that an aggregation is already in progress. Again, we’ll focus on an easy case where aggregation proceeds successfully for this example, but here’s some important information on what these statuses mean anyway.
In general, aggregation can be attempted for a member
with the following connection statuses:
CREATED
CONNECTED
DEGRADED
DISCONNECTED
EXPIRED
FAILED
IMPEDED
RECONNECTED
UPDATED
In general, you must update credentials before aggregating a member
with the following connection statuses:
PREVENTED
DENIED
IMPAIRED
IMPORTED
The following connection statuses represent a transitory state in an ongoing aggregation process:
CHALLENGED
DELAYED
REJECTED
RESUMED
You should not attempt aggregation on a member
with the following connection statuses:
CLOSED
DISABLED
DISCONTINUED
Endpoint:
GET /users/{user_guid}/members/{member_guid}/status
Example request
1
2
3
curl -L -X GET 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/members/MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa/status' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Authorization: Basic {token}'
Example response
1
2
3
4
5
6
7
8
9
10
{
"member": {
"aggregated_at": "2020-09-21T19:38:01Z",
"connection_status": "CONNECTED",
"guid": "MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa",
"is_authenticated": true,
"is_being_aggregated": false,
"successfully_aggregated_at": "2020-09-21T19:44:17Z"
}
}
Notice the various fields you see. This shows a member that was successfully authenticated and aggregated on September 21, 2020, but is not currently being aggregated. You see a connection_status
of CONNECTED
, which was the final state of the member at the end of the last aggregation. All this means we can proceed to the next step and actually request a new aggregation.
2. Call the aggregate member endpoint
Go ahead and make a request to the aggregate member endpoint.
Endpoint:
POST /users/{user_guid}/members/{member_guid}/aggregate
Example request
1
2
3
4
curl -L -X POST 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/members/MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa/aggregate' \
-H 'Authorization: Basic {token}' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Content-Type: application/json'
Example response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"member": {
"aggregated_at": "2020-09-21T19:48:57Z",
"connection_status": "CONNECTED",
"guid": "MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa",
"id": null,
"institution_code": "mxbank",
"is_being_aggregated": true,
"metadata": null,
"name": "MX Bank",
"successfully_aggregated_at": "2020-09-21T19:44:17Z",
"user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c"
}
}
Notice in the example response that the member still has a connection_status
of CONNECTED
and successfully_aggregated_at
is still the date and time.
However, the aggregated_at
field has updated to the time the request was made, and the is_being_aggregated
boolean is now true
. This shows that the aggregation process is active and ongoing. The connection_status
hasn’t changed from what it was at the last aggregation because the current process has not run into any errors or obstacles. However, it may change at any time in the process, so we need to check the status again.
3. Read the connection status again
Let’s check the connection status again to see what’s happening in this current aggregation.
Endpoint:
GET /users/{user_guid}/members/{member_guid}/status
Example request
1
2
3
curl -L -X GET 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/members/MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa/status' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Authorization: Basic {token}'
Example response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"member": {
"aggregated_at": "2020-09-21T19:48:57Z",
"challenges": [
{
"field_name": null,
"guid": "CRD-8f841084-66cb-4e3d-9253-96f97093100a",
"label": "What city were you born in?",
"type": 0
}
],
"connection_status": "CHALLENGED",
"guid": "MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa",
"is_authenticated": false,
"is_being_aggregated": true,
"successfully_aggregated_at": "2020-09-21T19:44:17Z"
}
}
Notice that the connection status is CHALLENGED
and there is a new array returned in this response called challenges
. This indicates that the aggregation has run into multi-factor authentication, and the status response includes the specific question or questions the end user will need to answer in order to proceed. Make a note of both the guid
in the challenges array and the label
, which is thins case What city were you born in?
.
4. Answer the challenges with the resume aggregation endpoint
The resume aggregation endpoint allows you to answer the challenges presented during MFA and continue the aggregation process. In the body of the request, you’ll need to include the challenge guid
provided in the previous response and the correct answer to the question given in the label
field of the last response.
In this case, we’re using MX Bank. The proper answer to any challenge when using MX Bank is correct
if you desire to proceed successfully. In an actual MFA situation, the end user will need to provide the correct answer to the question. If the security question is What city were you born in?
, the answer may be Chicago
, Talahassee
, etc.
There are also more exotic forms of MFA such as choosing from multiple options (like choosing from a list of phone number to text a code to), or choosing the correct pre-determined photo. These will not be covered in this guide, but you should be aware that they exist and that they can be answered with the MX API.
A relatively common scenario is requiring one-time code texted to a phone number. In this case, you’ll be using the resume aggregation endpoint twice: once to choose the phone number, and then again to provide the correct code. In this case, you’ll also need to use the read member status endpoint multiple times and you’ll get two different challenge GUIDs, one for the phone number and one for the code.
Endpoint:
PUT /users/{user_guid}/members/{member_guid}/resume
Example request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -L -X PUT 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/members/MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa/resume' \
-H 'Authorization: Basic {token}' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Content-Type: application/json' \
-d '{
"member": {
"challenges": [
{
"guid": "CRD-8f841084-66cb-4e3d-9253-96f97093100a",
"value": "correct"
}
]
}
}'
Example response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"member": {
"aggregated_at": "2020-09-21T19:48:57Z",
"connection_status": "RESUMED",
"guid": "MBR-84ca0882-ad6c-4f10-817f-c8c0de7424fa",
"id": null,
"institution_code": "mxbank",
"is_being_aggregated": true,
"metadata": null,
"name": "MX Bank",
"successfully_aggregated_at": "2020-09-21T19:44:17Z",
"user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c"
}
}
Notice that connection_status
has changed to RESUMED
and is_being_aggregated
is still true
. However, the is_authenticated
field is still false
. This indicates that the MFA answer provided was correct and the aggregation is proceeding, but the member’s login credentials have not yet been authenticated. We’ll need to keep checking the status to make sure there are no more challenges or errors.