MDX On Demand v5
MDX On Demand v5 is a proprietary specification for the RESTful exchange of data between financial institutions and MX.
Data providers implement the MDX On Demand API for the purpose of allowing MX to synchronize account and transaction data with the MX Platform.
MDX On Demand supports XML encoding of the request and response bodies. JSON encoding is not supported at this time.
An MDX On Demand session will start with a request to the sessions endpoint to authenticate the user. Additional endpoints are used to request account and transaction information once the user is authenticated.
Base URL
All endpoints in the MDX On Demand API have the following base URL:
https://{partner_base_url}/{institution_id}
The partner_base_url varies with each implementation and is provided to MX by you, the partner. The base URL may contain a port if needed.
The institution_id identifies the financial institution for which the request is made. The institution_id is provided to MX by you. In many integrations — especially those for an online banking provider — the client is a financial institution. In these cases it is recommended to use the same value for the client_id and the institution_id to avoid confusion; however, different values can be used if needed.
HTTPS
All API requests must be made over HTTPS. Calls made to your implementation of the API over plain HTTP should fail. 256-bit SSL or greater is preferred.
Versioning
The MDX version will change as the specification is updated. On Demand requests will specify the version expected in the response. Data providers may wish to support multiple MDX versions as they upgrade from one version to another.
Requests that don't specify a version should return the latest representation of resources. Unsupported endpoints should simply return HTTP 404 NOT FOUND.
Accept Header
All requests will have an Accept header that specifies the encoding and the version being requested.
Accept: application/vnd.moneydesktop.mdx.v5+xml
Content-Type Header
POST and PUT requests will include a Content-Type header to specify the encoding and the version of the request body. Your responses should include the same header.
Content-Type: application/vnd.moneydesktop.mdx.v5+xml
Job Type Header
An MDX-Job-Type header is provided with each request. The header identifies whether the request is being initiated by a user login or a background aggregation request to update the user's data. The provided value will be either foreground or background.
MDX-Job-Type: foreground
MDX-Job-Type: background
Sessions
When synchronizing accounts and transactions with MDX On Demand, a session key must first be obtained. MX will open a session with a request to the sessions endpoint.
When the session is established, the partner will return a session key to MX. MX will provide this session key in an MDX-Session-Key header in all subsequent requests during that session, as shown in the example.
If a request is made with an invalid session key, you should return a 401 (Unauthorized) error.
Example Session Request
_10$ curl -H "MDX-Session-Key: [SESSION_KEY]" https://dataprovider_base_url/:institution_id/accounts
Authentication
Every MDX On Demand request will include MDX-HMAC and Content-MD5 headers. If the HMAC signature or MD5 content do not match, you should return a 412 (precondition failed) error.
The HMAC key will be provided during your integration with MX and will be a 32- to 64-byte string. The length depends on the algorithm used. The key will be provided in base64 format since the key may contain non-printable characters. Supported algorithms are SHA1, SHA224, SHA256, SHA384, and SHA512.
MD5 Authentication
The Content-MD5 header is calculated by MD5 authenticating the body of each request. For GET requests without a body, you will use an empty string when computing the Content-MD5 value.
HMAC Signature
The MDX-HMAC header is composed using a string that is signed via HMAC. It is a canonical composition of the request's headers, the HTTP verb, and the REST resource.
The MDX-Session-Key value will be an empty string in requests to the sessions endpoint.
The REST Resource of the Request value will be the final portion of the URL. It will be one of these values:
/sessions/accounts/transactions/user/member/account_owner/account_number
Signature Pattern
_10HTTP VERB + "\n" + Content-MD5 Header + "\n" + Content-Type Header + "\n" + UNIX Epoch Date Time + "\n" + Accept Header + "\n" + MDX-Session-Key + "\n" + REST Resource of Request
HMAC Example
Given the information above, let's take a look at what a POST request to /sessions would look like.
_10POST /sessions "<?xml version=\"1.0\"?>\n<mdx version=\"5.0\">\n <session>\n <userkey><![CDATA[the-userkey]]></userkey>\n </session>\n</mdx>\n"_10Content-Type: application/vnd.moneydesktop.mdx.v5+xml_10Date: 1382975431_10Accept: application/vnd.moneydesktop.mdx.v5+xml_10MDX-Session-Key:
MD5 Hash
The MD5 hash would be computed using the body of the example above.
_10require 'digest/md5'_10digest = Digest::MD5.hexdigest("<?xml version=\"1.0\"?>\n<mdx version=\"5.0\">\n <session>\n <userkey><![CDATA[the-userkey]]></userkey>\n </session>\n</mdx>\n")_10puts digest_10=> "e9a179f879165fd64bdeaa57032d342f"
HMAC Signature
Now that we have our MD5 hash, we can take a look at our headers to compose our HMAC signature.
_10POST /sessions "<?xml version=\"1.0\"?>\n<mdx version=\"5.0\">\n <session>\n <userkey><![CDATA[the-userkey]]></userkey>\n </session>\n</mdx>\n"_10Content-MD5: e9a179f879165fd64bdeaa57032d342f_10Content-Type: application/vnd.moneydesktop.mdx.v5+xml_10Date: 1382975431_10Accept: application/vnd.moneydesktop.mdx.v5+xml_10MDX-Session-Key:
Canonical String
The canonical string to be signed can now be composed.
_10"POST\ne9a179f879165fd64bdeaa57032d342f\napplication/vnd.moneydesktop.mdx.v5+xml\n1382975431\napplication/vnd.moneydesktop.mdx.v5+xml\n\n/sessions"
Generated Signature
If your HMAC key (salt) was QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo3ODkwMTI=, the resulting signed signature would be generated as shown below.
The resulting signature is e47928dcd29e494116961ad12884c8fd7aae07f2. This signature will be provided in the MDX-HMAC header of our request.
_10require 'base64'_10require 'openssl'_10_10salt = 'QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo3ODkwMTI='_10digest = ::OpenSSL::Digest.new('sha1')_10hmac_signature = "POST\ne9a179f879165fd64bdeaa57032d342f\napplication/vnd.moneydesktop.mdx.v5+xml\n1382975431\napplication/vnd.moneydesktop.mdx.v5+xml\n\n/sessions"_10hmac = ::OpenSSL::HMAC.hexdigest(digest, ::Base64.decode64(salt), hmac_signature)_10puts hmac_10_10# => "e47928dcd29e494116961ad12884c8fd7aae07f2"
Session Request
We are now ready to compose our POST request to the /sessions endpoint.
_10POST /sessions "<?xml version=\"1.0\"?>\n<mdx version=\"5.0\">\n <session>\n <userkey><![CDATA[the-userkey]]></userkey>\n </session>\n</mdx>\n"_10Content-MD5: e9a179f879165fd64bdeaa57032d342f_10Content-Type: application/vnd.moneydesktop.mdx.v5+xml_10Date: 1382975431_10Accept: application/vnd.moneydesktop.mdx.v5+xml_10MDX-Session-Key:_10MDX-HMAC: e47928dcd29e494116961ad12884c8fd7aae07f2
HMAC Notes
The HMAC signature is generated in the MX system with lower-case letters in the hexadecimal representation. Some code libraries return the signature with upper-case letters. A ToLower or downcase applied to the signature may be required on your end before comparing it to the one provided in the request header. A case-insensitve comparison may also be used.
The base64 HMAC key in this example decodes to a 32-byte string. This is the ideal size for the SHA1 algorithm, although most libraries such as OpenSSL will accept other key lengths. SHA1 outputs a 40-character HMAC result. The length of the HMAC key and of the resulting signatures will vary if other algorithms are used.
IP Filtering
MDX On Demand requests will initiate from one of MX's data centers. For failover and load balancing purposes, these requests can initiate from any data center. If you intend to use IP whitelisting, the IP address ranges of all of MX's data centers must be included.
You should return a 403 (Forbidden) error for an MDX On Demand request that fails IP validation.
| CIDR | Range |
|---|---|
| 64.77.254.32/27 | 30 addresses from 64.77.254.33 to 64.77.254.62 |
| 68.142.151.128/26 | 62 addresses from 68.142.151.129 to 68.142.151.190 |
| 146.75.94.131/32 | 1 address 146.75.94.131 |
| 97.75.178.32/27 | 30 addresses from 97.75.178.33 to 97.75.178.62 |
| 192.41.25.128/26 | 62 addresses from 192.41.25.129 to 192.41.25.190 |
| 192.41.58.128/26 | 62 addresses from 192.41.58.129 to 192.41.58.190 |
Additional Authentication
In addition to request signing and IP filtering, you may choose to implement any or all of the following: HTTP basic authentication, mutual authentication, and/or CA certification authentication. Any additional authentication must be set up with MX during your initial integration.
Errors
The MDX On Demand API uses conventional HTTP response codes to indicate success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (for example, a required parameter was missing), and codes in the 5xx range indicate an error with your servers.
HTTP Status Code Summary
- 200 OK: Everything worked as expected.
- 400 Bad Request: Malformed request body or missing a required parameter.
- 401 Unauthorized: No valid session key or credentials provided.
- 403 Forbidden: The IP address isn't whitelisted.
- 404 Not Found: The requested item doesn't exist.
- 406 Not Acceptable: The request didn't specify a valid version.
- 412 Precondition Failed: The HMAC was invalid or missing.
- 422 Unprocessable Entity: The credentials couldn't be decrypted.
- 429 Too Many Requests: The partner's MDX service is at capacity.
- 500 Internal Server Error: Something went wrong on the data provider's end.
- 502 Bad Gateway: Something went wrong on the data provider's end.
- 503 Service Unavailable: The service is down for maintenance.
- 504 Gateway Timeout: The request couldn't be completed in the time allotted.
Additional Error Codes
You should use the error codes and messages documented here when applicable. These error codes and messages are intended to supplement the HTTP status code and offer additional detail. A message should always be returned. The code is optional. You can return your own code or leave the field blank, but the <code> and <message> elements should always be present in the error response body.
The format for sending an error is shown in the example.
| Code | Message | Description |
|---|---|---|
| 4010 | Invalid Credentials | The user key or login and password were invalid. |
| 4011 | Locked | The login was valid, but the account was locked. |
| 4012 | Invalid Session Key | The provided session key was invalid. |
| 4013 | MFA Failed | The MFA login information provided was incorrect. |
_10<mdx version="5.0">_10 <error>_10 <code>4010</code>_10 <message>Error message.</message>_10 </error>_10</mdx>
Response Format
The MDX On Demand specification is XML-based. Responses are required to be UTF-8 encoded and XML tags must be lowercase. Reserved XML characters must be properly escaped. The XML response must not contain Unicode Byte Order Mark characters (for example, 0xfeff).
Compression
Gzip compression is supported when Content-Encoding is set to gzip.
Data Sanitization
You are required to avoid sending identifiable account information such as complete account and/or credit card numbers for account IDs and names.