ING API with python
1. ING Developer
ING has a developer portal with instructions for accessing their APIs.
There are 2 API types:
- Openbanking: open for anyone to access
- PSD2: for accessing those ones you need an eIDAS certificate.
eIDAS certificates can only be optained by organizations, not by individuals like you or me
This post focus on the Open Banking API.
Disclaimer: At the time of writting it is not possible to use “Open Banking” for personal use. Only accredited institutions will get the requeried credentials. I discovered after doing all the work and I’m sharing it in case anyone wants to try it and/or in case individuals can use it in the future.
2. The Open Banking API
At the moment of writting of this post there is not a lot that you can do with this API. Those are the 2 APIs you can use:
- OAuth 2.0: Allows to authenticate and retrive a token
- Showcase API: This allows you to query
/greetings/single
which is the equivalent of ahello world
As you can see right now it is not very useful. When I started investigating I didn’t realized that you couldn’t retrive your own data with the Open Banking API. So I followed all their documentation and developed all the code until I realized that it was not useful at all. But since I had all the code I thought it might be useful to share.
I also contacted their support and they told me they plan to allow users to access their account info with the Open Banking API. But there is no ETA for that.
3. Open Banking API Sandbox
This part follows the Getting Started with Open Banking API.
The first thing you need to do is to download the example certificates:
- example_client_signing.cer (you don’t really need this one)
- example_client_signing.key
- example_client_tls.cer
- example_client_tls.key
And also:
- host:
https://api.sandbox.ing.com
- client_id:
e77d776b-90af-4684-bebc-521e5b2614dd
For requesting the token with the OAuth 2.0 API
they provide a script.
However I wanted to have everything in python.
The first thing is to install cryptodome
with
pip install pycryptodome
All the code can be found in Villoro posts: ING API
Let’s break down the script in parts
3.1. Digesting and signing
You need to calculate the SHA256
of some parts.
That can be done with:
from Crypto.Hash import SHA256
# to digest 'text'
digest = SHA256.new()
digest.update(text.encode())
From that we can create a function that does it and can also sign the digest with:
sign_key = "certificates/example_client_signing.key" # Adapt path
def encode_sha256(text, sign=False):
""" digest a text with SHA256 """
digest = SHA256.new()
digest.update(text.encode())
if sign:
# Get the signing key
with open(sign_key, "r") as file:
data = file.read()
private_key = RSA.importKey(data)
signer = PKCS1_v1_5.new(private_key)
out = signer.sign(digest)
else:
out = digest.digest()
return b64encode(out).decode()
And finally we need to encode it as a base64 string with:
from base64 import b64encode
b64encode(out).decode()
3.2. Parameters
Now let’s create the basic parameters:
import uuid
from datetime import datetime
mdate = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
digest = encode_sha256(body) # Without signing
req_id = str(uuid.uuid4())
And the headers:
headers = {
"Date": mdate,
"Digest": f"SHA-256={digest}",
"X-ING-ReqID": req_id,
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
}
3.3. Getting the signature
In this step you need to encode with SHA256
the composition of:
- endpoint
- date
- body digest
- req_id
After that you need to append some information. All of that can be done with:
def get_signature(method, endpoint, mdate, digest, req_id):
text = [
f"(request-target): {method.lower()} {endpoint}",
f"date: {mdate}",
f"digest: SHA-256={digest}",
f"x-ing-reqid: {req_id}",
]
signature_digest = encode_sha256("\n".join(text), True)
signature = [
f'keyId="{client_id}"',
'algorithm="rsa-sha256"',
'headers="(request-target) date digest x-ing-reqid"',
f'signature="{signature_digest}"',
]
return ",".join(signature)
3.4. Doing the request
Now we need to append the authorization as a header:
signature = get_signature(method, endpoint, mdate, digest, req_id)
if token:
headers.update({"Authorization": f"Bearer {token}", "Signature": signature})
else:
headers.update({"Authorization": f"Signature {signature}"})
And finally we can do the request:
tls_cert="certificates/example_client_tls.cer",
tls_key="certificates/example_client_tls.key",
result = requests.request(
method.upper(),
self.host + endpoint,
headers=headers,
data=body,
cert=(tls_cert, tls_key),
)
3.5. Getting the token
This can be done with the code explained and using those params:
- endpoint:
/oauth2/token
- method:
POST
- body:
grant_type=client_credentials
4. Creating your app
In this step you need to sign in to the ING developer portal.
Then you need to create an app.
4.1. Generating your certificates
You need to generate:
- ing_http.key
- ing_http.key
- ing_tls.crt
- ing_tls.crt
You can generate the first 2 with:
# 1. Generate an RSA private key. The password of the private key can be entered during execution of the command, so it doesn't end up in the history of your shell.
openssl genrsa -out ing_http.key -passout stdin 2048
# 2. Generate the X.509 Certificate Signing Request
openssl req -sha256 -new -key ing_http.key -out ing_http.csr
# 3. Sign the X.509 certificate with your own private key
openssl x509 -req -sha256 -days 365 -in ing_http.csr -signkey ing_http.key -out ing_http.crt
Then need to repeat the 3 steps but replacing ing_http
by ing_tls
.
4.2. Getting a token with your API
You need to follow the same as before but changing some params:
- host:
https://api.ing.com
- client_id: You can get that from the web
- sign_key:
certificates/ing_http.key
- tls_cert:
certificates/ing_tls.crt
- tls_key:
certificates/ing_tls.key
4.3. Doing a hello world
Once you have the open you can suscribe to Showcase API. You will need to wait until your request is approved.
Once it is approved you can query the only endpoint to check that everything is working:
- method:
GET
- endpoint:
/greetings/single
5. Next steps
Now you can wait with me until they add more APIs under the Open Banking 😢