masterfermin02 / vicidial-api-wrapper
Beautiful and simple Implementation to integrate Vicidial API
Package info
github.com/masterfermin02/vicidial-api-wrapper
Language:HTML
pkg:composer/masterfermin02/vicidial-api-wrapper
Requires
- php: ^8.2
- ext-json: *
- graham-campbell/guzzle-factory: ^5.0
- php-http/discovery: ^1.19
- php-http/multipart-stream-builder: ^1.3
- psr/http-client: ^1.0
- psr/http-client-implementation: *
- psr/http-factory-implementation: *
- psr/http-message: ^1.1
- psr/log: ^3.0
Requires (Dev)
- guzzlehttp/guzzle: ^7.5
- guzzlehttp/psr7: ^2.6
- illuminate/config: ^11.0|^12.0
- illuminate/console: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
- laravel/pint: ^1.13
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ~9
- rector/rector: ^1.0
- squizlabs/php_codesniffer: ~3.0
- symfony/var-dumper: ^6.3|^7.0
- vlucas/phpdotenv: ^5.5
Suggests
- illuminate/support: Laravel integration: VicidialServiceProvider, Vicidial facade, config/vicidial.php and the vicidial:ping command (^11|^12)
Provides
None
Conflicts
None
Replaces
None
README
Beautiful and simple Implementation to integrate Vicidial API
DISCLAIMER: VICIdial is a registered trademark of the Vicidial Group which i am not related in anyway.
VICIDIAL is a software suite that is designed to interact with the Asterisk Open-Source PBX Phone system to act as a complete inbound/outbound contact center suite with inbound email support as well.
http://www.vicidial.org/vicidial.php
Vicidial has an AGENT API and NON AGENT API, this classes are intended to make it easier to use in PHP. The wrapper covers all 31 Agent API functions and all 61 Non-Agent API functions documented by VICIdial (guarded by tests), see How the VICIdial API works.
Click-to-dial in 10 lines
composer require masterfermin02/vicidial-api-wrapper
use VicidialApi\Parameters\DialParameters; use VicidialApi\Parameters\DispoParameters; use VicidialApi\VicidialClient; use VicidialApi\VicidialConfig; $client = VicidialClient::make(VicidialConfig::create(host: 'vicidial.example.com', user: 'api_user', pass: 'api_pass', protocol: 'https')); $dial = $client->agent()->dialResponse('1000', new DialParameters(phoneNumber: '7275551212', phoneCode: 1)); if ($dial->failed()) { throw new RuntimeException($dial->message()); // "agent_user is not logged in - 1000", "auth USER DOES NOT HAVE PERMISSION ..." } // ... when the conversation is over: $client->agent()->hangupResponse('1000'); $client->agent()->dispoResponse('1000', new DispoParameters(status: 'SALE'));
1000 is the agent logged in to the VICIdial agent screen; api_user is a VICIdial user with
user_level 7+ and API access. Not sure the server, credentials or permissions are right? Run the
connectivity check first. Full walkthrough in
How the VICIdial API works; Laravel users get a service provider,
a Vicidial facade and php artisan vicidial:ping, see Laravel integration.
Support this project
This library is free and open source. I maintain it independently and am working toward making open-source maintenance my full-time work.
If your company uses this library, you can support ongoing maintenance, sponsor a feature, or hire me for integration support. Sponsored improvements remain open source.
Discuss sponsorship or support
Install
Requires PHP 8.2
composer require masterfermin02/vicidial-api-wrapper
For PHP 7.4+ must install this version
composer require masterfermin02/vicidial-api-wrapper:1.0.3
What's New in v4.x 🎉
Version 4.0 introduced major improvements for a better developer experience:
Configuration System
VicidialConfig: A clean configuration object with named parametersVicidialClient: The new recommended client entrypoint- Full configuration control: Set protocol (HTTP/HTTPS), timeout, TLS verification, custom user agent, and more
- Better validation: Built-in validation for configuration values
- Backward compatible: Legacy factory methods still work (but are deprecated)
Response DTOs
- Structured responses: No more regex or manual string parsing
- Helper methods:
ok(),failed(),asArray(),asText(),toJson() - Type-safe: Full IDE autocomplete and type checking
- Auto-parsing: Handles JSON, key-value, pipe-delimited, and other formats automatically
- Request tracking: Optional request ID for debugging
- Opt-in: Original methods still work, upgrade at your own pace
See the Response DTO Guide for details.
Consistent Method Naming
- camelCase everywhere: All methods use standard PHP camelCase convention
- Predictable patterns:
addLead(),updateFields(),mohList(),pauseCode() - No snake_case: Legacy Vicidial API's
external_dialbecomesdial(),pause_codebecomespauseCode()
See the Method Naming Conventions for the complete guide.
Reliability Features 🛡️ NEW
- Configurable timeouts: Separate connect timeout and request timeout
- Automatic retries: Exponential backoff with jitter for transient failures (5xx, network errors, rate limits)
- PSR-3 logging: Pluggable logger for observability and debugging
- Sensitive data protection: Automatic redaction of passwords and API keys in logs
- Production-ready defaults: Sensible timeout and retry configurations out of the box
See the Reliability Features Guide for complete documentation.
// New way (v4.0+) $config = VicidialConfig::create( host: 'vicidial.example.com', user: 'api_user', pass: 'api_password', protocol: 'https', timeout: 60 ); $client = VicidialClient::make($config);
4.2.0 (2026-10-12)
- Every Agent function has a
...Response()variant; typed parameter objects (DialParameters,AddLeadParameters, ...) VicidialResponse::fields(),rows(),statusCode(); empty / HTML / HTTP-error bodies are errors, not success- 5xx and non-throwing PSR-18 clients are retried; idempotency guidance for
add_lead - Laravel service provider,
Vicidialfacade,config/vicidial.php,php artisan vicidial:ping; framework-freeDiagnostics\Ping - Every example response from the official docs is a parsing test; weekly API-parity workflow
4.1.0 (2026-10-12)
- Full parity with the official Agent API (31 functions) and Non-Agent API (61 functions), guarded by tests
- Fixed:
TransportExceptionautoload crash on network errors,switchLead()sending the wrong parameter, double URL-encoding in Agent methods, non-staticcreateWithBasicAuth() - New docs: How the VICIdial API works and Roadmap
See the CHANGELOG and the Migration Guide for details.
Authentication
This wrapper supports two authentication modes and provides both a modern configuration-based approach and legacy factory methods.
Recommended: Using VicidialConfig (v4.0+)
The recommended way to create a client is using the VicidialConfig object, which provides a clean, explicit way to configure all client options:
Standard Authentication
use VicidialApi\VicidialConfig; use VicidialApi\VicidialClient; $config = VicidialConfig::create( host: getenv('YOUR_VICIDIAL_IP'), user: getenv('YOUR_VICIDIAL_USER'), pass: getenv('YOUR_VICIDIAL_PASSWORD'), protocol: 'https', // Optional: 'http' or 'https' (default: 'http') verifyTls: true, // Optional: Verify TLS certificates (default: true) timeout: 30, // Optional: Request timeout in seconds (default: 30) urlEncodeDefault: false, // Deprecated no-op: values are always URL-encoded once by the transport userAgent: 'MyApp/1.0', // Optional: Custom user agent source: 'myapp' // Optional: Source identifier shown in VICIdial logs, max 20 chars (default: 'vicidial-api-wrapper') ); $client = VicidialClient::make($config); // or $client = VicidialApi::client($config);
Basic Authentication (Remote Agent)
use VicidialApi\VicidialConfig; use VicidialApi\VicidialClient; $config = VicidialConfig::createWithBasicAuth( host: getenv('YOUR_VICIDIAL_IP'), user: getenv('YOUR_VICIDIAL_USER'), pass: getenv('YOUR_VICIDIAL_PASSWORD'), basicAuthUser: getenv('YOUR_VICIDIAL_API_USER'), // HTTP Basic Auth user basicAuthPass: getenv('YOUR_VICIDIAL_API_PASSWORD'), // HTTP Basic Auth password protocol: 'https', timeout: 60 ); $client = VicidialClient::make($config);
Response DTOs (New in v4.0)
All API methods now have Response DTO variants that return structured response objects instead of raw strings:
// New Response DTO methods (add "Response" suffix to any method) $response = $client->agent()->updateFieldsResponse("gabriel", [ 'first_name' => 'John', 'last_name' => 'Doe' ]); // Built-in success checking - no regex needed! if ($response->ok()) { echo "Success!"; // Direct data access $leadId = $response->get('lead_id'); // Multiple output formats $array = $response->asArray(); $json = $response->toJson(); $text = $response->asText(); } // Original methods still work for backward compatibility $rawString = $client->agent()->updateFields("gabriel", $fields);
See the Response DTO Guide for complete documentation.
Legacy: Factory Methods (Deprecated)
The original factory methods are still supported for backward compatibility but are deprecated in favor of the configuration object.
Standard Authentication (API User/Pass)
Use VicidialApi::create() for standard API authentication with user credentials. This is the most common method for Agent and Admin API operations.
$api = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') );
Basic Authentication (Remote Agent)
Use VicidialApi::createWithBasicAuth() for remote agent operations that require HTTP Basic Authentication along with agent credentials.
$api = VicidialApi::createWithBasicAuth( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_API_USER'), // HTTP Basic Auth user getenv('YOUR_VICIDIAL_API_PASSWORD'), // HTTP Basic Auth password getenv('YOUR_VICIDIAL_REMOTE_AGENT'), // Agent username getenv('YOUR_VICIDIAL_REMOTE_PASSWORD') // Agent password );
How to use it
💡 Tip: See example/using_config.php for a comprehensive demonstration of all configuration options.
📖 Migrating from v1.x? Check out the Migration Guide for step-by-step instructions.
Recommended Examples (Using VicidialConfig)
Example: Complete workflow with configuration object
<?php require_once 'vendor/autoload.php'; use VicidialApi\VicidialConfig; use VicidialApi\VicidialClient; // Create configuration $config = VicidialConfig::create( host: getenv('YOUR_VICIDIAL_IP'), user: getenv('YOUR_VICIDIAL_USER'), pass: getenv('YOUR_VICIDIAL_PASSWORD'), protocol: 'https', timeout: 30 ); // Create client $client = VicidialClient::make($config); try { // Update fields on agent screen $fields = [ 'first_name' => 'John', 'last_name' => 'Doe', 'address1' => '123 Fake St' ]; echo $client->agent()->updateFields("gabriel", $fields); // Make an external dial echo $client->agent()->dial("gabriel", [ 'phone_number' => '1234567890', 'phone_code' => '1' ]); // Use admin API echo $client->admin()->mohList([ 'format' => 'selectframe' ]); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example: Production setup with reliability features
<?php require_once 'vendor/autoload.php'; use Monolog\Logger; use Monolog\Handler\StreamHandler; use VicidialApi\VicidialConfig; use VicidialApi\VicidialClient; use VicidialApi\ValueObjects\RetryConfig; // Setup logging $logger = new Logger('vicidial-api'); $logger->pushHandler(new StreamHandler('logs/vicidial.log', Logger::DEBUG)); // Production configuration with all reliability features $config = VicidialConfig::create( host: getenv('YOUR_VICIDIAL_IP'), user: getenv('YOUR_VICIDIAL_USER'), pass: getenv('YOUR_VICIDIAL_PASSWORD'), protocol: 'https', timeout: 60, // Request timeout connectTimeout: 10, // Connection timeout retryConfig: RetryConfig::default(), // Enable automatic retries logger: $logger, // Enable request logging ); $client = VicidialClient::make($config); try { // All requests are automatically: // - Logged with sanitized parameters // - Retried on transient failures (5xx, 429, network errors) // (VICIdial has no idempotency keys: keep network-error retries off for clients that add leads) // - Timed out if they take too long $response = $client->agent()->updateFieldsResponse("gabriel", [ 'first_name' => 'John', 'phone_number' => '5551234567' ]); if ($response->ok()) { echo "✓ Success! Lead ID: " . $response->get('lead_id'); } } catch (Exception $e) { // Error is already logged, handle appropriately echo 'Failed after retries: ', $e->getMessage(), "\n"; }
See example/reliability_features.php for more examples.
#### Example: Remote agent with Basic Authentication
```php
<?php
require_once 'vendor/autoload.php';
use VicidialApi\VicidialConfig;
use VicidialApi\VicidialClient;
$config = VicidialConfig::createWithBasicAuth(
host: getenv('YOUR_VICIDIAL_IP'),
user: getenv('YOUR_VICIDIAL_USER'),
pass: getenv('YOUR_VICIDIAL_PASSWORD'),
basicAuthUser: getenv('YOUR_VICIDIAL_API_USER'),
basicAuthPass: getenv('YOUR_VICIDIAL_API_PASSWORD')
);
$client = VicidialClient::make($config);
try {
$remoteAgent = $client->remoteAgent();
$remoteAgent->active(
getenv('agentId'),
getenv('confExten')
);
$remoteAgent->hangUp("gabriel", [
'status' => 'SALE'
]);
$remoteAgent->inActive(
getenv('agentId'),
getenv('confExten')
);
} catch (Exception $e) {
echo 'Exception: ', $e->getMessage(), "\n";
}
Legacy Examples (Deprecated)
Note: The following examples use the legacy factory methods. While still supported, we recommend using
VicidialConfigandVicidialClientas shown above.
Example 1: Update fields on agent screen
<?php $fields['first_name'] = "John"; $fields['last_name'] = "Doe"; $fields['address1'] = "123 Fake St"; try { $agentApi = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') )->agent(); echo $agentApi->updateFields("gabriel", $fields); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example 2: Hangup Call, Dispo it and Pause Agent
<?php try { $agentApi = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') )->agent(); $agentApi->pause("gabriel", "PAUSE"); $agentApi->hangup("gabriel"); $agentApi->dispo("gabriel", ['value' => 'SALE']); $agentApi->pauseCode("gabriel", "BREAK"); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example 3: Make an external dial call
<?php try { $agentApi = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') )->agent(); echo $agentApi->dial("gabriel", [ 'phone_number' => '1234567890', 'phone_code' => '1', 'search' => 'YES', 'preview' => 'NO', 'focus' => 'YES' ]); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example 4: Using the Admin API (Non-Agent API)
<?php require_once 'vendor/autoload.php'; try { $agentApi = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') )->admin(); echo $agentApi->mohList([ 'format' => 'selectframe', 'comments' => 'fieldname', 'stage' => 'date' ]); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example 5: Special characters are encoded for you
Every query value is URL-encoded exactly once by the transport, so pass raw values. Do not call urlencode() yourself (that produced double-encoded values such as %2B turning into %252B in older versions).
<?php require_once 'vendor/autoload.php'; $fields['first_name'] = "John"; $fields['last_name'] = "Doe"; $fields['address1'] = "123 Fake St & Main"; $fields['phone_number'] = "+18002474747"; try { $adminApi = VicidialApi::create( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_USER'), getenv('YOUR_VICIDIAL_PASSWORD') )->admin(); echo $adminApi->addLead($fields); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Example 6: Remote agent login with Basic Authentication
<?php require_once 'vendor/autoload.php'; try { $remoteAgent = VicidialApi::createWithBasicAuth( getenv('YOUR_VICIDIAL_IP'), getenv('YOUR_VICIDIAL_API_USER'), getenv('YOUR_VICIDIAL_API_PASSWORD'), getenv('YOUR_VICIDIAL_REMOTE_AGENT'), getenv('YOUR_VICIDIAL_REMOTE_PASSWORD'), )->remoteAgent(); $remoteAgent->active( getenv('agentId'), getenv('confExten') ); $remoteAgent->hangup("gabriel", [ 'status' => 'SALE' ]); $remoteAgent->inactive( getenv('agentId'), getenv('confExten') ); } catch (Exception $e) { echo 'Exception: ', $e->getMessage(), "\n"; }
Docs:
- How the VICIdial API works 📘 start here: endpoints, auth, permissions, response formats, limits
- Audit and roadmap
- Agent
- Admin
- Response DTO Guide
- Method Naming Conventions
- Error Handling Guide 🎯 NEW
- Reliability Features 🛡️ NEW