NAV Navbar
cURL
  • What's in this guide
  • Whitelisting
  • Resource structure
  • Creating users
  • Creating members
  • Aggregating data and dealing with MFA
  • Pulling data
  • Tools to get you running
  • Testing your setup
  • Support
  • Product mailing list
  • Getting started with Atrium

    What's in this guide

    In this guide, you'll find lots of information to help you get up and running with Atrium. It includes material on about how the API works, common terminology, common problem scenarios, a Postman collection and downloadable examples in multiple languages, steps on how to test certain Atrium features, broad workflows for common tasks, and more.

    This is not designed to be comprehensive but to provide a broad overview of common tasks and issues. Refer to our detailed API reference for more specific information about Atrium resources, endpoints, and configuration options.

    Whitelisting

    Before you can work within Atrium's production environment, your IP addresses must be whitelisted. If you haven't been whitelisted, you'll see 403 Forbidden errors. Contact support to have your addresses whitelisted.

    Atrium's vestibule environment does not require any whitelisting.

    Resource structure

    Atrium is structured around five major resources, each with its own attributes and endpoints:

    Resource Description
    institution An institution represents a financial institution (FI) like Chase or Wells Fargo. It's important to point out that many real-world FI will actually have several different institution objects within Atrium. This is because, for example, the mortgage division of Wells Fargo might use a separate system than its everyday banking division, which is different from its credit card division, etc.
    user A user represents a person using Atrium via your application, be it a mobile app, web app, desktop app, etc.
    member A member represents the relationship between a user and an institution. A user may have one member each for their bank, their mortgage broker, their credit card provider, etc. Aggregation takes place via members.
    account An account represents a financial account held by an FI, e.g., a user's checking or savings account. A member may have more than one account associated with it. For instance, a user may have both a checking and savings account associated with one Chase login and therefore would have two accounts associated with one member.
    transaction A transaction represents any instance in which money moves into or out of an account, such as a purchase at a business, a payroll deposit, a transfer from one account to another, an ATM withdrawal, etc. Each transaction belongs to only one account.

    Creating users

    Example request

    $ curl -i -X POST 'https://vestibule.mx.com/users' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
      -d '{
            "user": {
              "identifier": "unique_id",
              "metadata": "{\"first_name\": \"Steven\"}"
            }
          }'
    

    Example response

    Status: 200 OK
    
    {
      "user": {
        "guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54",
        "identifier": "unique_id",
        "is_disabled": false,
        "metadata": "{\"first_name\": \"Steven\"}"
      }
    }
    

    To create a new user, call the create user endpoint. It's a good idea to send along a unique identifier with your request to create a new user. Atrium will also give each new user a unique GUID in the guid field within the user object. The Atrium user GUID also appears in the user_guid field when not inside the user object. The identifier and guid allow you to easily map between your system and Atrium.

    You may also include metadata, such as the date the user was created, if desired. You can read more on identifiers and metadata on our API reference page.

    An example request for creating a user is shown to the right.

    Creating members

    Once a user is created, we recommend creating a member with our MX Connect widget. MX Connect allows end users to easily choose an institution to connect to, enter credentials, update credentials, and answer multi-factor authentication.

    If your system or application is unable to support MX Connect, you can always call the endpoint directly in your code. To create a member via endpoints, you'll follow the workflow below:

    Once your member has been created, you'll want to call the read member status endpoint to determine whether answering MFA is required or to update credentials as needed.

    A step-by-step walkthrough on creating a member via endpoints can be found below.

    Aggregating data and dealing with MFA

    Aggregating data about accounts and transactions belonging to a member is a multi-step process. It involves attempting an aggregation request using the aggregate member endpoint, polling the member for changes in the aggregation status, possibly answering additional challenges as required by the institution, then resuming the aggregation.

    If an end user is present, you may call the aggregate member endpoint in order to run a foreground aggregation. End users must be present during foreground aggregations because they may run into MFA, credential update requests, terms and conditions agreements, or any number of other actions required of the end user at an online banking portal.

    Both foreground and background aggregation may be manually disabled by disabling a user. A user must be re-enabled before any aggregation can be attempted.

    Atrium may suspend background aggregation on a particular member in some circumstances, such as when several consecutive aggregation attempts fail. However, you may always attempt a foreground aggregation on a suspended member.

    MFA and connection statuses

    Some institutions require multiple steps for authentication; this process is called multi-factor authentication (MFA). Basically, it is a back and forth dialogue between the end user, the partner's application, and the institution. After the initial credentials are provided, the institution can either grant access or present an MFA challenge.

    When an MFA challenge is presented, you must get the correct value from the end user and send it to MX so the aggregation can continue. More than one MFA cycle may occur. Partners must continue to answer the institution's challenges until the institution grants access to the end user's account.

    Financial institutions will typically have multiple MFA questions and may ask a new question in future aggregations.

    A single aggregation may also enter multiple CHALLENGED states. A typical scenario for this is when a list of options is presented along with a question such as, "Where should we send an authentication token?"

    More details on how to deal with multi-factor authentication are below.

    Member connection statuses

    The connection_status field appears on all member resources and indicates the current state of aggregation for that particular member. Partners can poll a particular member using the read member connection status endpoint to follow changes in the connection_status throughout an aggregation. Partners can use the list members endpoint to get a list of connection statuses for all members.

    The connection_status should be used in conjunction with several other member fields to determine future actions, including aggregated_at, is_being_aggregated, and successfully_aggregated_at. Definitions for these fields appear at the end of this section. Definitions for all member fields are available here.

    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 should be pulled. Partners can use the field successfully_aggregated_at to determine when the last successful aggregation occurred.

    When the status is CHALLENGED, an MFA challenge has been issued, requiring a separate workflow and end-user input.

    The 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 continued polling until an end state is reached.

    The 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.

    Member fields to poll during aggregation

    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 below 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).

    Dealing with a CHALLENGED status

    When a member comes back with a status of CHALLENGED, the aggregation will require MFA credentials from the end user; specifically, the answers to challenges presented by the institution.

    Partners must make a request to the list member challenges endpoint to obtain the challenges to be presented to the end user.

    Resume the aggregation

    Once the MFA credentials have been gathered for the CHALLENGED member, a request to the resume aggregation endpoint will add these MFA credentials to the member and automatically resume the aggregation process. It will run until it either completes in an end state or enters into a state that requires action, as described above.

    It is not uncommon for an aggregation to be CHALLENGED more than once.

    Dealing with multiple CHALLENGED states in one aggregation

    A single aggregation may enter multiple CHALLENGED states. A typical scenario for this is when a list of options is presented along with a question such as, "Where should we send an authentication token?"

    The end user should be prompted for the answer and the answer provided to MX. The aggregation will move to a RESUMED state, but then will go back into a CHALLENGED state. This time, the end user should be prompted to enter the access token. If the MFA challenge is answered successfully, the aggregation will typically proceed to an end state.

    Dealing with a DENIED, PREVENTED, or EXPIRED status

    If a member has a PREVENTED or a DENIED status, it means the authentication credentials are invalid; the end user must provide new credentials, and the member must be updated. A request to the list member credentials endpoint (as distinct from the separate list institution credentials endpoint) will return a list of the authentication credentials required for that member; corresponding input should be gathered from the end user, and that input should be passed to the update member endpoint.

    Pulling data

    When an aggregation is initiated, the member field aggregated_at will update. If it completes successfully, the successfully_aggregated_at field will be updated. These will help you determine when to pull the latest data after a foreground aggregation.

    Transaction data can be accessed though three different endpoints: /users/{user_guid}/transactions, /users/{user_guid}/members/{member_guid}/transactions, and /users/{user_guid}/accounts/{account_guid}/transactions. The first will list all the transactions that belong to the user object. The second will return all transactions that belong to a member object. The third will return all transactions that belong to an 'account' object.

    We recommend first listing available accounts, then listing transactions for a specific account.

    Tools to get you running

    The Postman collection below will allow you to start experimenting with Atrium immediately. The GitHub collections below demonstrate recommended workflows.

    Postman

    To easily get up and running, we recommend using Postman to experiment with Atrium. To do so you should:

    1. Download Postman.
    2. Install the Atrium Postman collection as explained here.
    3. Add the following fields and your own values to a new Postman environment as explained here.
      • MX-API-Key
      • MX-Client-ID
      • Accept
      • Content-Type
      • baseURL
      • User
      • Member
      • Account

    Wrapper libraries on GitHub

    To see example workflows, please download one of our Atrium wrapper libraries in the language of your choice.

    Testing your setup

    The next few sections will take you through the process of creating and aggregating a member as well as aggregating a member that has been challenged by MFA and multiple-question MFA. This process involves many of the important tasks possible with Atrium — and therefore illuminates many of the places where you might trip up.

    MX provides credentials in our development environment that can be used with the MX Bank institution (institution code: mxbank) to test different aggregation responses. These can be used when creating a test member or answering MFA questions. To test the same behavior, aggregate the member again using the appropriate test credentials.

    The test credentials for different situations are as follows:

    Username Password Description
    test_atrium password This mimics successful aggregation with no MFA.
    test_atrium challenge This mimics a text-based MFA challenge. Answer with the word correct to successfully progress through MFA.
    test_atrium options This mimics the "option list" type of MFA challenge. Select "correct" to successfully progress through MFA.
    test_atrium image This mimics the image type of MFA challenge. Answer with the word "correct" to successfully progress through MFA.
    test_atrium BAD_REQUEST This mimics not having a username and password on the member. The member status will go to HALTED.
    test_atrium UNAUTHORIZED This mimics the member having invalid credentials. The member status will go to DENIED.
    test_atrium INVALID This mimics the member having invalid login and/or password fields. The member status will go to DENIED.
    test_atrium LOCKED This mimics a user being locked out of their banking institution. The member status will go to DENIED.
    test_atrium SERVER_ERROR This mimics the financial institution having a server error. The member status will go to HALTED.
    test_atrium UNAVAILABLE This mimics the financial institution having a "service unavailable" error. The member status will go to HALTED.

    Creating a member

    Step one: Search for an institution

    Request

    curl -i -X GET 'https://vestibule.mx.com/institutions?name=mx' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "institutions":
      [
        {"code":"mxbank",
          "name":"MX Bank",
          "url":"https://www.mx.com",
          "medium_logo_url":"https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/100x100/INS-1572a04c-912b-59bf-5841-332c7dfafaef_100x100.png",
          "small_logo_url":"https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/50x50/INS-1572a04c-912b-59bf-5841-332c7dfafaef_50x50.png"
        }
      ],
      "pagination":
      {
        "current_page":1,
        "per_page":25,
        "total_entries":1,
        "total_pages":1
      }
    }
    
    

    Step two: Get institution required credentials

    Request

    # Here, we're using the institution code "mxbank" with the credentials endpoint in order to get the required credentials for MX Bank.
    
    curl -i -X GET 'https://vestibule.mx.com/institutions/mxbank/credentials' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "credentials":
      [
        {"field_name":"LOGIN",
          "guid":"CRD-9f61fb4c-912c-bd1e-b175-ccc7f0275cc1",
          "label":"Username",
          "type":"LOGIN"
        },
        {
          "field_name":"PASSWORD",
          "guid":"CRD-e3d7ea81-aac7-05e9-fbdd-4b493c6e474d",
          "label":"Password",
          "type":"PASSWORD"
        }
      ]
    }
    

    Step three: List users

    Request

    
    # Here, we're checking to see what users are available for testing.
    # Note that this endpoint returns paginated results and accepts optional pagination parameters.
    
    curl -i -X GET 'https://vestibule.mx.com/users?page=1&records_per_page=25' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "users":
      [
        {
          "guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
          "is_disabled":false,
          "metadata":null,
          "identifier":"zt"
        },
        {
          "guid":"USR-d271c77e-e3e9-2b8f-68fe-101e6eb8c369",
          "is_disabled":false,
          "metadata":"{\"first_name\":\"Steven\"}",
          "identifier":"unique_id"
        },
        {
          "guid":"USR-ef3e4d5c-d6c6-2b0e-2f0d-33349c032a7c",
          "is_disabled":false,
          "metadata":null,
          "identifier":"4"
        },
        {
          "guid":"USR-3c896626-3f9f-2a46-e077-6fcb695b5cbc",
          "is_disabled":false,
          "metadata":null,
          "identifier":"2"
        },
        {
          "guid":"USR-28aa9b4f-a909-a370-e82c-34dd036becb1",
          "is_disabled":false,
          "metadata":null,
          "identifier":"mx_bank_test"
        },
        {
          "guid":"USR-ac50e77d-0f08-2b37-094f-ddc4b82927e1",
          "is_disabled":false,
          "metadata":null,
          "identifier":"my_unique_id"
        }
      ],
      "pagination":
        {"current_page":1,
          "per_page":25,
          "total_entries":6,
          "total_pages":1
        }
    }
    

    Step four: Create a member

    Request

    curl -i -X POST 'https://vestibule.mx.com/users/{user_guid}/members' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
      -d '{
            "member": {
              "institution_code": "mxbank",
              "credentials": [
                {
                  "guid": "CRD-9f61fb4c-912c-bd1e-b175-ccc7f0275cc1",
                  "value": "test_atrium"
                },
                {
                  "guid": "CRD-e3d7ea81-aac7-05e9-fbdd-4b493c6e474d",
                  "value": "password"
                }
              ]
            }
          }'
    

    Response

    {
      "member":
      {
        "status":"INITIATED",
        "guid":"MBR-a0df097e-4ccf-e24c-1c30-7a055d4ad24e",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:32:25+00:00",
        "identifier":null,
        "successfully_aggregated_at":null
        }
    }
    

    Step five: Poll the member status

    Request

    # Poll the member status
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"AUTHENTICATED",
        "guid":"MBR-a0df097e-4ccf-e24c-1c30-7a055d4ad24e",
        "aggregated_at":"2017-09-06T16:33:54+00:00",
        "successfully_aggregated_at":"2017-09-06T16:32:30+00:00",
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Request

    # Poll the member status again
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
    

    Response

    {
      "member":
      {
        "status":"TRANSFERRED",
        "guid":"MBR-a0df097e-4ccf-e24c-1c30-7a055d4ad24e",
        "aggregated_at":"2017-09-06T16:33:54+00:00",
        "successfully_aggregated_at":"2017-09-06T16:32:30+00:00",
        "has_processed_accounts":true,
        "has_processed_transactions":false
      }
    }
    

    Request

    # Poll the member status yet again
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

      {
        "member":
        {
          "status":"COMPLETED",
          "guid":"MBR-a0df097e-4ccf-e24c-1c30-7a055d4ad24e",
          "aggregated_at":"2017-09-06T16:33:54+00:00",
          "successfully_aggregated_at":"2017-09-06T16:33:57+00:00",
          "has_processed_accounts":true,
          "has_processed_transactions":true
        }
      }
    
      # Member status COMPLETED indicates aggregation is now done.
      # There is no need to continue polling.
      # Account and transaction data can now be pulled.
    

    Testing single-question MFA

    Step one: Create a member

    Either create a new member to connect to the same MX Bank institution, or use update member to update an existing test member's credentials.

    # The login credentials given below will mimic an aggregation challenged by MFA.
    
    curl -i -X POST 'https://vestibule.mx.com/users/{user_guid}/members' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
      -d '{
            "member": {
              "institution_code": "mxbank",
              "credentials": [
                {
                  "guid": "CRD-9f61fb4c-912c-bd1e-b175-ccc7f0275cc1",
                  "value": "test_atrium"
                },
                {
                  "guid": "CRD-e3d7ea81-aac7-05e9-fbdd-4b493c6e474d",
                  "value": "challenge"
                }
              ]
            }
          }'
    

    Response

    {
      "member":
      {
        "status":"INITIATED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:45:48+00:00",
        "identifier":null,
        "successfully_aggregated_at":null
      }
    }
    

    Step two: Check the member status

    Request

    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"CHALLENGED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "challenges":
        [
          {
            "field_name":null,
            "guid":"CRD-f61b2add-df2e-3ac0-b7ee-a7d5cbfad3f7",
            "label":"What city were you born in?",
            "type":"TEXT"
          }
        ],
        "aggregated_at":"2017-09-06T16:45:48+00:00",
        "successfully_aggregated_at":null,
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Step three: Resume aggregation

    Answer the MFA question incorrectly. Clearly, the idea is to answer challenges correctly; however, it is still important to test this situation.

    Request

    # We're answering the challenge incorrectly for testing purposes.
    
    curl -i -X PUT 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/resume' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
      -d '{
            "member":{
              "challenges":[
                {
                   "guid": "CRD-f61b2add-df2e-3ac0-b7ee-a7d5cbfad3f7",
                   "value": "asdf"
                }
              ]
            }
          }'
    

    Response

    {
      "member":
      {
        "status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:45:48+00:00",
        "identifier":null,
        "successfully_aggregated_at":null
      }
    }
    

    Step four: Poll the member status

    Request

    # Poll the member status to determine next steps.
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"DENIED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "aggregated_at":"2017-09-06T16:45:48+00:00",
        "successfully_aggregated_at":null,
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    
    # NOTE: The status was polled once because DENIED is considered an end state; it won't change until another aggregation happens.
    

    Step five: Re-aggregate the member

    # Because of the DENIED member status, member must be re-aggregated.
    curl -i -X POST 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/aggregate'   -H 'Accept: application/vnd.mx.atrium.v1+json'   -H 'MX-API-Key: {mx_api_key}'   -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:52:41+00:00",
        "identifier":null,
        "successfully_aggregated_at":null
      }
    }
    

    Step six: Poll the status again

    # Poll the member status again
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"CHALLENGED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "challenges":
        [
          {
            "field_name":null,
            "guid":"CRD-9226a95d-1d14-0a28-6907-03b2aed082dc",
            "label":"What city were you born in?",
            "type":"TEXT"
          }
        ],
        "aggregated_at":"2017-09-06T16:52:41+00:00",
        "successfully_aggregated_at":null,
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Step seven: Answer MFA correctly

    # NOTE: The following challenge GUID is different from the previous GUID.
    curl -i -X PUT 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/resume' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}' \
      -d '{
            "member":{
              "challenges":[
                {
                   "guid": "CRD-9226a95d-1d14-0a28-6907-03b2aed082dc",
                   "value": "correct"
                }
              ]
            }
          }'
    

    Response

    {
      "member":
      {"status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:52:41+00:00",
        "identifier":null,
        "successfully_aggregated_at":null
      }
    }
    

    Step eight: Poll the status yet again

    Request

    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"AUTHENTICATED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "aggregated_at":"2017-09-06T16:52:41+00:00",
        "successfully_aggregated_at":null,
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Step nine: Poll that sweet, sweet status one more time

    Request

    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"COMPLETED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "aggregated_at":"2017-09-06T16:52:41+00:00",
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00",
        "has_processed_accounts":true,
        "has_processed_transactions":true
      }
    }
    
    # NOTE: The member status is now in an end state.
    # There is no need to poll again.
    
    

    Testing multiple-question MFA

    Step one: Aggregate the member

    Request

    # NOTE: This example assumes that you have already created a test member with the password "challenge".
    curl -i -X POST 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/aggregate' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "identifier":null,
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00"
      }
    }
    

    Step two: Party like it's time to poll the status

    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"CHALLENGED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "challenges":
        [
          {
            "field_name":null,
            "guid":"CRD-a2f8c49a-f314-262f-e674-8b163e254c89",
            "label":"What city were you born in?",
            "type":"TEXT"
          }
        ],
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00",
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Step three: Answer the challenge question

    # Answering with the value "challenge" will successfully answer the current MFA question and trigger a follow-up question.
    curl -i -X PUT 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/resume' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
      -d '{
            "member":{
              "challenges":[
                {
                   "guid": "CRD-a2f8c49a-f314-262f-e674-8b163e254c89",
                   "value": "challenge"
                }
              ]
            }
          }'
    

    Response

    # NOTE: The member goes back to status requested.
    
    {
      "member":
      {
        "status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "identifier":null,
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00"
      }
    }
    

    Step four: Poll that status like it's hot

    # The status is CHALLENGED because a second question needs to be answered.
    
    {
      "member":
      {
        "status":"CHALLENGED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "challenges":
        [
          {
            "field_name":null,
            "guid":"CRD-fa61ff9b-c446-7878-73bd-d2efc58d516a",
            "label":"What city were you born in?",
            "type":"TEXT"
          }
        ],
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00",
        "has_processed_accounts":false,
        "has_processed_transactions":false
      }
    }
    

    Step five: Answer the second MFA question correctly

    curl -i -X PUT 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/resume' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'Content-Type: application/json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
      -d '{
            "member":{
              "challenges":[
                {
                   "guid": "CRD-fa61ff9b-c446-7878-73bd-d2efc58d516a",
                   "value": "correct"
                }
              ]
            }
          }'
    

    Response

    {
      "member":
      {
        "status":"REQUESTED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "institution_code":"mxbank",
        "metadata":null,
        "name":"MX Bank",
        "user_guid":"USR-767a5dd1-e243-2942-8717-20e89a7936f0",
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "identifier":null,
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00"
      }
    }
    

    Step six: Poll the status like it's an election year

    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"TRANSFERRED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "successfully_aggregated_at":"2017-09-06T16:55:08+00:00",
        "has_processed_accounts":true,
        "has_processed_transactions":true
      }
    }
    
    # Status is not in an end state; poll your heart out.
    
    curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/MBR-69691bf0-fc09-d876-284e-a8ea0165c04f/status' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Response

    {
      "member":
      {
        "status":"COMPLETED",
        "guid":"MBR-69691bf0-fc09-d876-284e-a8ea0165c04f",
        "aggregated_at":"2017-09-06T16:59:37+00:00",
        "successfully_aggregated_at":"2017-09-06T17:00:45+00:00",
        "has_processed_accounts":true,
        "has_processed_transactions":true
      }
    }
    
    # Status is now COMPLETED. You can stop polling and pull account and transaction data.
    

    Support

    When you go to contact MX Support, please include the following information for the various member statuses:

    Issue type Associated member status Resolution
    MFA REJECTED
    EXPIRED
    Use the workflows given above to resolve any MFA issues. Contact support only if you have trouble successfully implementing them. If you do contact support, please send the following information:

    • Member GUID;
    • MFA type;
    • Attempted API request and response — with any personally-identifiable information removed.
    Credentials DENIED
    PREVENTED
    IMPAIRED
    Use the workflows given above to resolve credential-related issues. Contact support only if a user can successfully log in to their FI's online portal, but has tried unsuccessfully to update their credentials using Atrium. If you contact support, please send the following information:

    • Member GUID;
    • FI website login URL;
    • Credential character lengths;
    • Screenshots of a successful log in at the FI website.
    FI website LOCKED
    IMPEDED
    End-user action is required to address these situations; the end user must log in to their FI website and address the issue.
    Aggregation issues DEGRADED
    DISCONNECTED
    Most aggregation issues are temporary and resolve themselves within 24 hours. Contact MX Support only after a member has landed on one of these statuses for more than two days. If you do contact support, please send the following information:

    • Member GUID.
    Failed update na If you believe a member is missing transactions or failing to update, please send MX Support the following information:

    • Member GUID;
    • Account GUID;
    • Date, amount, and payee of missing transaction(s);
    •Screenshots of missing transition(s) from FI website.

    Product mailing list

    For updates on new features and developments with Atrium, make sure to check back here and on the documentation website regularly.

    You can also sign up to be notified of important changes by email or RSS at our product website, product.mx.com.