Open Banking API

Welcome to the Zilverline Open banking API.

Functionality

MT940 conversion

This API provides the ability to convert a MT940 file to a JSON file according to the NextGenPSD2 format.

The MT940 of the following banks are supported:
ABN Amro, ASN, Bunq, Deutsche Bank, ING, Knab, Rabobank, Regiobank, SNS Reaal, Triodos, van Lanschot

CAMT.053 conversion

This API provides the ability to convert a CAMT.053 XML file to an JSON file according to the NextGenPSD2 format.

NextGenPSD2 format

The NextGenPSD2 format used by this API is essence the same format as described in the NextGenPSD2 Implementation Guidelines of The Berlin Group (an European standards initiative). The format is modified only by removing fields which aren't used and adding fields to supply extra information (like the raw MT940 / CAMT.053 data).

Please see the JSON Format Reference page for the exact details of the NextGenPSD2 format.

About

MT940

Message Type 940 is the SWIFT standard (Banking Communication Standard) for the electronic transmission of account statement data. In various online banking programs, MT940 is used as an interface to other programs (e.g. for accounting), with which the account statement data are processed further.

CAMT.053

CAMT is an ISO 20022 Payment Message definition that stands for Cash Management and specifically covers Bank to Customer Cash Management reporting.

CAMT.053 is a Bank to Customer Statement, essentially providing you with a prior or previous day statement of your account. It will indicate all entries booked to the account for the previous business day. CAMT.053 is an updated and standardised version of the MT940 and prior-day BAI2 bank statement formats. Click here to learn more about the differences of other CAMT formats, like CAMT.052 and CAMT.054.

API authorization

Connecting your application with the Open Banking API requires OAuth 2.0 authorization.

Authenticating to the API is done by following the OAuth 2.0 'Client Credentials' flow. This flow dictates that the application requests an access token by providing his client id and client secret to the /oauth-provider/oauth/token endpoint. When valid, the authorization server responds with an access token. This access token is then used to request resources or operations from the API.

The following links describe OAuth 2.0 and the client_credentials grant type in further detail:

Authorization scopes

The following scopes are supported:

mt940:upload
Access to upload the MT940 file.
camt053:upload
Access to upload the CAMT.053 XML file.
ais:read
Access to read the converted JSON output in the NextGenPSD2 format.

All of the scopes are default and will be used automatically when none are specified.

Note that for using the /upload endpoint, all of the scopes are required as this endpoint is capable of converting both MT940 and CAMT.053 data.

Register application to obtain client credentials

Send an email to info@zilverline.com to request an application registration for using the Open Banking API. In this email specify which scopes you need to have access to. When your request is accepted, you will receive the required client id and client secret.

Obtaining an access token

Once you have received the client id and secret you can obtain an access token for access to this API. When making a request for an access token, take note of the following:

  • The client ID and client secret must be passed via Basic Authentication.
  • The grant_type parameter must have value client_credentials.
  • The scope parameter can only contain (either the same or less) scopes that were specified when registering your application. Define multiple scopes separated by a space, for example:  mt940:upload camt053:upload ais:read.

Example request for access token, using curl:

curl -X POST -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" -d "grant_type=client_credentials&scope=YOUR_SCOPES" https://openbanking.zilverline.com/oauth-provider/oauth/token

Would respond with:

{
  "access_token": "d5MVxoEHnA3YT_GudJ6TE5XmHPV_1prjZ8OIOHJsBvg",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "mt940:upload ais:read camt053:upload",
  "created_at": 1665751476
}

Sending requests to the Open Banking API

Once you've retrieved the access token, you can make an authorized request to the API. The access_token must be provided in the HTTP Authorization header, prepended by Bearer:

Authorization: Bearer YOUR_ACCESS_TOKEN

MT940 conversion

Request

To upload MT940 files for conversion, upload it using a multipart/form-data HTTP POST request.

URL
https://openbanking.zilverline.com/mt940
https://openbanking.zilverline.com/upload Use this URL if you want to use the same URL for uploading MT940 and CAMT.053 data.
Note: requires extra scope, see Authorization scopes.
Headers
Authorization Provide your access token in this header. Prepend the header value with Bearer.
Content-Type Specifies the content type of your request. It should always be set to multipart/form-data.
X-Request-Id Optional header to specify unique end-to-end request id. This request id will be returned in the response.
Body
tamper_protection Enable or disable MT940 tamper protection by specifying the value 0 (off) or 1 (on).
Tamper protection is disabled by default. See the Reference page for more information.
file Specify MT940 data for conversion

Click on a tab below to view example code snippet for uploading a MT940 file in the specified code language.

HTTP POST https://openbanking.zilverline.com/mt940
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: multipart/form-data; boundary=a9214f8d
Content-Length: 3539

--a9214f8d
Content-Disposition: form-data; name="tamper_protection"

1
--a9214f8d
Content-Disposition: form-data; name="file"; filename="ing.txt"
Content-Type: text/plain

<< MT940 data >>
--a9214f8d--

curl

curl --location --request POST 'https://openbanking.zilverline.com/mt940' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--form 'tamper_protection="1"' \
--form 'file=@"/Users/user/Documents/ing.txt"'

Java (OkHttp)

OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  .addFormDataPart("tamper_protection","1")
  .addFormDataPart("file","ing.txt",
    RequestBody.create(MediaType.parse("application/octet-stream"),
    new File("/Users/user/Documents/ing.txt")))
  .build();
Request request = new Request.Builder()
  .url("https://openbanking.zilverline.com/mt940")
  .method("POST", body)
  .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
  .build();
Response response = client.newCall(request).execute();

Python (requests)

import requests

url = "https://openbanking.zilverline.com/mt940"

payload={'tamper_protection': '1'}
files=[
  ('file',('ing.txt',open('/Users/user/Documents/ing.txt','rb'),'text/plain'))
]
headers = {
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

Node.js (axios)

var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();
data.append('tamper_protection', '1');
data.append('file', fs.createReadStream('/Users/user/Documents/ing.txt'));

var config = {
  method: 'post',
  url: 'https://openbanking.zilverline.com/mt940',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

Response

Whenever you make an HTTP request to the API, the response will contain a JSON array with one or multiple objects (a success response), or a JSON object with "tppMessages" key (an error response).

CAMT.053 conversion

Request

To upload CAMT.053 XML files for conversion, upload it using a multipart/form-data HTTP POST request.

URL
https://openbanking.zilverline.com/camt053
https://openbanking.zilverline.com/upload Use this URL if you want to use the same URL for uploading MT940 and CAMT.053 data.
Note: requires extra scope, see Authorization scopes.
Headers
Authorization Provide your access token in this header. Prepend the header value with Bearer.
Content-Type Specifies the content type of your request. It should always be set to multipart/form-data.
X-Request-Id Optional header to specify unique end-to-end request id. This request id will be returned in the response.
Body
tamper_protection Enable or disable CAMT tamper protection by specifying the value 0 (off) or 1 (on).
Tamper protection is disabled by default. See the Reference page for more information.
file Specify CAMT.053 XML data for conversion

Click on a tab below to view example code snippet for uploading a CAMT.053 XML file in the specified code language.

HTTP POST https://openbanking.zilverline.com/camt053
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: multipart/form-data; boundary=a9214f8d
Content-Length: 3539

--a9214f8d
Content-Disposition: form-data; name="tamper_protection"

1
--a9214f8d
Content-Disposition: form-data; name="file"; filename="rabobank.xml"
Content-Type: text/xml

<< CAMT.053 XML data >>
--a9214f8d--

curl

curl --location --request POST 'https://openbanking.zilverline.com/camt053' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--form 'tamper_protection="1"' \
--form 'file=@"/Users/user/Documents/rabobank.xml"'

Java (OkHttp)

OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  .addFormDataPart("tamper_protection","1")
  .addFormDataPart("file","rabobank.xml",
    RequestBody.create(MediaType.parse("application/octet-stream"),
    new File("/Users/user/Documents/rabobank.xml")))
  .build();
Request request = new Request.Builder()
  .url("https://openbanking.zilverline.com/camt053")
  .method("POST", body)
  .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
  .build();
Response response = client.newCall(request).execute();

Python (requests)

import requests

url = "https://openbanking.zilverline.com/camt053"

payload={'tamper_protection': '1'}
files=[
  ('file',('rabobank.xml',open('/Users/user/Documents/rabobank.xml','rb'),'text/xml'))
]
headers = {
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

Node.js (axios)

var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();
data.append('tamper_protection', '1');
data.append('file', fs.createReadStream('/Users/user/Documents/rabobank.xml'));

var config = {
  method: 'post',
  url: 'https://openbanking.zilverline.com/camt053',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

Response

Whenever you make an HTTP request to the API, the response will contain a JSON array with one or multiple objects (a success response), or a JSON object with "tppMessages" key (an error response).

Example success request/response

An HTTP response with status code 200 OK indicates the request was successful.

Request
curl -X POST https://openbanking.zilverline.com/mt940 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -F 'tamper_protection="1"' -F 'file=@"knab.txt"'

In this example request/response, we've used the following example MT940 file; knab.txt

Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Request-Id: a9214f8d-3424-4321-a69a-00ffcb6e9bf7
[
  {
    "account": {
      "bic": "KNABNL2H",
      "iban": "NL92KNAB0123456789",
      "bban": "123456789",
      "currency": "EUR"
    },
    "balances": [
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "0.00"
        },
        "balanceType": "openingBooked",
        "referenceDate": "2014-10-24"
      },
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "1010.00"
        },
        "balanceType": "closingBooked",
        "referenceDate": "2014-10-27"
      }
    ],
    "transactions": {
      "booked": [
        {
          "bookingDate": "2014-10-24",
          "valueDate": "2014-10-24",
          "transactionAmount": {
            "currency": "EUR",
            "amount": "1000.00"
          },
          "debtorName": "BEDRIJF VOF",
          "debtorAccount": {
            "iban": "NL26ABNA0999999999",
            "bban": "999999999",
            "currency": "EUR"
          },
          "remittanceInformationUnstructured": "REK: NL26ABNA0999999999/NAAM: BEDRIJF VOF",
          "additionalInformation": "OVERIGE",
          "bankTransactionCode": "NTRF",
          "providerSpecificData": {
            "bankName": "KNAB",
            "bankReference": "ABC9886658908791",
            "customerReference": "NONREF",
            "mt940": ":61:1410241024C1000,NTRFNONREF//ABC9886658908791\n:86:REK: NL26ABNA0999999999/NAAM: BEDRIJF VOF"
          }
        },
        {
          "bookingDate": "2014-10-24",
          "valueDate": "2014-10-24",
          "transactionAmount": {
            "currency": "EUR",
            "amount": "10.00"
          },
          "debtorName": "STICHTING DERDEN JAAP JANSSEN",
          "debtorAccount": {
            "iban": "NL76INGB0444444444",
            "bban": "444444444",
            "currency": "EUR"
          },
          "remittanceInformationUnstructured": "DIT IS EEN OMSCHRIJVING DIE BEST WEL LANG ISREK: NL76INGB0444444444/NAAM: STICHTING DERDEN JAAP JANSSEN",
          "additionalInformation": "OVERIGE",
          "bankTransactionCode": "NTRF",
          "providerSpecificData": {
            "bankName": "KNAB",
            "bankReference": "AB1211111111111",
            "customerReference": "NONREF",
            "mt940": ":61:1410241024C10,NTRFNONREF//AB1211111111111\n:86:DIT IS EEN OMSCHRIJVING DIE BEST WEL LANG ISREK: NL76INGB0444444444/NAAM: STICHTING DERDEN JAAP JANSSEN"
          }
        }
      ]
    }
  }
]

An HTTP response with status code 200 OK indicates the request was successful.

Request
curl -X POST https://openbanking.zilverline.com/camt053 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -F 'tamper_protection="1"' -F 'file=@"rabobank.xml"'

In this example request/response, we've used the following example CAMT.053 XML file; rabobank.xml

Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Request-Id: a9214f8d-3424-4321-a69a-00ffcb6e9bf7
[
  {
    "account": {
      "iban": "NL44RABO0123456789",
      "bban": "123456789",
      "currency": "EUR"
    },
    "balances": [
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "56878.47"
        },
        "balanceType": "openingBooked",
        "referenceDate": "2019-03-12"
      },
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "99880.01"
        },
        "balanceType": "closingBooked",
        "referenceDate": "2019-03-12"
      }
    ],
    "transactions": {
      "booked": [
        {
          "entryReference": "7375",
          "endToEndId": "20198iijvhe3574",
          "bookingDate": "2019-03-12",
          "valueDate": "2019-03-12",
          "transactionAmount": {
            "currency": "EUR",
            "amount": "43001.54"
          },
          "debtorName": "OBAR Holding",
          "debtorAccount": {
            "bic": "RABONL2U",
            "iban": "NL72RABO0104510633",
            "bban": "104510633"
          },
          "debtorAgent": "RABONL2U",
          "remittanceInformationUnstructured": "periode 2019-03 FACT9iiAB86",
          "bankTransactionCode": "541",
          "providerSpecificData": {
            "bankName": "RABOBANK",
            "bankReference": "11207400299:CI07CT"
          }
        }
      ]
    }
  },
  {
    "account": {
      "iban": "NL72RABO0104510633",
      "bban": "104510633",
      "currency": "EUR"
    },
    "balances": [
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "10698.15"
        },
        "balanceType": "openingBooked",
        "referenceDate": "2019-03-12"
      },
      {
        "balanceAmount": {
          "currency": "EUR",
          "amount": "10589.14"
        },
        "balanceType": "closingBooked",
        "referenceDate": "2019-03-12"
      }
    ],
    "transactions": {
      "booked": [
        {
          "entryReference": "7401",
          "endToEndId": "DEB1199264123875995996465",
          "bookingDate": "2019-03-12",
          "valueDate": "2019-03-12",
          "transactionAmount": {
            "currency": "EUR",
            "amount": "-109.01"
          },
          "creditorName": "Rabobank BenS",
          "creditorAccount": {
            "bic": "RABONL2U",
            "iban": "NL94RABO0104510625",
            "bban": "104510625"
          },
          "creditorAgent": "RABONL2U",
          "remittanceInformationUnstructured": "889920190301",
          "bankTransactionCode": "064",
          "providerSpecificData": {
            "bankName": "RABOBANK",
            "bankReference": "15198258444:DR02DT"
          }
        }
      ]
    }
  }
]

Error response

An HTTP response with status code 4xx or 5xx indicates there was an error while processing the request. The response body will contain extra information about the error.
The following examples are from an attempted MT940 conversion but are very similar as CAMT.053 conversion.

Request (error) example
curl -X POST https://openbanking.zilverline.com/mt940 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -F 'file=@"bad.txt"'

In this example request/response, we've used a .txt file with some garbage contents; bad.txt

Response (error) example
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Request-Id: a9214f8d-3424-4321-a69a-00ffcb6e9bf7
{
  "tppMessages": [
    {
      "category": "ERROR",
      "code": "INVALID_FILE_CONTENT",
      "text": "Bad or corrupt data specified in 'file' parameter"
    }
  ]
}