Package: bridgeapi
bridgeapibridgeapiis a client for theBridge open banking API aggregator(API documentation).RequirementsPython 3.10+Installationpip install bridgeapiExamplefrombridgeapiimportAppClient,UserClientapp_client=AppClient("CLIENT_ID","CLIENT_SECRET")app_client.list_banks()app_client.list_users()app_client.create_user("john@doe.com","password")...user_client=UserClient("CLIENT_ID","CLIENT_SECRET","john@doe.com","password")user_client.list_items()user_client.connect_item()user_client.list_accounts()user_client.list_transactions()...API endpoints are split between two clients:AppClienthandles all application-scoped endpoints, that don't depend on a user being
authenticated. It only needs (client_id, client_secret) credentials to communicate with the API.UserClienthandles user-scoped endpoints, those that are specific to a user and require an
access token and theAuthorizationheader to communicate with the API. It needs (user_email,
user_password) credentials, in addition to the same client credentials asAppClient.All API client methods return a Pydantic model mapping exactly the schema of the API response. The
raw response object can be accessed with the.responseproperty:result=app_client.list_banks()result# PaginatedResult[Bank]result.response# <Response [200]>result.response.json()# JSON-parsed raw response bodyPaginated resultsAPI endpoints that return a list of results are paginated, i.e. they don't return the complete
list of objects in one result but in chunks (called pages). When calling a list API endpoint, the
first page of results is returned. Existence of more pages can be checked with.has_more().
Subsequent pages can be retrieved by calling.next_page():frombridgeapiimportAppClientapp_client=AppClient("CLIENT_ID","CLIENT_SECRET")banks=app_client.list_banks(limit=2)print(banks.resources)# List of 2 Bank instancesprint(banks.has_more())# Truebanks=banks.next_page()print(banks.resources)# List of 2 other Bank instancesThe entire list of objects can be retrieved by calling.fetch_all()on the first page returned
by the API. Attempting to call it on a subsequent page will result in an error. Beware of
potentially large collections, you may exceed API or memory limits, or wait for a long time. You
may also want to increase thelimitparameter.frombridgeapiimportAppClientapp_client=AppClient("CLIENT_ID","CLIENT_SECRET")banks=app_client.list_banks(limit=100)print(banks.fetch_all())# List of all banksbanks.next_page().fetch_all()# PaginationErrorUser authentication managementThe simplest usage ofUserClientis to it handle all the authorization lifecyle. It will
automatically obtain an access token and renew it when it expires (after 2 hours):user_client=UserClient("CLIENT_ID","CLIENT_SECRET","john@doe.com","password")print(user_client.list_items())# OK# 2+ hours laterprint(user_client.list_items())# OKIf you wish to manage the user authorization lifecycle yourself, passauto_renew=Falseat
creation. You will need to call.renew_auth()manually:user_client=UserClient("CLIENT_ID","CLIENT_SECRET","john@doe.com","password",auto_renew=False)print(user_client.is_authenticated())# Falseuser_client.list_items()# UserAuthenticationErroruser_client.renew_auth()print(user_client.is_authenticated())# Trueprint(user_client.list_items())# OK# 2+ hours laterprint(user_client.is_authenticated())# Falseuser_client.renew_auth()print(user_client.is_authenticated())# TrueAdditionally, if you are managing user tokens externally and persisting them to external storage,
you can provide them at creation as well:user_client=UserClient("CLIENT_ID","CLIENT_SECRET","john@doe.com","password",user_uuid="uuid",access_token="token",expires_at=datetime,# "yyyy-mm-dd HH:MM:SS"auto_renew=False,)print(user_client.is_authenticated())# Trueuser_client.list_items()# OK# Generate and store new authorization infoauth_info=user_client.renew_auth()store_user_auth_to_db(user_email=auth_info.user.email,user_uuid=auth_info.user.uuid,access_token=auth_info.access_token,expires_at=auth_info.expires_at,)Licensebridgeapiis distributed under the terms of theMITlicense.