PHPackages                             drchrono/php-sdk - 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. drchrono/php-sdk

ActiveLibrary[API Development](/categories/api)

drchrono/php-sdk
================

Official PHP SDK for the DrChrono API - Complete EHR/Practice Management integration

v1.8.0(3mo ago)0780↓50%MITPHPPHP ^8.1

Since Nov 23Pushed 1mo agoCompare

[ Source](https://github.com/xfairgamex/DrChrono-PHP)[ Packagist](https://packagist.org/packages/drchrono/php-sdk)[ Docs](https://github.com/drchrono/DrChrono-PHP)[ RSS](/packages/drchrono-php-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (5)Versions (13)Used By (0)

DrChrono PHP SDK
================

[](#drchrono-php-sdk)

[![PHP Version](https://camo.githubusercontent.com/cc9cdea9aa96b40a822425e981b0a030e3371202973c7d57b74e8e99834f81dc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e312d626c7565)](https://www.php.net/)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

PHP SDK for the DrChrono API - EHR/Practice Management integration for PHP applications.

Features
--------

[](#features)

✨ **Complete API Coverage** - All DrChrono API endpoints supported 🔐 **OAuth2 Authentication** - Full OAuth2 flow with automatic token refresh 📄 **Pagination Support** - Automatic pagination with generators for memory efficiency 🎯 **Type-Safe Models** - Optional DTOs for common entities (Patient, Appointment, etc.) 🔔 **Webhook Handling** - Built-in webhook verification and event parsing ⚡ **Smart Retry Logic** - Automatic retry with exponential backoff for rate limits 🛡️ **Error Handling** - Granular exceptions for different error types 📦 **Framework Agnostic** - Works with Laravel, Symfony, or plain PHP

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

[](#requirements)

- PHP 8.1 or higher
- Composer
- ext-json

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

[](#installation)

Install via Composer:

```
composer require drchrono/php-sdk
```

Quick Start
-----------

[](#quick-start)

### Basic Authentication

[](#basic-authentication)

```
use DrChrono\DrChronoClient;

// Create client with access token
$client = DrChronoClient::withAccessToken('your_access_token');

// Get current user
$user = $client->getCurrentUser();
echo "Authenticated as: {$user['first_name']} {$user['last_name']}";

// List patients
$patients = $client->patients->list();
foreach ($patients as $patient) {
    echo "{$patient['first_name']} {$patient['last_name']}\n";
}
```

### OAuth2 Flow

[](#oauth2-flow)

```
use DrChrono\DrChronoClient;

// Initialize client with OAuth credentials
$client = DrChronoClient::withOAuth(
    clientId: 'your_client_id',
    clientSecret: 'your_client_secret',
    redirectUri: 'https://yourapp.com/callback'
);

// Step 1: Redirect user to authorization URL
$authUrl = $client->auth()->getAuthorizationUrl(
    scopes: ['patients:read', 'appointments:read', 'appointments:write']
);
header("Location: {$authUrl}");

// Step 2: Exchange code for tokens (in your callback handler)
$tokens = $client->auth()->exchangeAuthorizationCode($_GET['code']);

// Step 3: Use access token
$client->getConfig()->setAccessToken($tokens['access_token']);
$patients = $client->patients->list();
```

### Laravel Integration

[](#laravel-integration)

The package ships with a Laravel service provider and config file for auto-registration. After installing, publish the config if you want to customize defaults:

```
php artisan vendor:publish --tag=drchrono-config
```

Laravel users can opt into the HTTP client integration (supports `Http::fake()` and pools) and Collections from list endpoints:

```
use DrChrono\DrChronoClient;
use Illuminate\Support\Facades\Http;

Http::fake();

$client = app(DrChronoClient::class);
$patients = $client->patients->list();
```

Core Concepts
-------------

[](#core-concepts)

### Resources

[](#resources)

The SDK organizes API endpoints into resource classes:

```
$client->patients        // Patient management
$client->appointments    // Appointment scheduling
$client->clinicalNotes   // Clinical documentation
$client->documents       // Document management
$client->offices         // Office locations
$client->users           // Doctors and staff
$client->tasks           // Task management
$client->prescriptions   // Medication prescriptions
$client->labOrders       // Laboratory orders
$client->labResults      // Lab results
$client->insurances      // Insurance information
$client->allergies       // Patient allergies
$client->medications     // Patient medications
$client->problems        // Problem list
$client->vitals          // Vital signs
$client->immunizations   // Vaccination records
$client->billing         // Billing and transactions
$client->appointmentProfiles    // Appointment types
$client->appointmentTemplates   // Recurring blocks
$client->patientPayments        // Payment records
$client->patientMessages        // Patient communications
$client->inventoryCategories    // Inventory organization
$client->patientVaccineRecords  // Immunization tracking
$client->taskTemplates          // Reusable task templates
$client->taskCategories         // Task organization
$client->taskStatuses           // Custom task statuses
$client->taskNotes              // Task documentation
$client->doctors                // Provider directory
$client->userGroups             // Permission groups
$client->prescriptionMessages   // Pharmacy communications
$client->commLogs               // Communication audit trail
```

### Verbose Mode

[](#verbose-mode)

Some endpoints support verbose mode to include additional related data that requires extra database queries:

```
// Get patient with full insurance details
$patient = $client->patients->getWithInsurance($patientId);
echo "Insurance: {$patient['primary_insurance']['insurance_payer_name']}\n";
echo "Policy #: {$patient['primary_insurance']['insurance_id_number']}\n";

// Get appointment with clinical data (vitals, notes, etc.)
$appointment = $client->appointments->getWithClinicalData($appointmentId);
echo "BP: {$appointment['vitals']['blood_pressure_1']}/{$appointment['vitals']['blood_pressure_2']}\n";

// Get clinical note with full section content
$note = $client->clinicalNotes->getWithSections($noteId);
foreach ($note['clinical_note_sections'] as $section) {
    echo "{$section['section_name']}: {$section['section_content']}\n";
}

// List patients with insurance details
// Note: Page size limited to 50 (vs 250 default)
$patients = $client->patients->listWithInsurance(['doctor' => 123456]);

// Manual verbose mode (low-level)
$appointments = $client->appointments->list(['verbose' => 'true']);
```

**Verbose mode includes:**

- **Patients**: Full insurance objects (primary/secondary/tertiary), custom demographics, patient flags, referring doctor
- **Appointments**: Clinical notes, vitals, custom vitals, status transitions, reminders
- **Clinical Notes**: Complete section content with all fields

**Performance considerations:**

- Page size reduced from 250 to 50 records
- Response time 2-5x slower per request
- Additional database queries per record
- Use only when you need the extra fields

📖 **See [Verbose Mode Guide](docs/VERBOSE_MODE.md) for comprehensive documentation and examples.**

### Pagination

[](#pagination)

All list endpoints return paginated results:

```
// Get first page
$patients = $client->patients->list(['page_size' => 50]);

echo "Page count: {$patients->count()}\n";
echo "Has more: " . ($patients->hasNext() ? 'Yes' : 'No') . "\n";

// Iterate through items
foreach ($patients as $patient) {
    // Process patient
}

// Auto-iterate all pages (memory efficient)
foreach ($client->patients->iterateAll() as $patient) {
    // Processes all patients across all pages
}

// Get all at once (caution: may be memory intensive)
$allPatients = $client->patients->all();
```

### Models

[](#models)

Use type-safe models for better IDE support:

```
use DrChrono\Model\Patient;
use DrChrono\Model\Appointment;

// Create from array
$patient = Patient::fromArray($patientData);

echo $patient->getFullName();
echo $patient->getEmail();
echo $patient->getDateOfBirth();

// Convert to array
$data = $patient->toArray();

// Use models with resources
$appointmentData = (new Appointment())
    ->setDoctor(123)
    ->setPatient(456)
    ->setOffice(1)
    ->setDuration(30)
    ->setScheduledTime('2025-01-15T10:00:00')
    ->toArray();

$created = $client->appointments->create($appointmentData);
```

### Error Handling

[](#error-handling)

The SDK provides granular exception classes:

```
use DrChrono\Exception\AuthenticationException;
use DrChrono\Exception\ValidationException;
use DrChrono\Exception\RateLimitException;
use DrChrono\Exception\ApiException;

try {
    $patient = $client->patients->create($data);
} catch (ValidationException $e) {
    // Handle validation errors
    echo "Validation failed: {$e->getMessage()}\n";
    print_r($e->getValidationErrors());
} catch (RateLimitException $e) {
    // Handle rate limiting
    echo "Rate limited. Retry after: {$e->getRetryAfter()} seconds\n";
} catch (AuthenticationException $e) {
    // Handle authentication errors
    echo "Auth failed: {$e->getMessage()}\n";
} catch (ApiException $e) {
    // Handle other API errors
    echo "API error: {$e->getMessage()}\n";
    echo "Status: {$e->getStatusCode()}\n";
    print_r($e->getErrorDetails());
}
```

Usage Examples
--------------

[](#usage-examples)

### Patient Management

[](#patient-management)

```
// Search patients
$results = $client->patients->search([
    'first_name' => 'John',
    'last_name' => 'Doe',
    'date_of_birth' => '1980-01-01'
]);

// Create patient
$patient = $client->patients->createPatient([
    'first_name' => 'Jane',
    'last_name' => 'Smith',
    'gender' => 'Female',
    'date_of_birth' => '1985-03-15',
    'email' => 'jane@example.com',
    'doctor' => 123456,
]);

// Update patient
$client->patients->updateDemographics($patient['id'], [
    'cell_phone' => '555-1234'
]);

// Get patient summary
$summary = $client->patients->getSummary($patient['id']);

// Get CCDA
$ccda = $client->patients->getCCDA($patient['id']);
```

### Appointment Management

[](#appointment-management)

```
// List appointments by date range
$appointments = $client->appointments->listByDateRange(
    startDate: '2025-01-01',
    endDate: '2025-01-31'
);

// List by patient
$patientAppts = $client->appointments->listByPatient($patientId);

// Create appointment
$appointment = $client->appointments->createAppointment([
    'doctor' => 123456,
    'patient' => 789012,
    'office' => 1,
    'duration' => 30,
    'scheduled_time' => '2025-01-15T10:00:00',
    'status' => 'Scheduled',
    'reason' => 'Annual checkup',
]);

// Update status
$client->appointments->setStatus($appointment['id'], 'Confirmed');

// Mark as arrived
$client->appointments->markArrived($appointment['id']);

// Mark as complete
$client->appointments->markComplete($appointment['id']);

// Cancel appointment
$client->appointments->cancel($appointment['id'], 'Patient requested cancellation');
```

### Clinical Documentation

[](#clinical-documentation)

```
// Create clinical note
$note = $client->clinicalNotes->createNote([
    'patient' => $patientId,
    'appointment' => $appointmentId,
    'doctor' => $doctorId,
    'chief_complaint' => 'Follow-up visit',
]);

// Update note
$client->clinicalNotes->updateNote($note['id'], [
    'assessment' => 'Patient improving',
    'plan' => 'Continue current treatment',
]);

// Lock note (finalize)
$client->clinicalNotes->lock($note['id']);

// Get note templates
$templates = $client->clinicalNotes->getTemplates();
```

### Document Upload

[](#document-upload)

```
// Upload document to patient chart
$document = $client->documents->upload(
    doctorId: 123456,
    patientId: 789012,
    filePath: '/path/to/document.pdf',
    description: 'Lab results',
    date: '2025-01-15',
    metatags: ['Lab Results', 'Bloodwork']
);

// List patient documents
$documents = $client->documents->listByPatient($patientId);

// Update metadata
$client->documents->updateMetadata($document['id'], [
    'description' => 'Updated description'
]);
```

### Laboratory Orders

[](#laboratory-orders)

```
// Create lab order
$order = $client->labOrders->createOrder([
    'patient' => $patientId,
    'doctor' => $doctorId,
    'order_type' => 'Lab',
]);

// List lab orders
$orders = $client->labOrders->listByPatient($patientId);

// Get order document (requisition)
$requisition = $client->labOrders->getOrderDocument($order['id']);
```

### Tasks

[](#tasks)

```
// Create task
$task = $client->tasks->createTask([
    'title' => 'Follow up with patient',
    'patient' => $patientId,
    'assignee' => $userId,
    'due_date' => '2025-01-20',
    'status' => 'Open',
]);

// List tasks by patient
$tasks = $client->tasks->listByPatient($patientId);

// Mark as complete
$client->tasks->markComplete($task['id']);

// Add note to task
$client->tasks->addNote($task['id'], 'Patient contacted successfully');
```

Webhooks
--------

[](#webhooks)

### Webhook Verification

[](#webhook-verification)

```
use DrChrono\Webhook\WebhookVerifier;

$verifier = new WebhookVerifier('your_client_secret');

// Get raw payload
$payload = file_get_contents('php://input');
$headers = getallheaders();

try {
    // Verify and parse webhook
    $event = $verifier->verifyFromRequest($payload, $headers);

    // Handle event
    if ($event->is('appointment.created')) {
        $appointmentId = $event->getAppointmentId();
        // Handle new appointment
    }

    if ($event->isPatientEvent()) {
        $patientId = $event->getPatientId();
        // Handle patient event
    }

    // Return success
    http_response_code(200);

} catch (\DrChrono\Exception\WebhookVerificationException $e) {
    http_response_code(401);
    echo "Invalid signature";
}
```

See [examples/05\_webhook\_handler.php](examples/05_webhook_handler.php) for a complete webhook handler.

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

[](#configuration)

### Advanced Configuration

[](#advanced-configuration)

```
use DrChrono\Client\Config;
use DrChrono\DrChronoClient;

$config = new Config([
    'access_token' => 'your_token',
    'client_id' => 'your_client_id',
    'client_secret' => 'your_client_secret',
    'timeout' => 60,              // Request timeout (seconds)
    'connect_timeout' => 10,      // Connection timeout (seconds)
    'max_retries' => 3,           // Max retry attempts for rate limits
    'retry_delay' => 1000,        // Initial retry delay (milliseconds)
    'debug' => true,              // Enable debug mode
    'api_version' => 'v4',        // Specific API version
]);

$client = new DrChronoClient($config);
```

### Token Management

[](#token-management)

```
// Check if token is expired
if ($client->getConfig()->isTokenExpired()) {
    // Refresh token
    $tokens = $client->auth()->refreshAccessToken();

    // Update config with new token
    $client->getConfig()->setAccessToken($tokens['access_token']);
}

// Auto-refresh (recommended)
$client->auth()->ensureValidToken();
```

Testing
-------

[](#testing)

Run the test suite:

```
# Run all tests
composer test

# Run with coverage
composer test:coverage

# Run PHPStan static analysis
composer phpstan

# Check code style
composer cs:check

# Fix code style
composer cs:fix
```

Examples
--------

[](#examples)

Runnable examples are provided in the `examples/` directory:

- `01_auth_basic.php` - Basic authentication with access token
- `02_auth_oauth_flow.php` - Complete OAuth2 flow
- `03_patients_crud.php` - Patient management (CRUD operations)
- `04_appointments_crud.php` - Appointment scheduling
- `05_webhook_handler.php` - Webhook verification and handling
- `06_clinical_workflow.php` - Complete clinical workflow example
- `07_verbose_mode.php` - Using verbose mode for additional data

API Reference
-------------

[](#api-reference)

### Available Resources

[](#available-resources)

ResourceDescriptionExample`patients`Patient demographics and records`$client->patients->list()``appointments`Appointment scheduling`$client->appointments->listByDateRange()``appointmentProfiles`Appointment types &amp; durations`$client->appointmentProfiles->listByDoctor()``appointmentTemplates`Recurring appointment blocks`$client->appointmentTemplates->createTemplate()``customAppointmentFields`Custom appointment metadata`$client->customAppointmentFields->listByDoctor()``clinicalNotes`Clinical documentation`$client->clinicalNotes->createNote()``documents`Document management`$client->documents->upload()``offices`Office locations`$client->offices->listAll()``users`Doctors and staff`$client->users->getCurrent()``tasks`Task management`$client->tasks->createTask()``prescriptions`Medications`$client->prescriptions->listByPatient()``labOrders`Lab orders`$client->labOrders->createOrder()``labResults`Lab results`$client->labResults->listByPatient()``insurances`Insurance info`$client->insurances->listByPatient()``allergies`Patient allergies`$client->allergies->createAllergy()``medications`Patient medications`$client->medications->listByPatient()``problems`Problem list`$client->problems->createProblem()``vitals`Vital signs`$client->vitals->createVitals()``immunizations`Vaccination records`$client->immunizations->listByPatient()``patientPayments`Patient payment records`$client->patientPayments->listByPatient()``patientMessages`Patient communications`$client->patientMessages->sendMessage()``patientsSummary`Bulk patient summaries`$client->patientsSummary->listByDoctor()``customDemographics`Custom patient fields`$client->customDemographics->createField()``patientFlagTypes`Custom patient flags`$client->patientFlagTypes->createFlagType()``billing`Billing/transactions`$client->billing->listLineItems()``billingProfiles`Billing configurations`$client->billingProfiles->getByDoctor()``eligibilityChecks`Insurance verification`$client->eligibilityChecks->verifyPrimaryInsurance()``feeSchedules`Pricing and fee schedules`$client->feeSchedules->getByCode()``transactions`Payment transactions`$client->transactions->recordPayment()``lineItems`Invoice line items`$client->lineItems->addProcedure()``patientPaymentLog`Payment history/audit`$client->patientPaymentLog->getPaymentHistory()``consentForms`Patient consent forms`$client->consentForms->markAsSigned()``customInsurancePlanNames`Custom insurance naming`$client->customInsurancePlanNames->setCustomName()``clinicalNoteTemplates`Note templates`$client->clinicalNoteTemplates->createTemplate()``clinicalNoteFieldTypes`Custom note fields`$client->clinicalNoteFieldTypes->createFieldType()``clinicalNoteFieldValues`Note field values`$client->clinicalNoteFieldValues->upsertValue()``procedures`Medical procedures`$client->procedures->createProcedure()``amendments`Record amendments`$client->amendments->approve()``carePlans`Patient care plans`$client->carePlans->createCarePlan()``patientRiskAssessments`Risk evaluations`$client->patientRiskAssessments->createAssessment()``patientPhysicalExams`Physical exam records`$client->patientPhysicalExams->createExam()``patientInterventions`Treatment interventions`$client->patientInterventions->createIntervention()``patientCommunications`Patient communications`$client->patientCommunications->createCommunication()``implantableDevices`Implanted devices`$client->implantableDevices->createDevice()`Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

License
-------

[](#license)

This SDK is open-sourced software licensed under the [MIT license](LICENSE).

Support
-------

[](#support)

- **Documentation**: [DrChrono API Docs](https://app.drchrono.com/api-docs/)
- **Issues**: [GitHub Issues](https://github.com/drchrono/DrChrono-PHP/issues)
- **Email**:

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for version history and updates.

---

Made with ❤️ for the healthcare community

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance86

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60.6% 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

Every ~77 days

Total

2

Last Release

99d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8ef0357dc22917dd039523562175a81d680b6e7b6e376e0c3c67cfb88ad0b133?d=identicon)[joemasterson](/maintainers/joemasterson)

---

Top Contributors

[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (40 commits)")[![xfairgamex](https://avatars.githubusercontent.com/u/334259?v=4)](https://github.com/xfairgamex "xfairgamex (26 commits)")

---

Tags

apioauth2ehrhealthcaremedicaldrchronopractice-management

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/drchrono-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/drchrono-php-sdk/health.svg)](https://phpackages.com/packages/drchrono-php-sdk)
```

###  Alternatives

[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k7.6M74](/packages/openai-php-laravel)[get-stream/stream-chat

A PHP client for Stream Chat (https://getstream.io/chat/)

301.8M2](/packages/get-stream-stream-chat)

PHPackages © 2026

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