What Are Partner-Managed Resources?

Rather than relying on our aggregation services to bring in your held account and transaction data, you can manage all that yourself — down to the last detail — with partner-managed resources.

This guide will take you through the process of adding one of your held transactions using the Platform API. We’ll also outline best practices and cover common problems you might run into.


The MX Data Architecture

Every resource on the MX platform has to fit into our existing data architecture. For instance, every transaction belongs to an account, every account belongs to a member, and every member belongs to a user. So, before we can deal with the transactions we’re most interested in, we need to deal with users, members, and accounts — in that order.

You’ll also want to think about what your ultimate use case is going to be. Each of these four resources (users, members, accounts, and transactions) have many attributes that you can set, but not all of those attributes will be useful for every case, and some of them depend on other attributes. So, you’ll need to know exactly what information you plan on sending to MX and how it’s going to fit into the product you’re building with the Platform API.


Workflow

Here’s a general workflow for creating your first transaction with held data:

  1. Create a user (which represents your customer).
  2. Create a member belonging to that user (which represents the connection between the user and your special institution).
  3. Create an account (which represents the account the customer holds with you).
  4. Create a transaction (which represents any instance in which money moves into or out of your customer’s account).

Other workflows

Once all those resources exist, workflows are mostly about updating accounts and transactions to reflect the latest information — like increasing an account balance after a paycheck is deposited, or, for that matter, creating a new transaction to represent that deposited paycheck.


1. Create a User

The first step is to create a user. A user represents your end user in the MX Platform. Make a POST request to the create user endpoint, as shown below.

We recommend that you include a unique id of your choice with the request. You may also include metadata, such as the date the user was created or the end user’s name. Don’t include any sensitive information here, such as credentials.

In the response, the API gives each new user an MX-defined guid (or user_guid when appearing outside the user object). Between your id and the guid, you can map between your system and ours. You’ll need the user guid for nearly every request on the MX API, at least when using basic authorization.

1
2
3
4
5
6
7
8
9
10
11
12
curl -i -X POST 'https://int-api.mx.com/users' \
-u 'client_id:api_key' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Content-Type: application/json' \
-d '{
      "user": {
        "id": "partner-2345",
        "is_disabled": false,
        "email": "totally.fake.email@notreal.com",
        "metadata": "Yada yada yada"
      }
    }'
1
2
3
4
5
6
7
8
9
{
  "user": {
    "email": "totally.fake.email@notreal.com",
    "guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c",
    "id": "partner-2345",
    "is_disabled": false,
    "metadata": "Yada yada yada"
  }
}

2. Create a Managed Member


2.1 List the Available Institutions

This endpoint lists the institutions that you are allowed to use for creating managed members. You’ll most likely have only one available institution, but you may have a use case that requires more; this is determined when enabling managed data with MX.

You shouldn’t need to perform this step often since your list of available institutions won’t often change. Feel free to work from a cached list.

Capture the institution_code that gets returned. You’ll use it in step 2.2.

Endpoint:

GET /managed_institutions

1
2
3
curl -i 'https://int-api.mx.com/managed_institutions' \
-u 'client_id:api_key' \
-H 'Accept: application/vnd.mx.api.v1+json'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
  "institutions": [
    {
      "code": "partnerinstitutioncode",
      "instructional_text": null,
      "medium_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/100x100/default_100x100.png",
      "name": "Partner Institution",
      "small_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/50x50/default_50x50.png",
      "supports_account_identification": false,
      "supports_account_statement": false,
      "supports_account_verification": false,
      "supports_oauth": false,
      "supports_transaction_history": false,
      "url": "https://PrtnerInstitutionWebsite.com"
    },
    {
      "code": "mxbank",
      "instructional_text": null,
      "medium_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/100x100/INS-1572a04c-912b-59bf-5841-332c7dfafaef_100x100.png",
      "name": "MX Bank",
      "small_logo_url": "https://content.moneydesktop.com/storage/MD_Assets/Ipad%20Logos/50x50/INS-1572a04c-912b-59bf-5841-332c7dfafaef_50x50.png",
      "supports_account_identification": true,
      "supports_account_statement": false,
      "supports_account_verification": true,
      "supports_oauth": false,
      "supports_transaction_history": true,
      "url": "https://www.mx.com"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 30,
    "total_entries": 2,
    "total_pages": 1
  }
}

2.2 Create a Member

Now that we’ve got a user_guid and your institution_code, we can create a member. As with creating a user, MX strongly encourages you to give the member a unique id so you can match the data on your systems with our systems.

If the request is successful, the response will contain the newly created member.

See the API reference for more detailed information on each parameter.

Field Data type Required?
id String No
institution_code String Yes (This should always be set to your default institution.)
metadata String No
name String No

Endpoint:

POST /users/{user_guid}/managed_members

1
2
3
4
5
6
7
8
9
10
11
curl -i -X POST 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/managed_members' \
  -u 'client_id:api_key' \
  -H 'Accept: application/vnd.mx.api.v1+json' \
  -H 'Content-Type: application/json' \
  -d '{
        "member": {
            "institution_code": "mxbank",
            "id": "partner-1234",
            "metadata": "this and that"
        }
      }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "member": {
    "aggregated_at": null,
    "connection_status": "CONNECTED",
    "guid": "MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e",
    "id": "partner-1234",
    "institution_code": "aef89293-88d9-42e6-82a2-0a2b14fe7667",
    "is_being_aggregated": false,
    "is_managed_by_user": false,
    "is_oauth": false,
    "metadata": "this and that",
    "name": null,
    "successfully_aggregated_at": null,
    "user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c",
    "user_id": "partner-2345"
  }
}

3. Create a Managed Account

Now we have a member, so it’s time to create an account.

Remember that a member represents the overall connection between your institution and the end user. So, if they open a new account with you, you don’t want to create a new member; you want to attach a new account to the member you just created. In other words, members can have multiple accounts, each one representing an account that user has with you: one for their savings account, another for their checking, another for their mortgage, etc.

See the API reference for more detailed information on each parameter.

Parameters Required?
account_number No
apr No
apy No
available_balance No
available_credit No
balance Yes
cash_surrender_value No
credit_limit No
currency_code No
day_payment_is_due No
death_benefit No
id No
interest_rate No
is_closed No
is_hidden No
last_payment_at No
last_payment No
loan_amount No
matures_on No
metadata No
minimum_balance No
minimum_payment No
name Yes
nickname No
original_balance No
payment_due_at No
payoff_balance No
routing_number No
started_on No
subtype No
type Yes

Endpoint:

POST /users/{user_guid}/managed_members/{member_guid}/accounts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl -i -X POST 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/managed_members/MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e/accounts' \
-u 'client_id:api_key' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Content-Type: application/json' \
-d'{
      "account": {
        "account_number": "12345",
        "balance": "10000",
        "id": "partner-account-7890",
        "is_closed": false,
        "metadata": "some metadata",
        "name": "Swiss Bank Acct",
        "nickname": "Swiss Account",
        "started_on": "1980-03-28",
        "subtype": "MONEY_MARKET",
        "type": "SAVINGS"
      }
    }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
  "account": {
    "account_number": "12345",
    "apr": null,
    "apy": null,
    "available_balance": 10000.00,
    "available_credit": null,
    "balance": 10000.00,
    "cash_balance": null,
    "cash_surrender_value": null,
    "created_at": "2021-08-31T18:17:44Z",
    "credit_limit": null,
    "currency_code": null,
    "day_payment_is_due": null,
    "death_benefit": null,
    "guid": "ACT-1e194555-a690-44ec-b363-282165cf4dab",
    "holdings_value": null,
    "id": "partner-account-7890",
    "institution_code": "mxbank",
    "interest_rate": null,
    "insured_name": null,
    "is_closed": false,
    "is_hidden": false,
    "last_payment": null,
    "last_payment_at": null,
    "loan_amount": null,
    "matures_on": null,
    "member_guid": "MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e",
    "metadata": "some metadata",
    "minimum_balance": null,
    "minimum_payment": null,
    "name": "Swiss Bank Acct",
    "nickname": null,
    "original_balance": null,
    "pay_out_amount": null,
    "payment_due_at": null,
    "payoff_balance": null,
    "premium_amount": null,
    "routing_number": null,
    "started_on": "1980-03-28",
    "subtype": "MONEY_MARKEY",
    "total_account_value": null,
    "type": "SAVINGS",
    "updated_at": "2021-08-31T18:17:44Z",
    "user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c"
  }
}

4. Create a Managed Transaction

Now that you have a user, member, and account, you can create a transaction.

This example represents a deposit into a savings account.

See the API reference for more detailed information on each parameter.

Field Data type Required?
amount String Yes
category String No
category_guid String No
check_number_string String No
currency_code String No
description String Yes
id String No
is_international String No
latitude String No
localized_description String No
localized_memo String No
longitude String No
memo String No
metadata String No
merchant_category_code String No
merchant_guid String No
merchant_location_guid String No
posted_at String No
status String Yes
transacted_at String Yes
type String Yes

Endpoint:

POST /users/{user_guid}/managed_members/{managed_member_guid}/accounts/{account_guid}/transactions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl -L -X POST 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/managed_members/MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e/accounts/ACT-09c0ee66-51a8-4edf-b977-99534a471134/transactions' \
  -u 'client_id:api_key' \
  -H 'Accept: application/vnd.mx.api.v1+json' \
  -H 'Content-Type: application/json' \
  -d '{
        "transaction": {
            "id": "partner-transaction-3QP5X0",
            "status": "PENDING",
            "type": "CREDIT",
            "amount": 400,
            "description": "Savings Deposit",
            "is_international": false,
            "transacted_at": "2021-09-01T12:00:00Z",
            "category": "INCOME",
            "latitude": 40.429675,
            "longitude": -111.891982
        }
      }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
  "transaction": {
    "account_guid": "ACT-1e194555-a690-44ec-b363-282165cf4dab",
    "account_id": "1",
    "amount": 8.2,
    "category": "Gas",
    "category_guid": "CAT-b6d63a19-30a7-e852-2703-bdfb4072289e",
    "check_number_string": "9543",
    "created_at": "2020-06-28T12:00:00Z",
    "currency_code": "USD",
    "date": "2020-03-02",
    "description": "Costcoo Gas",
    "guid": "TRN-181ce5d9-d33e-45b9-a9cd-8f8ef9d82d5d",
    "id": "T-3QP5X0",
    "is_bill_pay": false,
    "is_direct_deposit": false,
    "is_expense": false,
    "is_fee": false,
    "is_income": true,
    "is_international": false,
    "is_overdraft_fee": false,
    "is_payroll_advance": false,
    "is_recurring": false,
    "is_subscription": false,
    "latitude": "40.429675",
    "localized_description": null,
    "localized_memo": null,
    "longitude": "-111.891982",
    "member_guid": "MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e",
    "memo": "POS Purchase",
    "merchant_category_code": null,
    "merchant_guid": "MCH-bcd4eed1-f341-b7bb-4cbd-e2a854205306",
    "merchant_location_guid": null,
    "metadata": null,
    "original_description": "COSTCO GAS STATION #22299",
    "posted_at": null,
    "status": null,
    "top_level_category": "Car & Auto",
    "transacted_at": "2020-06-28T12:00:00Z",
    "type": "DEBIT",
    "updated_at": "2020-06-28T12:00:00Z",
    "user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c",
    "user_id": "U-39XBF7"
  }
}

5. Update a Managed Resource

You can now update the account you created so its balance reflects the deposit we just recorded by creating a new transaction. The account balance was $10,000 before, and you just deposited $400.

Endpoint:

PUT /users/{user_guid}/managed_members/{member_guid}/accounts/{account_guid}

1
2
3
4
5
6
7
8
9
curl -i -X PUT 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/managed_members/MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e/accounts/ACT-1e194555-a690-44ec-b363-282165cf4dab' \
-u 'client_id:api_key' \
-H 'Accept: application/vnd.mx.api.v1+json' \
-H 'Content-Type: application/json' \
-d '{
      "account": {
        "balance": 10400.00
      }
    }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
  "account": {
    "account_number": "12345",
    "apr": null,
    "apy": null,
    "available_balance": 10000.00,
    "available_credit": null,
    "balance": 10400.00,
    "cash_balance": null,
    "cash_surrender_value": null,
    "created_at": "2021-08-31T18:17:44Z",
    "credit_limit": null,
    "currency_code": null,
    "day_payment_is_due": null,
    "death_benefit": null,
    "guid": "ACT-1e194555-a690-44ec-b363-282165cf4dab",
    "holdings_value": null,
    "id": "partner-account-7890",
    "institution_code": "mxbank",
    "interest_rate": null,
    "insured_name": null,
    "is_closed": false,
    "is_hidden": false,
    "last_payment": null,
    "last_payment_at": null,
    "loan_amount": null,
    "matures_on": null,
    "member_guid": "MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e",
    "metadata": "some metadata",
    "minimum_balance": null,
    "minimum_payment": null,
    "name": "Swiss Bank Acct",
    "nickname": null,
    "original_balance": null,
    "pay_out_amount": null,
    "payment_due_at": null,
    "payoff_balance": null,
    "premium_amount": null,
    "routing_number": null,
    "started_on": "1980-03-28",
    "subtype": "MONEY_MARKEY",
    "total_account_value": null,
    "type": "SAVINGS",
    "updated_at": "2021-09-01T18:20:37Z",
    "user_guid": "USR-11141024-90b3-1bce-cac9-c06ced52ab4c"
  }
}

6. Delete a Managed Resource

Marking an account as closed or temporarily disabling a user might be better than deleting an account or user since you can still restore the data. But sometimes, deletes are necessary.

You won’t get a response body with a delete request. The status will be 204 No Content if it’s successful.

Endpoint:

DELETE /users/{user_guid}/managed_members/{member_guid}

1
2
3
curl -i -X DELETE 'https://int-api.mx.com/users/USR-11141024-90b3-1bce-cac9-c06ced52ab4c/managed_members/MBR-e6239750-24e8-4833-93a8-d4c2ecf2ec7e' \
  -u 'client_id:api_key' \
  -H 'Accept: application/vnd.mx.api.v1+json'

Dealing with Pending and Posted Transactions

Because you are in full control of your held data with partner-managed resources, you are also responsible for reconciling pending and posted transactions. There are two different strategies for doing this:

  1. The ideal case: Keep the same transaction and update it from a status of PENDING to a status of POSTED.
  2. The other case: Delete all PENDING transactions and create entirely new transactions with a status of POSTED.

The Ideal Case

The best case scenario is to keep the existing Platform transaction and update it from PENDING to POSTED. This means the transaction will maintain the same GUID assigned by MX and ID assigned by you. If your systems use different IDs for associated pending/posted transactions, you’re free to update the ID in the Platform API as well.

This also means that if the end user has made any updates while the transaction was PENDING (like recategorizing it or changing the description), those end-user changes will be maintained.

If a PENDING transaction never becomes POSTED on your end, then you should simply delete the PENDING platform transaction.

Ideal pending to posted path


The Other Case

This strategy is necessary for partners who are unable to confidently tie pending and posted transactions together on their own systems.

In this scenario, you will need to delete every PENDING transaction you create on the Platform API. Only POSTED transactions should persist. It also means that any end-user changes to the pending transaction will be lost when it is deleted. In this scenario you may even consider disallowing end-user updates to PENDING transactions.

PENDING transactions should be deleted at the same time as the new POSTED transaction is created, or as close to it as possible. This is to prevent end users from seeing a both a pending and posted version of the same transaction.

Alternative scenario for dealing with pending transactions