Plaid

raw JSON →
38.3.0 verified Tue May 12 auth: yes python install: verified quickstart: stale

Official Python client for the Plaid API (bank account linking, transactions, identity, income verification). Auto-generated from OpenAPI spec. Updated monthly, major versions contain breaking changes. Only supports the 2020-09-14 API version (no version selection in client — API version is fixed per SDK release).

pip install plaid-python
error ModuleNotFoundError: No module named 'plaid'
cause The `plaid-python` package is installed as `plaid`, so the import statement should use `import plaid`.
fix
import plaid
error ImportError: cannot import name 'PlaidApi' from 'plaid.api.plaid_api'
cause The `PlaidApi` class was moved to be directly under the `plaid` module in recent versions (e.g., v30+); the old import path is no longer valid.
fix
import plaid # ... client = plaid.PlaidApi(api_client)
error "error_code":"INVALID_CLIENT_ID"
cause The configured Plaid `client_id` is either incorrect, missing, or does not match the specified environment (e.g., Sandbox, Development, Production).
fix
Verify that your CLIENT_ID, SECRET, and ENVIRONMENT variables are correctly set and correspond to a valid Plaid application's credentials.
error "missing required field 'user.client_user_id'"
cause When creating a `LinkTokenCreateRequest`, the `user` object's `client_user_id` field is mandatory and was either not provided or was provided incorrectly.
fix
Ensure the LinkTokenCreateRequestUser object correctly includes a unique client_user_id string, for example: LinkTokenCreateRequestUser(client_user_id='unique-user-id').
breaking v8.0.0 (August 2021) completely removed the old Client class and all previous import patterns. Any tutorial using 'from plaid import Client' or 'Client(client_id=..., secret=..., environment=...)' fails with ImportError.
fix Use Configuration + ApiClient + PlaidApi pattern. See README for current quickstart.
breaking plaid-python ships a major version (x.0.0) roughly monthly. Major versions may include breaking changes — new required fields, renamed parameters, or removed endpoints. Unpinned installs will auto-upgrade.
fix Pin to a specific version in production: pip install plaid-python==38.3.0. Monitor changelog before upgrading major versions.
breaking Each endpoint requires importing its specific request model. Passing a plain dict instead of the typed request object raises a TypeError. Old-style dict-based calls from pre-v8 tutorials do not work.
fix Import the model for each endpoint: from plaid.model.transactions_sync_request import TransactionsSyncRequest, then pass an instance.
gotcha Sandbox and Production have separate API secrets. The client_id is shared but the secret differs per environment. Using the wrong secret for an environment returns 401.
fix Get environment-specific secrets from Plaid Dashboard > Team Settings > Keys. Store separately as PLAID_SECRET_SANDBOX and PLAID_SECRET_PRODUCTION.
gotcha Plaid API responses are typed objects, not dicts. Code trying to access response['transactions'] fails with TypeError. Attributes are accessed as response.added, response.modified, etc.
fix Access typed attributes: response.added for new transactions, response.next_cursor for pagination cursor, etc.
gotcha Beta product APIs (e.g. Assets, CRA) are subject to breaking changes without versioning, with 30 days notice. GA products are versioned but the SDK fixes to a single API version — there is no per-request API version override.
fix Monitor Plaid changelog for beta product changes. For GA products, upgrade SDK major versions intentionally, not automatically.
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.31s 76.9M
3.10 slim (glibc) - - 0.21s 77M
3.11 alpine (musl) - - 0.49s 85.1M
3.11 slim (glibc) - - 0.39s 86M
3.12 alpine (musl) - - 0.42s 74.4M
3.12 slim (glibc) - - 0.41s 75M
3.13 alpine (musl) - - 0.41s 73.8M
3.13 slim (glibc) - - 0.40s 74M
3.9 alpine (musl) - - 0.30s 76.6M
3.9 slim (glibc) - - 0.28s 77M

Plaid uses strongly-typed request/response models. Each endpoint has its own request model (e.g. TransactionsSyncRequest). Import the specific model for each call.

import plaid
from plaid.api import plaid_api
from plaid.model.transactions_sync_request import TransactionsSyncRequest
import json

configuration = plaid.Configuration(
    host=plaid.Environment.Sandbox,  # or Production
    api_key={
        'clientId': 'your_client_id',
        'secret': 'your_secret'
    }
)
api_client = plaid.ApiClient(configuration)
client = plaid_api.PlaidApi(api_client)

# Sync transactions
request = TransactionsSyncRequest(access_token='access-sandbox-...')
response = client.transactions_sync(request)
transactions = response.added

# Error handling
try:
    response = client.transactions_sync(request)
except plaid.ApiException as e:
    error = json.loads(e.body)
    print(error['error_code'])  # e.g. 'ITEM_LOGIN_REQUIRED'