PHPackages                             mrnewport/laravel-plaid - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. mrnewport/laravel-plaid

ActiveLibrary[API Development](/categories/api)

mrnewport/laravel-plaid
=======================

A comprehensive Laravel package for Plaid API integration

v1.0.0(9mo ago)2352↓37.5%MITPHPPHP ^8.1CI failing

Since Jul 30Pushed 9mo agoCompare

[ Source](https://github.com/MrNewport/laravel-plaid)[ Packagist](https://packagist.org/packages/mrnewport/laravel-plaid)[ RSS](/packages/mrnewport-laravel-plaid/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (11)Versions (2)Used By (0)

Laravel Plaid Package
=====================

[](#laravel-plaid-package)

A comprehensive, production-ready Laravel package for the Plaid API, providing complete coverage of all Plaid products and endpoints with a clean, intuitive interface.

[![Latest Version](https://camo.githubusercontent.com/c16d22830961e5fe948e33e10b17b3c6603b1bf9145c2032befe27fc0e0887a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d726e6577706f72742f6c61726176656c2d706c6169642e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mrnewport/laravel-plaid)[![MIT License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Laravel 10.x](https://camo.githubusercontent.com/77d579450465c8f91cf6e423135e0e63f0a86228512e20ee1f9f85dad715bfe1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302e782d7265642e7376673f7374796c653d666c61742d737175617265)](https://laravel.com)[![Laravel 11.x](https://camo.githubusercontent.com/6af540d86774b68377b5404150551aad9a1c12ae64d639fe671176a7192d794a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312e782d7265642e7376673f7374796c653d666c61742d737175617265)](https://laravel.com)[![Laravel 12.x](https://camo.githubusercontent.com/19d5bb0370853f3f5f64da8e47f7b2e14803b7fa5f7c8d04e347ac6849edb9ee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e782d7265642e7376673f7374796c653d666c61742d737175617265)](https://laravel.com)

Features
--------

[](#features)

- 🚀 **Complete API Coverage**: Every Plaid endpoint is implemented
- 🔒 **Type-Safe**: Full PHP type hints and DTOs for all responses
- 🛡️ **Production Ready**: Automatic retries, error handling, and logging
- 🧪 **Fully Tested**: 100% test coverage with Pest
- 📝 **Well Documented**: Clear examples and comprehensive documentation
- ⚡ **Laravel Native**: Service provider, facades, and config publishing
- 🔄 **Auto Retry**: Configurable retry logic for failed requests
- 📊 **Request Logging**: Optional request/response logging with sensitive data redaction

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require mrnewport/laravel-plaid
```

Configuration
-------------

[](#configuration)

Publish the configuration file:

```
php artisan vendor:publish --provider="MrNewport\LaravelPlaid\PlaidServiceProvider" --tag="plaid-config"
```

Add your Plaid credentials to your `.env` file:

```
PLAID_CLIENT_ID=your_client_id
PLAID_SECRET=your_secret_key
PLAID_ENVIRONMENT=sandbox # sandbox, development, or production
PLAID_VERSION=2020-09-14
```

### Optional Configuration

[](#optional-configuration)

```
# HTTP Client Options
PLAID_TIMEOUT=30
PLAID_CONNECT_TIMEOUT=10
PLAID_RETRY_ENABLED=true
PLAID_RETRY_MAX_ATTEMPTS=3
PLAID_RETRY_DELAY=1000

# Webhook Configuration
PLAID_WEBHOOK_SECRET=your_webhook_secret
PLAID_WEBHOOK_TOLERANCE=300

# Logging
PLAID_LOGGING_ENABLED=false
PLAID_LOG_CHANNEL=stack
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

```
use MrNewport\LaravelPlaid\Facades\Plaid;

// Create a link token for Plaid Link
$response = Plaid::linkToken()->create([
    'user' => [
        'client_user_id' => 'user-' . $user->id,
    ],
    'products' => ['auth', 'transactions'],
    'client_name' => 'Your App Name',
    'country_codes' => ['US'],
    'language' => 'en',
    'webhook' => 'https://yourapp.com/webhooks/plaid',
]);

$linkToken = $response['link_token'];
```

### Exchange Public Token

[](#exchange-public-token)

```
// After user completes Plaid Link
$response = Plaid::item()->publicTokenExchange($publicToken);
$accessToken = $response['access_token'];
$itemId = $response['item_id'];

// Store these securely in your database
$user->plaid_access_token = encrypt($accessToken);
$user->plaid_item_id = $itemId;
$user->save();
```

### Get Accounts

[](#get-accounts)

```
$response = Plaid::accounts()->get($accessToken);

foreach ($response['accounts'] as $account) {
    echo $account->name . ': $' . $account->balances['current'] . PHP_EOL;
}
```

### Get Transactions

[](#get-transactions)

```
// Using the new Transactions Sync endpoint (recommended)
$cursor = $user->plaid_cursor; // Store cursor for incremental updates
$hasMore = true;

while ($hasMore) {
    $response = Plaid::transactions()->sync($accessToken, $cursor);

    foreach ($response['added'] as $transaction) {
        // Process new transactions
        Transaction::create([
            'account_id' => $transaction->account_id,
            'amount' => $transaction->amount,
            'name' => $transaction->name,
            'date' => $transaction->date,
            'category' => $transaction->category,
        ]);
    }

    foreach ($response['modified'] as $transaction) {
        // Update existing transactions
    }

    foreach ($response['removed'] as $removed) {
        // Delete removed transactions
    }

    $cursor = $response['next_cursor'];
    $hasMore = $response['has_more'];
}

// Save cursor for next sync
$user->plaid_cursor = $cursor;
$user->save();
```

### Get Auth Information

[](#get-auth-information)

```
$response = Plaid::auth()->get($accessToken);

foreach ($response['accounts'] as $account) {
    $accountNumbers = $response['numbers']->ach;
    foreach ($accountNumbers as $ach) {
        if ($ach['account_id'] === $account['account_id']) {
            echo "Routing: {$ach['routing']}, Account: {$ach['account']}" . PHP_EOL;
        }
    }
}
```

### Create ACH Transfer

[](#create-ach-transfer)

```
// First, create a transfer authorization
$authResponse = Plaid::transfer()->authorizationCreate([
    'access_token' => $accessToken,
    'account_id' => $accountId,
    'type' => 'debit',
    'network' => 'ach',
    'amount' => '100.00',
    'ach_class' => 'ppd',
    'user' => [
        'legal_name' => 'John Doe',
        'email_address' => 'john@example.com',
    ],
]);

// Then create the transfer
if ($authResponse['authorization']['decision'] === 'approved') {
    $transferResponse = Plaid::transfer()->create([
        'access_token' => $accessToken,
        'account_id' => $accountId,
        'authorization_id' => $authResponse['authorization']['id'],
        'description' => 'Payment for order #1234',
    ]);

    $transferId = $transferResponse['transfer']['id'];
}
```

### Identity Verification

[](#identity-verification)

```
$response = Plaid::identityVerification()->create([
    'template_id' => 'idvtmp_xxxxx',
    'gave_consent' => true,
    'user' => [
        'client_user_id' => 'user-' . $user->id,
        'email_address' => $user->email,
        'phone_number' => $user->phone,
        'date_of_birth' => $user->date_of_birth,
        'name' => [
            'given_name' => $user->first_name,
            'family_name' => $user->last_name,
        ],
        'address' => [
            'street' => $user->street_address,
            'city' => $user->city,
            'region' => $user->state,
            'postal_code' => $user->zip,
            'country' => 'US',
        ],
    ],
]);
```

### Investment Data

[](#investment-data)

```
// Get investment holdings
$holdings = Plaid::investments()->holdingsGet($accessToken);

foreach ($holdings['holdings'] as $holding) {
    echo "{$holding['quantity']} shares of {$holding['security_id']}" . PHP_EOL;
}

// Get investment transactions
$transactions = Plaid::investments()->transactionsGet(
    $accessToken,
    '2024-01-01',
    '2024-12-31'
);
```

### Create Processor Token

[](#create-processor-token)

```
// For Stripe
$response = Plaid::processor()->stripeTokenCreate($accessToken, $accountId);
$stripeToken = $response['stripe_bank_account_token'];

// For Dwolla
$response = Plaid::processor()->dwollaTokenCreate($accessToken, $accountId);
$processorToken = $response['processor_token'];

// For other processors
$response = Plaid::processor()->tokenCreate($accessToken, $accountId, 'achq');
$processorToken = $response['processor_token'];
```

Available Services
------------------

[](#available-services)

### Core Services

[](#core-services)

- **Accounts**: `Plaid::accounts()` - Account information and balances
- **Auth**: `Plaid::auth()` - Account and routing numbers
- **Transactions**: `Plaid::transactions()` - Transaction data and categorization
- **Identity**: `Plaid::identity()` - Account holder information
- **Balance**: `Plaid::accounts()->getBalance()` - Real-time balance

### Wealth &amp; Investments

[](#wealth--investments)

- **Investments**: `Plaid::investments()` - Investment holdings and transactions
- **Liabilities**: `Plaid::liabilities()` - Loan and credit card data

### Income &amp; Employment

[](#income--employment)

- **Income**: `Plaid::income()` - Income verification
- **Employment**: `Plaid::employment()` - Employment verification
- **Assets**: `Plaid::assets()` - Asset reports for lending

### Payments &amp; Transfers

[](#payments--transfers)

- **Transfer**: `Plaid::transfer()` - ACH transfers and payments
- **Payment Initiation**: `Plaid::paymentInitiation()` - UK/EU payments

### Risk &amp; Compliance

[](#risk--compliance)

- **Identity Verification**: `Plaid::identityVerification()` - KYC/AML
- **Monitor**: Built into relevant services
- **Beacon**: Built into relevant services

### Other Services

[](#other-services)

- **Link Token**: `Plaid::linkToken()` - Create and manage Link tokens
- **Item**: `Plaid::item()` - Manage Items (connections)
- **Institutions**: `Plaid::institutions()` - Institution information
- **Processor**: `Plaid::processor()` - Processor tokens
- **Statements**: `Plaid::statements()` - PDF statements
- **Sandbox**: `Plaid::sandbox()` - Testing utilities

Error Handling
--------------

[](#error-handling)

The package provides specific exception types for different error scenarios:

```
use MrNewport\LaravelPlaid\Exceptions\PlaidException;
use MrNewport\LaravelPlaid\Exceptions\PlaidAuthenticationException;
use MrNewport\LaravelPlaid\Exceptions\PlaidRateLimitException;
use MrNewport\LaravelPlaid\Exceptions\PlaidRequestException;

try {
    $accounts = Plaid::accounts()->get($accessToken);
} catch (PlaidAuthenticationException $e) {
    // Invalid API keys
    Log::error('Plaid authentication failed: ' . $e->getMessage());
} catch (PlaidRateLimitException $e) {
    // Rate limit exceeded
    Log::warning('Plaid rate limit hit: ' . $e->getMessage());
} catch (PlaidRequestException $e) {
    // Invalid request (400 errors)
    Log::error('Invalid Plaid request: ' . $e->getMessage());
    Log::error('Error code: ' . $e->getErrorCode());
    Log::error('Error type: ' . $e->getErrorType());
} catch (PlaidException $e) {
    // Other Plaid errors
    Log::error('Plaid error: ' . $e->getMessage());
}
```

Webhooks
--------

[](#webhooks)

Handle Plaid webhooks in your application:

```
Route::post('/webhooks/plaid', function (Request $request) {
    $webhookType = $request->input('webhook_type');
    $webhookCode = $request->input('webhook_code');

    switch ($webhookType) {
        case 'TRANSACTIONS':
            if ($webhookCode === 'SYNC_UPDATES_AVAILABLE') {
                // Sync new transactions
                $itemId = $request->input('item_id');
                dispatch(new SyncPlaidTransactions($itemId));
            }
            break;

        case 'ITEM':
            if ($webhookCode === 'ERROR') {
                // Handle item errors
                $error = $request->input('error');
                // Notify user to re-authenticate
            }
            break;
    }

    return response()->json(['status' => 'ok']);
});
```

Logging
-------

[](#logging)

Enable request/response logging for debugging:

```
PLAID_LOGGING_ENABLED=true
PLAID_LOG_CHANNEL=plaid
```

Configure the log channel in `config/logging.php`:

```
'channels' => [
    'plaid' => [
        'driver' => 'daily',
        'path' => storage_path('logs/plaid.log'),
        'level' => 'debug',
        'days' => 7,
    ],
],
```

Sensitive fields are automatically redacted from logs.

Testing
-------

[](#testing)

The package includes comprehensive test coverage using Pest:

```
# Run all tests
composer test

# Run with coverage
composer test-coverage

# Run specific test file
vendor/bin/pest tests/Unit/Services/TransactionsServiceTest.php
```

### Mocking in Tests

[](#mocking-in-tests)

```
use MrNewport\LaravelPlaid\Facades\Plaid;

// In your test
Plaid::shouldReceive('accounts->get')
    ->once()
    ->with($accessToken)
    ->andReturn([
        'accounts' => [
            ['account_id' => 'test123', 'name' => 'Checking'],
        ],
    ]);
```

Sandbox Testing
---------------

[](#sandbox-testing)

Use the sandbox environment for testing:

```
// Create sandbox public token
$publicToken = Plaid::sandbox()->publicTokenCreate(
    'ins_109508',
    ['auth', 'transactions']
);

// Fire a webhook in sandbox
Plaid::sandbox()->itemFireWebhook($accessToken, 'DEFAULT_UPDATE');

// Simulate transfer events
Plaid::sandbox()->transferSimulate($transferId, 'posted');
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom HTTP Client Options

[](#custom-http-client-options)

```
// config/plaid.php
'http_options' => [
    'timeout' => 60,
    'connect_timeout' => 10,
    'retry_enabled' => true,
    'retry_max_attempts' => 5,
    'retry_delay' => 2000,
    'proxy' => 'tcp://localhost:8080',
],
```

### Using Without Facade

[](#using-without-facade)

```
use MrNewport\LaravelPlaid\Plaid;
use MrNewport\LaravelPlaid\PlaidClient;

// Inject via constructor
public function __construct(private Plaid $plaid)
{
}

// Or resolve from container
$plaid = app(Plaid::class);
$accounts = $plaid->accounts()->get($accessToken);
```

### Direct Client Access

[](#direct-client-access)

```
$client = Plaid::getClient();
$response = $client->post('/custom/endpoint', ['data' => 'value']);
```

Troubleshooting
---------------

[](#troubleshooting)

### Common Issues

[](#common-issues)

1. **SSL Certificate Issues**

    ```
    # Download latest CA bundle
    curl -o /path/to/cacert.pem https://curl.se/ca/cacert.pem
    ```

    Configure in your `.env`:

    ```
    CURL_CA_BUNDLE=/path/to/cacert.pem
    ```
2. **Rate Limiting**The package automatically retries on rate limit errors. Adjust retry settings:

    ```
    PLAID_RETRY_MAX_ATTEMPTS=5
    PLAID_RETRY_DELAY=5000
    ```
3. **Timeout Issues**Increase timeout for large requests:

    ```
    PLAID_TIMEOUT=120
    PLAID_CONNECT_TIMEOUT=30
    ```

Contributing
------------

[](#contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [MrNewport](https://github.com/mrnewport)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

Support
-------

[](#support)

For support, please email  or create an issue on GitHub.

Changelog
---------

[](#changelog)

Please see [CHANGELOG.md](CHANGELOG.md) for recent changes.

---

Built with ❤️ for the Laravel community

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance57

Moderate activity, may be stable

Popularity20

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

287d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/19dc283a8ecb45d1efbc444dc510eb63c8aab21427be09f3c1aefd507a5ab40c?d=identicon)[mrnewport](/maintainers/mrnewport)

---

Top Contributors

[![MrNewport](https://avatars.githubusercontent.com/u/48736345?v=4)](https://github.com/MrNewport "MrNewport (3 commits)")

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/mrnewport-laravel-plaid/health.svg)

```
[![Health](https://phpackages.com/badges/mrnewport-laravel-plaid/health.svg)](https://phpackages.com/packages/mrnewport-laravel-plaid)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[skagarwal/google-places-api

Google Places Api

1913.0M8](/packages/skagarwal-google-places-api)[essa/api-tool-kit

set of tools to build an api with laravel

52680.5k](/packages/essa-api-tool-kit)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[simplestats-io/laravel-client

Client for SimpleStats!

4515.5k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
