The official python client library for the Plaid API.
This module was recently refactored and released with breaking changes as version 1.0.x
.
Via pip:
pip install plaid-python
Via source:
git clone git@github.com:plaid/plaid-python.git
python setup.py install
The module supports all Plaid API endpoints. For complete information about the API, head to the docs.
from plaid import Client
Client.config({
'url': 'https://tartan.plaid.com'
})
By default, all non-200 responses will throw an error.
For more information on Plaid response codes, head to codes.
from plaid import Client
from plaid import errors as plaid_errors
client = Client(client_id='***', secret='***')
try:
response = client.connect('bofa', {
'username': '[something_invalid]',
'password': '***'
})
except plaid_errors.UnauthorizedError:
# handle this
If you would prefer to handle non-20x status codes yourself, you can configure the client to suppress these exceptions
import json
from plaid import Client
Client.config({
url: 'https://tartan.plaid.com',
suppress_http_errors: True,
})
response = client.connect('bofa', {
'username': '[something_invalid]',
'password': '***'
})
if response.ok:
content = json.loads(response.content)
else:
# handle non-20x status codes
Public endpoints (category and institution information) require no authentication and can be accessed as follows:
from plaid import Client
from plaid import errors as plaid_errors
from plaid.utils import json
client = Client()
institutions = json.loads(client.institutions().content)
institutions = json.loads(client.categories().content)
Authenticated endpoints require a valid client_id
and secret
to access. You can use the sandbox client_id and secret for testing (test_id
and test_secret
) during development mode.
from plaid import Client
from plaid import errors as plaid_errors
from plaid.utils import json
client = Client(client_id='***', secret='***')
account_type = 'bofa'
try:
response = client.connect(account_type, {
'username': '***',
'password': '***'
})
except plaid_errors.PlaidError:
pass
else:
connect_data = json.loads(response.content)
from plaid import Client
from plaid import errors as plaid_errors
from plaid.utils import json
client = Client(client_id='***', secret='***')
account_type = 'bofa'
try:
response = client.connect(account_type, {
'username': '***',
'password': '***'
})
except plaid_errors.PlaidError, e:
pass
else:
if response.status_code == 200:
# User connected
data = json.loads(response.content)
elif response.stat_code == 201:
# MFA required
try:
mfa_response = answer_mfa(json.loads(response.content))
except plaid_errors.PlaidError, e:
pass
else:
# check for 200 vs 201 responses
# 201 indicates that additional MFA steps required
def answer_mfa(data):
if data['type'] == 'questions':
# Ask your user for the answer to the question[s].
# Although questions is a list, there is only ever a
# single element in this list, at present
return answer_question([q['question'] for q in data['mfa']])
elif data['type'] == 'list':
return answer_list(data['mfa'])
elif data['type'] == 'selection':
return answer_selections(data['mfa'])
else:
raise Exception('Unknown mfa type from Plaid')
def answer_question(questions):
# We have magically inferred the answer
# so we respond immediately
# In the real world, we would present questions[0]
# to our user and submit their response
answer = 'dogs'
return client.connect_step(account_type, answer)
def answer_list(devices):
# You should specify the device to which the passcode is sent.
# The available devices are present in the devices list
return client.connect_step('bofa', None, options={
'send_method': {'type': 'phone'}
})
def answer_selections(selections):
# We have magically inferred the answers
# so we respond immediately
# In the real world, we would present the selection
# questions and choices to our user and submit their responses
# in a JSON-encoded array with answers provided
# in the same order as the given questions
answer = json.dumps(['Yes', 'No'])
return client.connect_step(account_type, answer)
Effectively the same as Connect.
client = Client(client_id='***', secret='***')
response = client.auth('bofa', {
'username': '***',
'password': '***'
})
Effectively the same as Connect.
client = Client(client_id='***', secret='***')
response = client.auth('bofa', {
'username': '***',
'password': '***'
})
mfa_response = client.auth_step('bofa', 'my_answer')
Add a product (auth or connect to the user)
client = Client(client_id='***', secret='***', access_token='usertoken')
response = client.upgrade('connect')
client = Client(client_id='***', secret='***', access_token='usertoken')
client.connect_delete() ## deletes Connect user
# OR
client.auth_delete() ## deletes Auth user
Exchange a public_token
from Plaid Link for a Plaid access token and then
retrieve account data:
client = Client(client_id='***', secret='***')
response = client.exchange_token('test,chase,connected')
# client.access_token should now be populated with a
# valid access_token; we can make authenticated requests
client.auth('chase', {
'username': '***',
'password': '***'
})
User previously Auth-ed
client = Client(client_id='***', secret='***', access_token='usertoken')
accounts = json.loads(client.auth_get().content)
User previously added
client = Client(client_id='***', secret='***', access_token='usertoken')
response = client.balance()
User previously Connected-ed
client = Client(client_id='***', secret='***', access_token='usertoken')
response = client.connect_get()
json.loads(response.content)
This repository was originally authored by Chris Forrette. Version 1.0.0 was authored by Ben Plesser.
Open an issue!
All pull requests should be linted with flakes8 and tested by running:
$ make test
- PK - fixes and Google App Engine Support