NAV Navbar
cURL Ruby
  • Verification overview
  • Create a user
  • Get the institution code
  • Get the institution's required credentials using the institution code
  • Create a member using institution code and required credentials
  • Poll the connection_status
  • Answer MFA, if necessary
  • Read account numbers
  • Verify a member
  • Testing Verification
  • Change log
  • Atrium Verification Guide

    Verification overview

    MX's account verification is offered in the context of the Atrium API and relies on the resources of that RESTful API to function properly. Specifically, this means following the general workflow below:

    1. Creating a user;
    2. Creating a member using the correct institution code and credentials required by that institution;
    3. Polling the member's connection_status and answering MFA if necessary (a member aggregates automatically when it is created);
    4. Reading the member's account_numbers (you may begin with this step for members that already exist);
    5. Calling the verify endpoint, if needed, ;
    6. Repeating steps 3 and 4.

    One reason for this workflow is that account and routing information is sometimes available through normal aggregation; in these cases, there would be no need to incur the cost of calling the verify endpoint.

    For important information on errors, standards and conventions, and resource structure in Atrium, please see our technical reference page.

    Create a user

    Endpoint: POST /users

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    user = ::Atrium::User.create identifier: "unique_id", is_disabled: "", metadata: "{\"first_name\": \"Steven\"}"
    puts user.attributes
    
    $ 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
    
    {
      "guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54",
      "identifier"=>"unique_id",
      "is_disabled"=>false,
      "metadata"=>"{\"first_name\": \"Steven\"}"
    }
    
    {
      "user": {
        "guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54",
        "identifier": "unique_id",
        "is_disabled": false,
        "metadata": "{\"first_name\": \"Steven\"}"
      }
    }
    

    For further details on users, click here.

    Get the institution code

    Endpoint: GET /institutions

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    institution = ::Atrium::Institution.read institution_code: "chase"
    puts institution.attributes
    
    $ curl -i -X GET 'https://vestibule.mx.com/institutions?name=chase' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Example response:

    Status: 200 OK
    
    {
      "code"=>"chase",
      "name"=>"Chase Bank",
      "url"=>"https://www.chase.com",
      "small_logo_url"=>"https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/100x100/default_100x100.png",
      "medium_logo_url"=>"https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/50x50/default_50x50.png",
      "supports_account_identification"=>true,
      "supports_account_verification"=>true
    }
    
    {
      "institutions": [
        {
          "code": "chase",
          "medium_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/100x100/default_100x100.png",
          "name": "Chase Bank",
          "small_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/50x50/default_50x50.png",
          "supports_account_identification": true,
          "supports_account_verification": true,
          "url": "https://www.chase.com",
        }
      ]
    }
    

    Only certain institutions support verification. To get a list of all institutions which support verification, append the following query string to your request URL: supports_account_verification=true.

    For further details on institutions, click here.

    Get the institution's required credentials using the institution code

    Endpoint: GET /institutions/{institution_code}/credentials

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    credentials = ::Atrium::Institution.credentials "chase"
    credentials.each do |credential|
      puts credential.attributes
    end
    
    $ curl -i -X GET 'https://vestibule.mx.com/institutions/chase/credentials' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Example response

    Status: 200 OK
    
    {
      "field_name"=>"LOGIN",
      "guid"=>"CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
      "label"=>"Username",
      "type"=>"LOGIN",
      "value"=>nil
    }
    {
      "field_name"=>"PASSWORD",
      "guid"=>"CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
      "label"=>"Password",
      "type"=>"PASSWORD",
      "value"=>nil
    }
    
    {
      "credentials": [
        {
          "field_name": "LOGIN",
          "guid": "CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
          "label": "Username",
          "type": "LOGIN"
        },
        {
          "field_name": "PASSWORD",
          "guid": "CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
          "label": "Password",
          "type": "PASSWORD"
        }
      ]
    }
    

    Create a member using institution code and required credentials

    Endpoint: POST /users/{user_guid}/members

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    credentialOne = {}
    credentialOne[:guid] = "CRD-598ec8d4-6200-8cda-345d-3dbb5fc17716"
    credentialOne[:value] = "username"
    
    credentialTwo = {}
    credentialTwo[:guid] = "CRD-27d0edb8-1d50-5b90-bcbc-be270ca42b9f"
    credentialTwo[:value] = "password"
    
    credentialArray = []
    credentialArray.push(credentialOne)
    credentialArray.push(credentialTwo)
    
    member = ::Atrium::Member.create user_guid: "{user_guid}", institution_code: "chase", credentials: credentialArray
    puts member.attributes
    
    $ 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": "chase",
              "credentials": [
                {
                  "guid": "CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
                  "value": "ExampleUsername"
                },
                {
                  "guid": "CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
                  "value": "Pa$$vv@Rd"
                }
              ],
              "skip_aggregation": true
            }
          }'
    

    Example response:

    Status: 202 Accepted
    
    {
      "aggregated_at"=>"2016-10-13T17:57:36+00:00",
      "challenges"=>nil,
      "guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "has_processed_accounts"=>nil,
      "has_processed_transactions"=>nil,
      "identifier"=>"unique_id",
      "institution_code"=>"chase",
      "is_being_aggregated"=>true,
      "metadata"=>"{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
      "name"=>"Chase Bank",
      "status"=>"INITIATED",
      "successfully_aggregated_at"=>nil,
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
      "member": {
        "aggregated_at": "2016-10-13T17:57:36+00:00",
        "connection_status": "CREATED",
        "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
        "identifier": "unique_id",
        "institution_code": "chase",
        "is_being_aggregated": true,
        "metadata": "{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
        "name": "Chase Bank",
        "status": "INITIATED",
        "successfully_aggregated_at": null,
        "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
      }
    }
    

    Creating a member automatically starts aggregation unless the skip_aggregation parameter is set to true in the request body. On already-existing members for which standard aggregation did not return account information, you can use the verify endpoint described below.

    For further details on members, click here

    Poll the connection_status

    Endpoint: GET /users/{user_guid}/members/{member_guid}/status

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    member = member.aggregation_status
    puts member.attributes
    
    $ 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}'
    

    Example response:

    {
      "aggregated_at"=>"2016-10-13T18:07:57+00:00",
      "challenges"=>nil,
      "guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "has_processed_accounts"=>true,
      "has_processed_transactions"=>false,
      "identifier"=>"unique_id",
      "institution_code"=>"chase",
      "is_being_aggregated"=>true,
      "metadata"=>"{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
      "name"=>"Chase Bank",
      "status"=>"COMPLETED",
      "successfully_aggregated_at"=>"2016-10-13T17:57:38+00:00",
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    Status: 200 OK
    
    {
      "member": {
        "aggregated_at": "2016-10-13T18:07:57+00:00",
        "connection_status": "CONNECTED",
        "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
        "has_processed_accounts": true,
        "has_processed_transactions": false,
        "identifier": "unique_id",
        "institution_code": "chase",
        "is_being_aggregated": false,
        "metadata": "{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
        "name": "Chase Bank",
        "status": "COMPLETED",
        "successfully_aggregated_at": "2016-10-13T17:57:38+00:00",
        "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
      }
    }
    

    A connection status of CONNECTED means that the member was successfully authenticated and aggregation has begun. The is_being_aggregated field will tell you whether aggregation has completed; the field will be true while aggregation is taking place and returns to false when aggregation is complete.

    For further information on connection_status, click here

    Answer MFA, if necessary

    Endpoint: GET /users/{user_guid}/members/member_guid}/challenges

    Example request for challenges:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    member = member.mfa_challenges
    puts member.attributes
    
    $ curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/challenges' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Example response for credential type TEXT:

    Status: 200 OK
    
    {
      "field_name"=>"Who is this guy?",
      "guid"=>"CRD-ce76d2e3-86bd-ec4a-ec52-eb53b5194bf5",
      "label"=>"Who is this guy?",
      "type"=>"IMAGE_DATA",
      "image_data"=>"data:image/png;base64,iVBORw0KGgoAAAANSUh ... more image data ...",
      "options"=>nil
    }
    
    {
      "challenges": [
        {
          "field_name": "What city were you born in?",
          "guid": "CRD-1ec152cd-e628-e81a-e852-d1e7104624da",
          "label": "What city were you born in?",
          "type": "TEXT"
        }
      ]
    }
    

    Endpoint PUT /users/{user_guid}/members/{member_guid}/resume

    Example request to resume aggregation:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    
    credentialOne = {}
    credentialOne[:guid] = "institution-credential-guid"
    credentialOne[:value] = "user-entered-value"
    
    credentialTwo = {}
    credentialTwo[:guid] = "institution-credential-guid"
    credentialTwo[:value] = "user-entered-value"
    
    challengeResponses = []
    challengeResponses.push(credentialOne)
    challengeResponses.push(credentialTwo)
    
    member = member.resume challengeResponses
    puts member.attributes
    
    $ curl -i -X PUT 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/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-1ec152cd-e628-e81a-e852-d1e7104624da",
                   "value": "Chicago"
                }
              ]
            }
          }'
    

    Example response for resumed aggregation:

    Status: 202 Accepted
    
    {
      "aggregated_at"=>"2016-09-30T14:31:45-06:00",
      "challenges"=>nil,
      "guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "has_processed_accounts"=>nil,
      "has_processed_transactions"=>nil,
      "identifier"=>"unique_id",
      "institution_code"=>"chase",
      "is_being_aggregated"=>true,
      "metadata"=>"{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
      "name"=>"Chase Bank",
      "status"=>"CHALLENGED",
      "successfully_aggregated_at"=>nil,
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
      "member": {
        "aggregated_at": "2016-09-30T14:31:45-06:00",
        "connection_status": "CHALLENGED",
        "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
        "identifier":"unique_id",
        "institution_code": "chase",
        "is_being_aggregated": true,
        "metadata": "{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
        "name": "Bank Name",
        "status": "CHALLENGED",
        "successfully_aggregated_at": null,
        "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
      }
    }
    

    Endpoint: GET /users/{user_guid}/members/{member_guid}/status

    Example request to poll connection status:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    member = member.aggregation_status
    puts member.attributes
    
    $ 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}'
    

    Example response:

    Status: 200 OK
    
    {
      "aggregated_at"=>"2016-10-13T18:07:57+00:00",
      "challenges"=>nil,
      "guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "has_processed_accounts"=>true,
      "has_processed_transactions"=>false,
      "identifier"=>"unique_id",
      "institution_code"=>"chase",
      "is_being_aggregated"=>true,
      "metadata"=>"{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
      "name"=>"Chase Bank",
      "status"=>"COMPLETED",
      "successfully_aggregated_at"=>"2016-10-13T17:57:38+00:00",
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
      "member": {
        "aggregated_at": "2016-10-13T18:07:57+00:00",
        "connection_status": "CONNECTED",
        "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
        "has_processed_accounts": true,
        "has_processed_transactions": false,
        "identifier": "unique_id",
        "institution_code": "chase",
        "is_being_aggregated": false,
        "metadata": "{\"credentials_last_refreshed_at\": \"2015-10-15\"}",
        "name": "Chase Bank",
        "status": "COMPLETED",
        "successfully_aggregated_at": "2016-10-13T17:57:38+00:00",
        "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
      }
    }
    

    If the connection_status returns as CHALLENGED during polling, it will be necessary to answer multi-factor authentication in order to continue. This requires calling the list member MFA challenges endpoint and the resume aggregation from MFA endpoint, then polling the connection_status again.

    Further details on MFA, see our technical reference or our troubleshooting guide.

    Read account numbers

    Account numbers can be accessed either through a member or through a specific account. Both paths are shown below.

    Endpoint: GET /users/{user_guid}/members/{member_guid}/account_numbers

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    account_numbers = member.account_numbers
    account_numbers.each do |account_number|
      puts account_number.attributes
    end
    
    $ curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/account_numbers' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Example response:

    Status: 200 OK
    
    {
      "account_guid"=>"ACT-123",
      "account_number"=>"10001",
      "routing_number"=>"68899990000000",
      "member_guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
      "account_numbers": [
        {
          "account_guid": "ACT-123",
          "account_number": "10001",
          "routing_number": "68899990000000",
          "member_guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
            "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
        }
      ]
    }
    

    Endpoint: GET /users/{user_guid}/accounts/{account_guid}/account_numbers

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    account = ::Atrium::Account.read user_guid: "{user_guid}", account_guid: "{account_guid}"
    account_numbers = account.account_numbers
    account_numbers.each do |account_number|
      puts account_number.attributes
    end
    
    $ curl -i -X GET 'https://vestibule.mx.com/users/{user_guid}/accounts/{account_guid}/account_numbers' \
      -H 'Accept: application/vnd.mx.atrium.v1+json' \
      -H 'MX-API-Key: {mx_api_key}' \
      -H 'MX-Client-ID: {mx_client_id}'
    

    Example response:

    Status: 200 OK
    
    {
      "account_guid"=>"ACT-123",
      "account_number"=>"10001",
      "routing_number"=>"68899990000000",
      "member_guid"=>"MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
      "user_guid"=>"USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
      "account_numbers": [
        {
          "account_guid": "ACT-123",
          "account_number": "10001",
          "routing_number": "68899990000000",
          "member_guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
            "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
        }
      ]
    }
    

    Verify a member

    Endpoint: POST /users/{user_guid}/members/{member_guid}/verify

    Example request:

    ::Atrium.configure do |config|
      config.mx_client_id = "YOUR_MX_CLIENT_ID"
      config.mx_api_key = "YOUR_MX_API_KEY"
    end
    
    member = ::Atrium::Member.read user_guid: "{user_guid}", member_guid: "{member_guid}"
    member = member.verify
    puts member.attributes
    
    curl -i -X POST 'https://vestibule.mx.com/users/{user_guid}/members/{member_guid}/verify' \
      -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}'
    

    Example response:

    Status: 200 OK
    
    {
        "aggregated_at": "2018-06-25T20:04:19Z",
        "connection_status": "CONNECTED",
        "identifier": "chase_ds",
        "status": "INITIATED",
        "successfully_aggregated_at": "2018-06-25T19:45:01Z",
        "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
        "institution_code": "6930ee63-16b3-fc5e-ab48-18bbc39379d0",
        "is_being_aggregated": true,
        "metadata": null,
        "name": "chase ds",
        "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
    }
    
    {
        "member": {
            "aggregated_at": "2018-06-25T20:04:19Z",
            "connection_status": "CONNECTED",
            "identifier": "chase_ds",
            "status": "INITIATED",
            "successfully_aggregated_at": "2018-06-25T19:45:01Z",
            "guid": "MBR-7c6f361b-e582-15b6-60c0-358f12466b4b",
            "institution_code": "6930ee63-16b3-fc5e-ab48-18bbc39379d0",
            "is_being_aggregated": true,
            "metadata": null,
            "name": "chase ds",
            "user_guid": "USR-fa7537f3-48aa-a683-a02a-b18940482f54"
        }
    }
    

    The verify endpoint begins a verification process for an already-existing member.

    Testing Verification

    To test your setup without incurring the cost of calling the verify endpoint, Atrium has test endpoints available.

    Simply modify the URL to contain the user GUID test_atrium and the member GUID test_atrium_member.

    The endpoint URLs will then be as follows:

    /users/test_atrium/members/test_atrium_member/verify
    /users/test_atrium/members/test_atrium_member/account_numbers

    Change log

    Change information for all Atrium documentation can be found here.