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

ActiveLibrary[API Development](/categories/api)

vmeretail/servicedeskify-php-sdk
================================

A Laravel package for interacting with the Vme Retail ServiceDeskify API.

v3.0.0(2w ago)025.9k↑5273.3%MITPHPPHP ^8.2CI passing

Since Nov 7Pushed 2w ago4 watchersCompare

[ Source](https://github.com/vmeretail/servicedeskify-php-sdk)[ Packagist](https://packagist.org/packages/vmeretail/servicedeskify-php-sdk)[ RSS](/packages/vmeretail-servicedeskify-php-sdk/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (10)Versions (21)Used By (0)

ServiceDeskify Laravel SDK
==========================

[](#servicedeskify-laravel-sdk)

A Laravel package for ServiceDeskify, built on [Saloon](https://docs.saloon.dev/).

The package handles OAuth password-grant authentication, encrypted token caching, token refresh and one automatic re-authentication after an API `401`.

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

[](#requirements)

- PHP 8.2 or newer
- Laravel 11, 12 or 13

Laravel 11 is supported for applications that still require it, although its upstream security-fix window ended in March 2026. Prefer Laravel 12 or 13 for new applications.

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

[](#installation)

```
composer require vmeretail/servicedeskify-php-sdk
```

The package service provider is discovered automatically. Publish the configuration file if you need to customise caching or token timing:

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

Configure the credentials supplied by VME Retail:

```
SERVICEDESKIFY_URL=https://helpdesk.vme.co
SERVICEDESKIFY_USERNAME=
SERVICEDESKIFY_PASSWORD=
SERVICEDESKIFY_CLIENT_ID=
SERVICEDESKIFY_CLIENT_SECRET=
```

For the ServiceDeskify test environment, set `SERVICEDESKIFY_URL=https://helpdesk-test.vme.co`.

The configured Laravel cache store is used by default. A different store may be selected with `SERVICEDESKIFY_CACHE_STORE`. Advanced token-cache settings are also configurable. The selected store must support Laravel atomic locks.

```
SERVICEDESKIFY_CACHE_STORE=
SERVICEDESKIFY_CACHE_KEY=servicedeskify.oauth-token
SERVICEDESKIFY_CACHE_TTL=2592000
SERVICEDESKIFY_TOKEN_EXPIRY_LEEWAY=60
SERVICEDESKIFY_TOKEN_LOCK_SECONDS=10
SERVICEDESKIFY_TOKEN_LOCK_WAIT_SECONDS=5
```

Incidents
---------

[](#incidents)

Import the package facade and typed input objects:

```
use VmeRetail\ServiceDeskify\Data\CreateIncidentData;
use VmeRetail\ServiceDeskify\Enums\IncidentPriority;
use VmeRetail\ServiceDeskify\Facades\ServiceDeskify;

$incident = ServiceDeskify::incidents()->create(new CreateIncidentData(
    title: 'Till 2 is not rebooting',
    details: 'Till 2 remains offline after a restart.',
    storeNumber: 722,
    priority: IncidentPriority::P1,
));
```

Incidents can be listed, retrieved, closed and given closure details:

```
use VmeRetail\ServiceDeskify\Data\IncidentClosureData;
use VmeRetail\ServiceDeskify\Data\IncidentQueryData;
use VmeRetail\ServiceDeskify\Enums\IncidentStatus;

$openIncidents = ServiceDeskify::incidents()->all(new IncidentQueryData(
    status: IncidentStatus::Open,
));

$incident = ServiceDeskify::incidents()->find(123);

ServiceDeskify::incidents()->addClosureDetails(123, new IncidentClosureData(
    symptom: 'Till could not connect',
    symptomSolution: 'Restarted the service',
    cause: 'The service had stopped',
    permanentResolution: 'Monitoring has been added',
));

ServiceDeskify::incidents()->close(123);
```

Paginated methods return `PaginatedData` with typed `items` and the usual page, total, link and range values. A page can also be iterated directly or passed to `count()`.

To process every result without hand-rolling page loops, incidents, posts and locations expose `lazy()` and `each()`. Returning `false` from an `each()`callback stops iteration early.

```
foreach (ServiceDeskify::incidents()->lazy() as $incident) {
    // Process one incident at a time.
}
```

Replies and attachments
-----------------------

[](#replies-and-attachments)

```
use Illuminate\Http\UploadedFile;
use VmeRetail\ServiceDeskify\Data\CreateIncidentPostData;

$reply = ServiceDeskify::incidents()->posts(123)->create(
    new CreateIncidentPostData(
        details: 'The requested log is attached.',
        attachments: [
            new UploadedFile('/tmp/till.log', 'till.log'),
        ],
    ),
);
```

Attachments may be Laravel `UploadedFile` instances, `SplFileInfo` instances or readable filesystem paths. Requests without attachments are JSON; requests with attachments are multipart.

Download an attachment using its incident, post and attachment IDs:

```
$download = ServiceDeskify::incidents()
    ->posts(123)
    ->download(postId: 456, attachmentId: 789);

$download->saveTo(storage_path('app/'.$download->fileName));
```

Locations, software assets and releases
---------------------------------------

[](#locations-software-assets-and-releases)

```
use Carbon\CarbonImmutable;
use VmeRetail\ServiceDeskify\Data\CreateSoftwareAssetReleaseData;
use VmeRetail\ServiceDeskify\Data\LocationQueryData;
use VmeRetail\ServiceDeskify\Data\ReleaseQueryData;

$locations = ServiceDeskify::locations()->all(new LocationQueryData(
    store: '722',
    customer: 'Customer Name',
));

$assets = ServiceDeskify::softwareAssets()->all();
$asset = ServiceDeskify::softwareAssets()->find(10);

$created = ServiceDeskify::softwareAssets()->createRelease(
    10,
    new CreateSoftwareAssetReleaseData(
        version: '4.2.0',
        date: CarbonImmutable::parse('2026-07-28'),
    ),
);

$releases = ServiceDeskify::releases()->all(new ReleaseQueryData(
    fromDate: CarbonImmutable::parse('2026-07-01'),
));

ServiceDeskify::releases()->updateUrl(
    releaseId: 20,
    url: 'https://example.test/releases/4.2.0',
);
```

Software-asset lists return summary DTOs containing the ID, name and current release ID. `find()` returns the full software-asset DTO. Creating a release requires an agent account, and posting a version that already exists for that software asset results in a `ValidationException`.

Errors
------

[](#errors)

Failed responses are mapped to package exceptions:

- `AuthenticationException` for `401` and `403`
- `NotFoundException` for `404`
- `ValidationException` for `422`
- `UnexpectedResponseException` when a successful response is missing required identity fields
- `ServiceDeskifyRequestException` for other API and transport failures

Exceptions expose the HTTP status, response body and validation errors where available. All exceptions above extend `ServiceDeskifyRequestException`. Credentials are never included in exception messages.

Testing consuming applications
------------------------------

[](#testing-consuming-applications)

The package uses Saloon core and does not require Saloon's Laravel plugin. Use Saloon's global `MockClient` and provide an OAuth response before API responses:

```
use Saloon\Http\Faking\MockClient;
use Saloon\Http\Faking\MockResponse;
use VmeRetail\ServiceDeskify\Facades\ServiceDeskify;

$mock = MockClient::global([
    MockResponse::make([
        'access_token' => 'test-token',
        'refresh_token' => 'test-refresh-token',
        'token_type' => 'Bearer',
        'expires_in' => 3600,
    ]),
    MockResponse::make([
        'data' => [
            'id' => 123,
            'title' => 'Test incident',
            'summary' => 'Test details',
            'attachments' => [],
        ],
    ]),
]);

$incident = ServiceDeskify::incidents()->find(123);

$mock->assertSentCount(2);
MockClient::destroyGlobal();
```

Destroy the global mock in each test's teardown to prevent it leaking into other tests.

Migrating from v2
-----------------

[](#migrating-from-v2)

Version 3 is a complete rewrite. The following v2 classes have been removed:

- `PublicClient` and `AuthenticatedClientSingleton`
- `AbstractApiResource`
- `Incidents`, `IncidentPosts`, `IncidentClose` and `IncidentClosureDetails`
- `Locations`, `UserLocations` and `SoftwareAssets`
- `ServiceDeskifyResponseObject` and `ServiceDeskifyConstants`

Applications no longer authenticate manually or construct resource classes. Configure credentials in Laravel, use the `ServiceDeskify` facade, pass typed input objects and consume typed result objects.

The obsolete `users/locations` resource is not included because the current ServiceDeskify service does not expose that route.

###  Health Score

59

—

FairBetter than 98% of packages

Maintenance96

Actively maintained with recent releases

Popularity28

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity80

Battle-tested with a long release history

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~204 days

Recently: every ~413 days

Total

13

Last Release

19d ago

Major Versions

v1.1.2 → v2.0.02024-01-02

v2.1.0 → v3.0.02026-07-29

PHP version history (3 changes)v1.0.1PHP &gt;=5.6.4

v1.1PHP ~7.0|~8.0

v3.0.0PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/557390?v=4)[Pablo Maria Martelletti](/maintainers/pmartelletti)[@pmartelletti](https://github.com/pmartelletti)

---

Top Contributors

[![AndreVME](https://avatars.githubusercontent.com/u/28352370?v=4)](https://github.com/AndreVME "AndreVME (12 commits)")[![guillermovme](https://avatars.githubusercontent.com/u/39256057?v=4)](https://github.com/guillermovme "guillermovme (8 commits)")[![erikacamilleri](https://avatars.githubusercontent.com/u/14978900?v=4)](https://github.com/erikacamilleri "erikacamilleri (5 commits)")[![jsandfordhughes](https://avatars.githubusercontent.com/u/35659248?v=4)](https://github.com/jsandfordhughes "jsandfordhughes (1 commits)")[![pmartelletti](https://avatars.githubusercontent.com/u/557390?v=4)](https://github.com/pmartelletti "pmartelletti (1 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

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

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

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k113.1M997](/packages/laravel-socialite)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5226.7k](/packages/simplestats-io-laravel-client)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

818355.4k3](/packages/defstudio-telegraph)[spatie/laravel-export

Create a static site bundle from a Laravel app

679153.2k7](/packages/spatie-laravel-export)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1239.7k25](/packages/fleetbase-core-api)

PHPackages © 2026

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