Python Code Example PSD2 - OAuth integration

In the linked repository you'll find a example integration that has all the moving parts of setting up a bunq server and the oauth flow.

Setting up the example

In order to use the code example we expect you have a python environment set up. Simply running `pip install -r requirements.txt` will take care of setting up dependancies. If you are a PSD2 user you'll want to create a UserPaymentServiceProvider user. These are specific users that have no banking features attached to their bunq account. If that's the case you'll want to run the create_psd2_user.sh script. That will register a sandbox PSD2 user for you.

If you're just a bunq business user you can just paste your API Keys in the main.py file.

From there you can run `uvicorn main:app --reload' this will kick off a uvicorn server, serving a FastAPI app on port 8000 to start the server

Initializing your installation

We prepared a endpoint that you'll have to run 1x it will set up the . It will also register your OAuthclient and register a Callback URL OAuth.

You can do so by hitting the localhost:8000/setup_one_time it will take a minute.

Finally that script will create a .env file that can be used going forward.

This is a great step to remove your API key from the main.py file. From now on it will be read from the .env file.

Using Oauth

You can now go to your localhost:8000/auth endpoint which will trigger a oauth request. If you have the Android Emulator on a physical device you'll be able to scan the QR code that is generated and complete the oauth flow.

What happens in the background is:

  1. The app created a oauth client in the set up. This allows us to now generate a oauth session. It is a screen with a QR code that the end-user scans with their bunq app

  2. In the app the bunq user can select which monetary accounts they grant access to.

  3. When the user completes the steps they are redirected to our app. With a authorization code from bunq. This code is immidiatly used by the app to request a access token. The app stores that access token in a database. and assosciates it to a user. We did not build a pretty page but if the oauth flow was successful you'll see a json response with:

    {"message":"OAuth success","new_user_id":1}

    This means that we stored a user in our local database with id 1 that has a bunq oauth access token associated to it.

  4. So now we can retrieve data on that user. One way to do that is to visit the /docs endpoint. FastApi offers a interactive API documentation. You can also simply visit the localhost:8000/user/1 url. If you request data on behalf of a user then this happens: 1. We look up the bunq access token for that user 1 in our database 2. We request a session token with the access token 3. We make the API call we want with that session token 4. Return the results to the end-user

For instance: if you go to the user/2/accounts endpoint you'll get a summary of the Monetary Accountfor that user:

{
  "Response": [
    {
      "MonetaryAccountBank": {
        "id": 2083712,
        "created": "2025-04-14 00:00:00.811318",
        "updated": "2025-04-14 00:00:00.811318",
        "alias": [
          {
            "type": "PHONE_NUMBER",
            "value": "+31611019364",
            "name": "+31611019364"
          },
          {
            "type": "EMAIL",
            "value": "[email protected]",
            "name": "[email protected]"
          },
          {
            "type": "IBAN",
            "value": "NL65BUNQ2090411945",
            "name": "Jodi Walker"
          }
        ],
        "avatar": {
          "uuid": "2ef45ffc-67e9-44ac-a432-a8987c5d4e9d",
          "image": [
            {
              "attachment_public_uuid": "3f3a3d92-b646-463c-ae8d-6a0393e45500",
              "height": 1023,
              "width": 1024,
              "content_type": "image/png",
              "urls": [
                {
                  "type": "ORIGINAL",
                  "url": "https://bunq-triage-model-storage-public.s3.eu-central-1.amazonaws.com/bunq_file/File/content/921ece497cd00f4e0cef3f0f63a962c31cf3f8e35311d127d5a7b23be3d074d5.png"
                }
              ]
            }
          ],
          "anchor_uuid": "5e758d81-add9-4510-89e1-ff2bd5a04146",
          "style": "NONE"
        },
        "balance": {
          "currency": "EUR",
          "value": "4118.00"
        },
        "country": "NL",
        "currency": "EUR",
        "display_name": "J. Walker",
        "daily_limit": {
          "currency": "EUR",
          "value": "5000.00"
        },
        "description": "Main",
        "public_uuid": "5e758d81-add9-4510-89e1-ff2bd5a04146",
        "status": "ACTIVE",
        "sub_status": "NONE",
        "timezone": "europe/amsterdam",
        "user_id": 1864430,
        "monetary_account_profile": null,
        "setting": {
          "color": "#FF7819",
          "icon": null,
          "default_avatar_status": "AVATAR_DEFAULT",
          "restriction_chat": "ALLOW_INCOMING",
          "sdd_expiration_action": "AUTO_ACCEPT"
        },
        "connected_cards": [],
        "budget": [],
        "all_access": [
          {
            "MonetaryAccountAccess": {
              "id": 2268800,
              "created": "2025-04-14 00:00:00.822699",
              "updated": "2025-04-14 00:00:00.822699",
              "access_type": "FULL_PERMANENT"
            }
          }
        ],
        "overdraft_limit": {
          "currency": "EUR",
          "value": "0.00"
        },
        "all_auto_save_id": []
      }
    },
    {
      "MonetaryAccountBank": {
        "id": 2083715,
        "created": "2025-04-14 09:12:06.578796",
        "updated": "2025-06-03 09:48:46.647401",
        "alias": [
          {
            "type": "IBAN",
            "value": "NL55BUNQ2090409118",
            "name": "Jodi Walker"
          }
        ],
        "avatar": {
          "uuid": "f8217171-567f-4034-ac5e-5fc281b611a6",
          "image": [
            {
              "attachment_public_uuid": "fa99b3bf-7121-4d23-9fe9-6ce48ff76285",
              "height": 1024,
              "width": 1024,
              "content_type": "image/jpeg",
              "urls": [
                {
                  "type": "ORIGINAL",
                  "url": "https://bunq-triage-model-storage-public.s3.eu-central-1.amazonaws.com/bunq_file/File/content/1fcb8573f717dc6406dbbb170367f98cbed175ca4d3bee3aeaa772fdcf284c1a.jpg"
                }
              ]
            }
          ],
          "anchor_uuid": "0477b9c1-ff11-4fcb-9bf1-9b84b1b5c27d",
          "style": "NONE"
        },
        "balance": {
          "currency": "EUR",
          "value": "1900.00"
        },
        "country": "NL",
        "currency": "EUR",
        "display_name": "J. Walker",
        "daily_limit": {
          "currency": "EUR",
          "value": "5000.00"
        },
        "description": "Main",
        "public_uuid": "0477b9c1-ff11-4fcb-9bf1-9b84b1b5c27d",
        "status": "ACTIVE",
        "sub_status": "NONE",
        "timezone": "europe/amsterdam",
        "user_id": 1864430,
        "monetary_account_profile": null,
        "setting": {
          "color": "#ff7819",
          "icon": "FINANCE",
          "default_avatar_status": "AVATAR_ICON",
          "restriction_chat": "ALLOW_INCOMING",
          "sdd_expiration_action": "AUTO_ACCEPT"
        },
        "connected_cards": [],
        "budget": [],
        "all_access": [
          {
            "MonetaryAccountAccess": {
              "id": 2268802,
              "created": "2025-04-14 09:12:06.599804",
              "updated": "2025-04-14 09:12:06.599804",
              "access_type": "FULL_PERMANENT"
            }
          }
        ],
        "overdraft_limit": {
          "currency": "EUR",
          "value": "0.00"
        },
        "all_auto_save_id": []
      }
    },
    {
      "MonetaryAccountBank": {
        "id": 2083719,
        "created": "2025-04-14 09:12:58.553604",
        "updated": "2025-04-14 09:14:06.776031",
        "alias": [
          {
            "type": "IBAN",
            "value": "NL17BUNQ2090415428",
            "name": "Jodi Walker"
          }
        ],
        "avatar": {
          "uuid": "48bb720a-6baf-4482-a78c-b8592e5fde08",
          "image": [
            {
              "attachment_public_uuid": "0e76b824-36ef-4680-9554-0c2da11f6ed9",
              "height": 1024,
              "width": 1024,
              "content_type": "image/jpeg",
              "urls": [
                {
                  "type": "ORIGINAL",
                  "url": "https://bunq-triage-model-storage-public.s3.eu-central-1.amazonaws.com/bunq_file/File/content/4c90f8a578279abd53b06840a4dd619009c2f4b9ddc4342dbf12e4fbf11bbd4a.jpg"
                }
              ]
            }
          ],
          "anchor_uuid": "fbb765b0-2eef-4c91-8060-37950b65694a",
          "style": "NONE"
        },
        "balance": {
          "currency": "EUR",
          "value": "954.00"
        },
        "country": "NL",
        "currency": "EUR",
        "display_name": "J. Walker",
        "daily_limit": {
          "currency": "EUR",
          "value": "5000.00"
        },
        "description": "Car",
        "public_uuid": "fbb765b0-2eef-4c91-8060-37950b65694a",
        "status": "ACTIVE",
        "sub_status": "NONE",
        "timezone": "europe/amsterdam",
        "user_id": 1864430,
        "monetary_account_profile": null,
        "setting": {
          "color": "#47bfff",
          "icon": "TRANSPORT",
          "default_avatar_status": "AVATAR_ICON",
          "restriction_chat": "ALLOW_INCOMING",
          "sdd_expiration_action": "AUTO_ACCEPT"
        },
        "connected_cards": [],
        "budget": [],
        "all_access": [
          {
            "MonetaryAccountAccess": {
              "id": 2268806,
              "created": "2025-04-14 09:12:58.575972",
              "updated": "2025-04-14 09:12:58.575972",
              "access_type": "FULL_PERMANENT"
            }
          }
        ],
        "overdraft_limit": {
          "currency": "EUR",
          "value": "0.00"
        },
        "all_auto_save_id": []
      }
    },
    {
      "MonetaryAccountBank": {
        "id": 2083721,
        "created": "2025-04-14 09:13:51.146459",
        "updated": "2025-04-14 09:13:51.146459",
        "alias": [
          {
            "type": "IBAN",
            "value": "NL09BUNQ2090405775",
            "name": "Jodi Walker"
          }
        ],
        "avatar": {
          "uuid": "5ac4305a-846b-46c0-bff7-b383db308acf",
          "image": [
            {
              "attachment_public_uuid": "b312f25b-fb29-4fd0-a971-79c6eaf8b8e0",
              "height": 1024,
              "width": 1024,
              "content_type": "image/jpeg",
              "urls": [
                {
                  "type": "ORIGINAL",
                  "url": "https://bunq-triage-model-storage-public.s3.eu-central-1.amazonaws.com/bunq_file/File/content/854e26c59d732cf32e7187f7ee4bcc11f8415d06f99ed59780fcc21883bd0f62.jpg"
                }
              ]
            }
          ],
          "anchor_uuid": "81802c69-3039-4d73-8138-da6e43acb7f0",
          "style": "NONE"
        },
        "balance": {
          "currency": "EUR",
          "value": "1643.00"
        },
        "country": "NL",
        "currency": "EUR",
        "display_name": "J. Walker",
        "daily_limit": {
          "currency": "EUR",
          "value": "5000.00"
        },
        "description": "Medical",
        "public_uuid": "81802c69-3039-4d73-8138-da6e43acb7f0",
        "status": "ACTIVE",
        "sub_status": "NONE",
        "timezone": "europe/amsterdam",
        "user_id": 1864430,
        "monetary_account_profile": null,
        "setting": {
          "color": "#ff2d55",
          "icon": "HEALTHCARE",
          "default_avatar_status": "AVATAR_ICON",
          "restriction_chat": "ALLOW_INCOMING",
          "sdd_expiration_action": "AUTO_ACCEPT"
        },
        "connected_cards": [],
        "budget": [],
        "all_access": [
          {
            "MonetaryAccountAccess": {
              "id": 2268808,
              "created": "2025-04-14 09:13:51.163604",
              "updated": "2025-04-14 09:13:51.163604",
              "access_type": "FULL_PERMANENT"
            }
          }
        ],
        "overdraft_limit": {
          "currency": "EUR",
          "value": "0.00"
        },
        "all_auto_save_id": []
      }
    }
  ],
  "Pagination": {
    "future_url": null,
    "newer_url": null,
    "older_url": null
  }
}

Last updated

Was this helpful?