skeylup / laravel-pipedrive
Wrapper for Pipedrive <> Laravel
Requires
- php: ^8.4
- devio/pipedrive: ^2.17
- illuminate/contracts: ^10.0||^11.0||^12.0
- spatie/laravel-data: ^4.17
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.0.0||^9.0.0||^8.22.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
This package is auto-updated.
Last update: 2025-07-20 08:36:36 UTC
README
A comprehensive Laravel package for seamless Pipedrive CRM integration. Sync entities, manage custom fields, and leverage Eloquent relationships with a robust JSON-based data structure for maximum flexibility and performance.
β¨ Features
- π Complete Entity Synchronization - Activities, Deals, Files, Notes, Organizations, Persons, Pipelines, Products, Stages, Users, Goals
- π Real-Time Webhooks - Instant synchronization with secure webhook handling
- οΏ½ Scheduled Synchronization - Automated background sync with configurable frequency
- π‘οΈ API Rate Limiting - Built-in delays to prevent API rate limit issues
- οΏ½π Eloquent Relationships - Navigate between entities with Laravel's relationship system
- π― Custom Fields Management - Full support for Pipedrive custom fields with automated synchronization
- ποΈ Hybrid Data Structure - Essential columns + JSON storage for maximum flexibility
- π Dual Authentication - Support for both API tokens and OAuth
- β‘ Performance Optimized - Efficient queries with proper indexing
- π Rich Querying - Advanced filtering and relationship queries
- π Automatic Entity Merging - Seamless handling of entity merges with relationship continuity
- π€ Smart Custom Field Detection - Real-time detection and sync of new custom fields via webhooks
π‘οΈ Production-Ready Robustness
This package includes enterprise-grade robustness features designed for production environments:
Smart Rate Limiting
- π¦ Token-based system supporting Pipedrive's December 2024 rate limiting changes
- π Daily budget tracking with automatic token consumption monitoring
- β±οΈ Exponential backoff with intelligent retry strategies
- π― Per-endpoint cost calculation for optimal API usage
Intelligent Error Handling
- π Circuit breaker pattern prevents cascading failures
- π― Error classification with specific retry strategies for different error types
- π Automatic exception classification (rate limits, auth, server errors, etc.)
- π Failure tracking with automatic recovery detection
Adaptive Memory Management
- π§ Real-time memory monitoring with automatic alerts
- π Dynamic batch size adjustment based on memory usage
- ποΈ Automatic garbage collection during large operations
- β οΈ Memory threshold warnings with suggested optimizations
API Health Monitoring
- π Continuous health checks with cached status
- π Performance degradation detection with response time monitoring
- π Automatic recovery when API health improves
- π Health statistics and trend analysis
Centralized Job Architecture
- ποΈ Unified processing eliminates code duplication
- β‘ Dual execution modes (synchronous for commands, asynchronous for schedulers)
- π Progress tracking with detailed statistics
- π Automatic retry logic with intelligent backoff strategies
π¦ Installation
Install the package via Composer:
composer require skeylup/laravel-pipedrive
Publish and run the migrations:
php artisan vendor:publish --tag="laravel-pipedrive-migrations"
php artisan migrate
Publish the config file:
php artisan vendor:publish --tag="laravel-pipedrive-config"
βοΈ Configuration
Add your Pipedrive credentials to your .env
file:
API Token Authentication (Recommended for Simple Integrations)
The simplest way to authenticate with Pipedrive. Get your API token from Pipedrive:
- Log into your Pipedrive account
- Go to Settings β Personal preferences β API
- Copy your API token
- Add to your
.env
file:
PIPEDRIVE_AUTH_METHOD=token PIPEDRIVE_TOKEN=your_api_token_here
OAuth 2.0 Authentication (Recommended for Production Apps)
OAuth provides more secure authentication and is required for public applications. Follow these steps:
Step 1: Create a Pipedrive App
- Go to Pipedrive Developer Hub
- Sign in with your Pipedrive account
- Click "Create an app"
- Fill in your app details:
- App name: Your application name
- App description: Brief description of your app
- App URL: Your application's homepage URL
- Callback URL:
https://your-domain.com/pipedrive/oauth/callback
- Select required scopes (permissions your app needs)
- Submit for review (for public apps) or create as private app
Step 2: Get Your OAuth Credentials
After app creation/approval, you'll receive:
- Client ID: Public identifier for your app
- Client Secret: Secret key (keep this secure!)
Step 3: Configure Your Laravel App
Add OAuth credentials to your .env
file:
PIPEDRIVE_AUTH_METHOD=oauth PIPEDRIVE_CLIENT_ID=your_client_id_from_pipedrive PIPEDRIVE_CLIENT_SECRET=your_client_secret_from_pipedrive PIPEDRIVE_REDIRECT_URL=https://your-domain.com/pipedrive/oauth/callback
Step 4: OAuth Web Interface (Built-in)
The package includes a complete OAuth web interface with beautiful UI pages. After configuration, you can use these routes:
# OAuth management routes (automatically registered) /pipedrive/oauth/authorize # Start OAuth flow (protected) /pipedrive/oauth/callback # OAuth callback (set this in Pipedrive app) /pipedrive/oauth/status # Check connection status (protected) /pipedrive/oauth/disconnect # Disconnect from Pipedrive (protected) /pipedrive/webhook/health # Webhook health check (protected)
π Security Note: Most routes are protected by dashboard authorization in non-local environments. See Dashboard Authorization for configuration details.
Step 5: Initiate OAuth Flow
Option A: Use Built-in Web Interface
- Visit
/pipedrive/oauth/status
to check current status - Click "Connect to Pipedrive" or visit
/pipedrive/oauth/authorize
- You'll see a beautiful authorization page with scope details
- Click "Connect to Pipedrive" to redirect to Pipedrive
- Authorize your app on Pipedrive
- You'll be redirected back with a success page
Option B: Programmatic OAuth (Custom Implementation)
// In your controller public function connectToPipedrive() { $authService = app(\Skeylup\LaravelPipedrive\Services\PipedriveAuthService::class); $pipedrive = $authService->getPipedriveInstance(); $authUrl = $pipedrive->getAuthorizationUrl([ 'scope' => 'deals:read deals:write persons:read persons:write' ]); return redirect($authUrl); }
Step 6: Non-Expiring Tokens
The package automatically handles token storage and refresh. For non-expiring tokens:
- Tokens are stored securely in cache with long TTL (1 year for non-expiring tokens)
- No manual refresh needed for non-expiring tokens
- Automatic refresh for expiring tokens (when supported by Pipedrive)
- Use
/pipedrive/oauth/status
to monitor token status
OAuth vs API Token Comparison
Feature | API Token | OAuth 2.0 |
---|---|---|
Setup Complexity | Simple | Moderate |
Security | Good | Excellent |
Token Expiration | Never | Yes (with refresh) |
User Consent | Not required | Required |
Multi-user Support | No | Yes |
Recommended For | Personal/Internal apps | Production/Public apps |
Pipedrive App Store | Not eligible | Required |
Scheduled Synchronization & Robustness Configuration
# Enable scheduled sync (SAFE MODE - always uses standard sync, never full-data) PIPEDRIVE_SCHEDULER_ENABLED=true PIPEDRIVE_SCHEDULER_FREQUENCY=24 PIPEDRIVE_SCHEDULER_TIME=02:00 PIPEDRIVE_SCHEDULER_LIMIT=500 # Custom fields automatic synchronization PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_ENABLED=true PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_FREQUENCY=1 PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_FORCE=true # Webhook custom field detection PIPEDRIVE_WEBHOOKS_DETECT_CUSTOM_FIELDS=true # Entity configuration PIPEDRIVE_ENABLED_ENTITIES=deals,activities,persons,organizations,products # Robustness features PIPEDRIVE_RATE_LIMITING_ENABLED=true PIPEDRIVE_DAILY_TOKEN_BUDGET=10000 PIPEDRIVE_MEMORY_THRESHOLD=80 PIPEDRIVE_HEALTH_MONITORING_ENABLED=true PIPEDRIVE_CIRCUIT_BREAKER_THRESHOLD=5
π Quick Start
Test Your Connection
php artisan pipedrive:test-connection
View Configuration
# Show current entity configuration php artisan pipedrive:config --entities # Show full configuration php artisan pipedrive:config # JSON output php artisan pipedrive:config --json
Sync Entities from Pipedrive
# Sync all enabled entities php artisan pipedrive:sync-entities # Sync specific entity (even if disabled) php artisan pipedrive:sync-entities --entity=deals --limit=50 # Verbose output with configuration details php artisan pipedrive:sync-entities --entity=users --verbose
Sync Custom Fields
# Sync all custom fields php artisan pipedrive:sync-custom-fields # Sync specific entity fields php artisan pipedrive:sync-custom-fields --entity=deal --verbose # Force sync (skip confirmations) php artisan pipedrive:sync-custom-fields --force # Full data mode with pagination (use with caution) php artisan pipedrive:sync-custom-fields --full-data --force
π€ Automatic Custom Field Synchronization:
- Hourly Scheduler: Automatically syncs custom fields every hour (configurable)
- Webhook Detection: Real-time detection of new custom fields in entity updates
- Smart Triggering: Only syncs when new fields are detected to minimize API usage
Scheduled Synchronization
# Run scheduled sync manually (SAFE MODE - always uses standard sync) php artisan pipedrive:scheduled-sync # Test configuration (dry run) php artisan pipedrive:scheduled-sync --dry-run # Verbose output for debugging php artisan pipedrive:scheduled-sync --verbose
π‘οΈ Safety Features:
- Scheduled sync ALWAYS uses standard mode (limit=500, sorted by last modified)
- NEVER uses full-data mode for safety and performance
- Includes comprehensive robustness features (rate limiting, error handling, memory management)
- Automatic retry logic with circuit breaker protection
Real-Time Webhooks
# Setup webhook for real-time sync php artisan pipedrive:webhooks create \ --url=https://your-app.com/pipedrive/webhook \ --event=*.* \ --auth-user=webhook_user \ --auth-pass=secure_password # List existing webhooks php artisan pipedrive:webhooks list # Test webhook endpoint curl https://your-app.com/pipedrive/webhook/health
π Dashboard Authorization
The package includes a Telescope-like authorization system to protect management routes in production:
Quick Setup
# Complete installation (config, migrations, views, service provider) php artisan pipedrive:install # Run migrations php artisan migrate # Add to config/app.php providers array App\Providers\PipedriveServiceProvider::class,
Configuration Options
Option 1: Simple Email/ID Authorization
// config/pipedrive.php 'dashboard' => [ 'authorized_emails' => [ 'admin@example.com', 'developer@example.com', ], 'authorized_user_ids' => [1, 2], ],
Option 2: Custom Gate Logic
// app/Providers/PipedriveServiceProvider.php Gate::define('viewPipedrive', function ($user) { return $user->hasRole('admin') || $user->can('manage-pipedrive'); });
Protected Routes: /pipedrive/oauth/*
, /pipedrive/webhook/health
π Complete Authorization Guide β
π Models & Relationships
All Pipedrive entities are available as Eloquent models with full relationship support:
use Skeylup\LaravelPipedrive\Models\{ PipedriveActivity, PipedriveDeal, PipedriveFile, PipedriveNote, PipedriveOrganization, PipedrivePerson, PipedrivePipeline, PipedriveProduct, PipedriveStage, PipedriveUser, PipedriveGoal }; // Link your Laravel models to Pipedrive entities use Skeylup\LaravelPipedrive\Traits\HasPipedriveEntity; use Skeylup\LaravelPipedrive\Enums\PipedriveEntityType; class Order extends Model { use HasPipedriveEntity; // Define default Pipedrive entity type protected PipedriveEntityType $pipedriveEntityType = PipedriveEntityType::DEALS; public function linkToDeal(int $dealId): void { $this->linkToPipedriveEntity($dealId, true); } } // Navigate relationships $deal = PipedriveDeal::with(['user', 'person', 'organization', 'stage'])->first(); echo $deal->user->name; // Deal owner echo $deal->person->name; // Contact person echo $deal->organization->name; // Company echo $deal->stage->name; // Current stage // Reverse relationships $user = PipedriveUser::with(['deals', 'activities'])->first(); echo $user->deals->count(); // Number of deals echo $user->activities->count(); // Number of activities
π Entity Linking
Link your Laravel models to Pipedrive entities with morphic relationships:
// In your Laravel model class Order extends Model { use HasPipedriveEntity; // Set default entity type protected PipedriveEntityType $pipedriveEntityType = PipedriveEntityType::DEALS; } // Usage $order = Order::create([...]); // Link to Pipedrive deal (uses default entity type) $order->linkToPipedriveEntity(123, true, ['source' => 'manual']); // Link to additional entities $order->linkToPipedrivePerson(456, false, ['role' => 'customer']); $order->linkToPipedriveOrganization(789, false, ['type' => 'client']); // Get linked entities $deal = $order->getPrimaryPipedriveEntity(); $persons = $order->getPipedrivePersons(); // Check if linked if ($order->isLinkedToPipedriveEntity(123)) { // Order is linked to deal 123 } // Push modifications to Pipedrive (async by default) $result = $order->pushToPipedrive([ 'title' => 'Updated Order', 'value' => 1500.00, ], [ 'Order Number' => $order->order_number, 'Customer Email' => $order->customer_email, ]); // Force synchronous execution $result = $order->pushToPipedrive($modifications, $customFields, true); // Use custom queue with retries $result = $order->pushToPipedrive($modifications, $customFields, false, 'high-priority', 5); // Display details with readable custom field names $details = $order->displayPipedriveDetails(); foreach ($details['custom_fields'] as $name => $fieldData) { echo "{$name}: {$fieldData['value']}\n"; } // Manage links via Artisan php artisan pipedrive:entity-links stats php artisan pipedrive:entity-links sync php artisan pipedrive:entity-links cleanup
π‘ Events
Listen to Pipedrive entity changes with Laravel events:
// In EventServiceProvider.php protected $listen = [ PipedriveEntityCreated::class => [ App\Listeners\NewDealNotificationListener::class, ], PipedriveEntityUpdated::class => [ App\Listeners\DealStatusChangeListener::class, ], PipedriveEntityDeleted::class => [ App\Listeners\CleanupListener::class, ], ]; // Example listener public function handle(PipedriveEntityUpdated $event) { if ($event->isDeal() && $event->hasChanged('status')) { $deal = $event->entity; $newStatus = $event->getNewValue('status'); if ($newStatus === 'won') { CreateInvoiceJob::dispatch($deal); } } }
π Querying Data
Basic Queries
// Active deals with high value $deals = PipedriveDeal::where('status', 'open') ->where('value', '>', 10000) ->active() ->get(); // Overdue activities $activities = PipedriveActivity::where('done', false) ->where('due_date', '<', now()) ->with('user') ->get();
Relationship Queries
// Deals from specific organization $deals = PipedriveDeal::whereHas('organization', function($query) { $query->where('name', 'like', '%Acme Corp%'); })->get(); // Activities assigned to specific user $activities = PipedriveActivity::whereHas('user', function($query) { $query->where('email', 'john@example.com'); })->get();
JSON Data Access
$activity = PipedriveActivity::first(); // Essential data (columns) echo $activity->subject; echo $activity->type; echo $activity->done; // Extended data (JSON) echo $activity->getPipedriveAttribute('note'); echo $activity->getPipedriveAttribute('duration'); echo $activity->getPipedriveAttribute('location'); // Direct JSON access $allData = $activity->pipedrive_data; $customField = $activity->pipedrive_data['custom_field_hash'] ?? null;
π Advanced Synchronization
Smart Sync Commands
# Standard mode: Latest modifications (optimized) php artisan pipedrive:sync-entities --entity=deals --limit=500 # Full data mode: ALL data with pagination (use with caution) php artisan pipedrive:sync-entities --entity=deals --full-data # Custom fields sync php artisan pipedrive:sync-custom-fields --entity=deal
Key Features:
- Smart Sorting: Latest modifications first (default) or chronological for full sync
- API Optimization: Respects Pipedrive API limits (max 500 per request)
- Pagination Support: Automatic pagination for large datasets
- Safety Warnings: Built-in warnings for resource-intensive operations
β οΈ Important: Use --full-data
with caution due to API rate limits. See Sync Commands Documentation for details.
βοΈ Entity Configuration
Control which Pipedrive entities are synchronized using the PIPEDRIVE_ENABLED_ENTITIES
environment variable:
# Enable specific entities (comma-separated) PIPEDRIVE_ENABLED_ENTITIES=deals,activities,persons,organizations # Enable all entities PIPEDRIVE_ENABLED_ENTITIES=all # Disable all entities (empty value) PIPEDRIVE_ENABLED_ENTITIES=
Available Entities
activities
- Activities/Tasksdeals
- Deals/Opportunitiesfiles
- Files/Attachmentsgoals
- Goals/Targetsnotes
- Notes/Commentsorganizations
- Companies/Organizationspersons
- People/Contactspipelines
- Sales Pipelinesproducts
- Products/Servicesstages
- Pipeline Stagesusers
- Users/Team Members
Configuration Commands
# View current configuration php artisan pipedrive:config # View only entity configuration php artisan pipedrive:config --entities # Export configuration as JSON php artisan pipedrive:config --json
Behavior
- Commands: Only enabled entities are synchronized by default
- Schedulers: Only enabled entities are included in automated sync
- Force Override: Use
--force
flag to sync disabled entities manually - Validation: Invalid entity names in configuration are ignored with warnings
π Webhook Management
The package provides intelligent webhook management with smart configuration defaults:
Smart Webhook Creation
# Quick setup with auto-configuration (recommended) php artisan pipedrive:webhooks create --auto-config # Interactive setup with intelligent suggestions php artisan pipedrive:webhooks create --verbose # Test webhook connectivity php artisan pipedrive:webhooks test
Configuration-Aware Features
- Auto URL Detection: Uses
APP_URL
+ webhook path from config - Smart Event Suggestions: Based on your
PIPEDRIVE_ENABLED_ENTITIES
- Auto Authentication: Uses configured HTTP Basic Auth credentials
- Connectivity Testing: Validates webhook endpoints before creation
Example Workflow
# 1. Configure your environment APP_URL=https://your-app.com PIPEDRIVE_ENABLED_ENTITIES=deals,activities,persons PIPEDRIVE_WEBHOOK_BASIC_AUTH_ENABLED=true PIPEDRIVE_WEBHOOK_BASIC_AUTH_USERNAME=admin PIPEDRIVE_WEBHOOK_BASIC_AUTH_PASSWORD=secure_password # 2. Test webhook connectivity php artisan pipedrive:webhooks test # 3. Create webhook with smart defaults php artisan pipedrive:webhooks create --auto-config --test-url # 4. List existing webhooks php artisan pipedrive:webhooks list
Manual Configuration
# Create webhook manually php artisan pipedrive:webhooks create \ --url="https://your-app.com/pipedrive/webhook" \ --event="*.*" \ --auth-user="webhook_user" \ --auth-pass="secure_password" # Delete webhook php artisan pipedrive:webhooks delete --id=123
See Webhook Management Documentation for detailed usage.
π― Custom Fields
Manual Management
use Skeylup\LaravelPipedrive\Models\PipedriveCustomField; // Get all deal fields $dealFields = PipedriveCustomField::forEntity('deal')->active()->get(); // Get only custom fields (not default Pipedrive fields) $customFields = PipedriveCustomField::forEntity('deal')->customOnly()->get(); // Get mandatory fields $mandatoryFields = PipedriveCustomField::forEntity('deal')->mandatory()->get(); // Access field properties foreach ($dealFields as $field) { echo "Field: {$field->name} ({$field->field_type})\n"; echo "Mandatory: " . ($field->isMandatory() ? 'Yes' : 'No') . "\n"; if ($field->hasOptions()) { echo "Options: " . implode(', ', $field->getOptions()) . "\n"; } }
π€ Automatic Synchronization
Hourly Scheduler:
# Enable automatic hourly sync (default: true) PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_ENABLED=true # Sync frequency in hours (default: 1 hour) PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_FREQUENCY=1 # Force sync without confirmations (default: true) PIPEDRIVE_CUSTOM_FIELDS_SCHEDULER_FORCE=true
Real-Time Webhook Detection:
# Enable detection of new custom fields in webhooks (default: true) PIPEDRIVE_WEBHOOKS_DETECT_CUSTOM_FIELDS=true
How It Works:
- Webhook Processing: Automatically detects new custom fields (40-character hash keys) in entity updates
- Smart Detection: Compares with known fields and triggers sync only when new fields are found
- Supported Entities: Deals, Persons, Organizations, Products, Activities
- Asynchronous Processing: Uses queue jobs to avoid blocking webhook processing
- Error Handling: Graceful error handling that doesn't interrupt main webhook processing
See Custom Field Automation Documentation for detailed configuration and monitoring.
π Documentation
Core Features
- π Models & Relationships - Complete guide to all models and their relationships
- π Data Synchronization - Entity and custom field sync strategies
- β‘ Sync Commands - Advanced sync commands with pagination and sorting
- π Real-Time Webhooks - Instant synchronization with webhook handling
- π― Custom Fields - Working with Pipedrive custom fields
- π Authentication - API token and OAuth setup
Advanced Features
- π Entity Linking - Link Laravel models to Pipedrive entities
- π Push to Pipedrive - Sync modifications back to Pipedrive
- π‘ Events System - Laravel events for Pipedrive operations
- π Entity Merging - Automatic handling of entity merges
- π Using Relations - Navigate between Pipedrive entities
- π€ Custom Field Automation - Automated custom field synchronization
Technical Reference
- ποΈ Database Structure - Understanding the hybrid data approach
- β‘ Performance - Optimization tips and best practices
π οΈ Commands Reference
Command | Description | Options |
---|---|---|
pipedrive:test-connection |
Test Pipedrive API connection | - |
pipedrive:sync-entities |
Sync Pipedrive entities | --entity , --limit , --force , --verbose |
pipedrive:sync-custom-fields |
Sync custom fields (with automatic scheduling) | --entity , --force , --full-data , --verbose |
pipedrive:scheduled-sync |
Automated scheduled sync | --dry-run , --verbose |
pipedrive:webhooks |
Manage webhooks (list/create/delete/test) with smart configuration | action , --url , --event , --id , --auth-user , --auth-pass , --auto-config , --test-url , --verbose |
pipedrive:entity-links |
Manage entity links (stats/sync/cleanup/list) | action , --entity-type , --model-type , --status , --limit , --verbose |
ποΈ Database Structure
Each Pipedrive entity table follows this hybrid structure:
-- Essential columns (indexed, queryable) id -- Laravel auto-increment pipedrive_id -- Unique Pipedrive ID name/title/subject -- Main identifier [relationships] -- Foreign keys (user_id, person_id, etc.) active_flag -- Status flag -- JSON storage (flexible, all other data) pipedrive_data -- Complete Pipedrive data as JSON -- Timestamps pipedrive_add_time -- Pipedrive creation time pipedrive_update_time -- Pipedrive modification time created_at/updated_at -- Laravel timestamps
π Documentation
Comprehensive documentation is available in the docs/
directory:
Core Features
- Authentication - API token and OAuth setup
- Synchronization - Data sync strategies and best practices
- Custom Fields - Managing Pipedrive custom fields
- Custom Field Automation - Automated synchronization and detection
- Entity Merging - Automatic handling of entity merges
- Webhooks - Real-time data synchronization
- Entity Linking - Connect Laravel models to Pipedrive entities
Commands
- Sync Commands - Complete sync command reference
- Scheduled Sync - Automated synchronization setup
Robustness & Production Features
- Robustness Overview - Production-ready features and architecture
- Troubleshooting Guide - Common issues and solutions
Advanced Topics
- Models & Relationships - Eloquent relationships and querying
- Performance - Optimization and best practices
- Database Structure - Table schemas and indexing
- Events - Event system and listeners
π€ Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
π Security
If you discover any security-related issues, please email kevin.eggermont@gmail.com instead of using the issue tracker.
π License
The MIT License (MIT). Please see License File for more information.
π Credits
- Built on top of devio/pipedrive
- Plugin template from spatie/laravel-package-tools
- Powered by Laravel