PHPackages                             itsjustvita/laravel-znuny - 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. [HTTP &amp; Networking](/categories/http)
4. /
5. itsjustvita/laravel-znuny

ActiveLibrary[HTTP &amp; Networking](/categories/http)

itsjustvita/laravel-znuny
=========================

Modern Laravel SDK for the Znuny / OTRS Community Edition Generic Interface REST API

v0.1.2(3mo ago)224MITPHPPHP ^8.3

Since Apr 10Pushed 3mo agoCompare

[ Source](https://github.com/itsjustvita/laravel-znuny)[ Packagist](https://packagist.org/packages/itsjustvita/laravel-znuny)[ RSS](/packages/itsjustvita-laravel-znuny/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (9)Versions (5)Used By (0)

laravel-znuny
=============

[](#laravel-znuny)

[![Latest Version on Packagist](https://camo.githubusercontent.com/b97e69f3c9a622e1d0b3bad785810db37360d5b2dc013c653abec4842cea30be/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6974736a757374766974612f6c61726176656c2d7a6e756e792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/itsjustvita/laravel-znuny)[![Total Downloads](https://camo.githubusercontent.com/f6af21ada2cefd0549034543c56e0ac2051f667ffa0c6fd5586457417dad3c43/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6974736a757374766974612f6c61726176656c2d7a6e756e792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/itsjustvita/laravel-znuny)[![PHP Version](https://camo.githubusercontent.com/dee420adfa5b4e112382679aa8f16023ca2ce91e8722d97e98812b1e1a4ece45/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6974736a757374766974612f6c61726176656c2d7a6e756e792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/itsjustvita/laravel-znuny)[![License](https://camo.githubusercontent.com/6973873fbe1282dfca237ccde6d1525cd32ab86913e14bf29dcddc8947bcd0b8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6974736a757374766974612f6c61726176656c2d7a6e756e792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/itsjustvita/laravel-znuny)

> Modern Laravel SDK for the Znuny / OTRS Community Edition Generic Interface REST API.

Replaces hand-rolled `OTRSService` implementations with a typed, fluent, Laravel-native package: facade-centric API, multi-connection support, cache-backed sessions with auto-retry, typed DTOs, fluent ticket search with pagination, per-resource caching for lookup data, and hybrid dynamic fields.

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

[](#requirements)

- PHP 8.3+
- Laravel 12 or 13
- A reachable Znuny instance with a configured `GenericInterface` webservice exposing `TicketCreate`, `TicketGet`, `TicketUpdate`, `TicketSearch`, `SessionCreate`, `QueueList`, `QueueGet`, `StateList`, `PriorityList`, `TypeList`, `CustomerUserGet`

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

[](#installation)

```
composer require itsjustvita/laravel-znuny
php artisan vendor:publish --tag=znuny-config
```

Add the required environment variables:

```
ZNUNY_BASE_URL=https://agent.ticket.example.com/otrs/nph-genericinterface.pl/Webservice/td-webservice
ZNUNY_USERNAME=apiuser
ZNUNY_PASSWORD=apipass
ZNUNY_VERIFY_SSL=true

```

Usage
-----

[](#usage)

### Tickets

[](#tickets)

```
use Znuny;

// Find
$ticket = Znuny::tickets()->find('12345');
$ticket = Znuny::tickets()->find('12345', withArticles: true, withDynamicFields: true);

// Create
$ticket = Znuny::tickets()->create([
    'title'        => 'Connection issue',
    'queue'        => 'Support',
    'state'        => 'new',
    'priority'     => '3 normal',
    'customerUser' => 'customer@example.com',
    'customerId'   => '12345',
])
->withArticle([
    'subject'     => 'Initial message',
    'body'        => 'Customer reports...',
    'contentType' => 'text/plain; charset=utf8',
])
->withDynamicFields([
    'OrderId'  => 'ORD-2026-001',
    'Severity' => 'high',
])
->save();

// Update
Znuny::tickets()->update('12345', ['state' => 'open']);

// Add an article
Znuny::tickets()->addArticle('12345', [
    'subject'              => 'Internal note',
    'body'                 => 'Customer called back',
    'communicationChannel' => 'Internal',
    'senderType'           => 'agent',
]);

// Close
Znuny::tickets()->close('12345');
```

### Search (fluent builder)

[](#search-fluent-builder)

```
$tickets = Znuny::tickets()
    ->where('CustomerID', '12345')
    ->whereState('open')
    ->whereQueue('Support')
    ->whereCreatedAfter(now()->subDays(30))
    ->orderByDesc('Created')
    ->limit(50)
    ->get();                              // Collection

$paginator = Znuny::tickets()
    ->where('CustomerID', '12345')
    ->paginate(perPage: 25);              // LengthAwarePaginator

$ids = Znuny::tickets()->where('State', 'open')->ids();          // Collection

foreach (Znuny::tickets()->where('State', 'open')->lazy() as $ticket) {
    // process each ticket, chunked fetch under the hood
}
```

> **Note:** `paginate(perPage: 25)` first fetches *all* matching TicketIDs via `TicketSearch`, then batch-fetches the current page. The ID list is cheap but not free -- if you have 10k+ matching tickets, prefer `lazy()` for background jobs.

### Queues / states / priorities / types

[](#queues--states--priorities--types)

```
$queues = Znuny::queues()->all();                                  // cached 1h
$queue  = Znuny::queues()->find('803');
$queue  = Znuny::queues()->findByName('Support');

// Replaces the old OtrsQueueService:
$queueId = Znuny::queues()->resolve('relocation', businessCustomer: true);

Znuny::states()->all();
Znuny::priorities()->all();
Znuny::types()->all();
```

### Customers

[](#customers)

```
$customer = Znuny::customers()->find('12345');
$tickets  = Znuny::customers()->tickets('12345');
```

### Multi-connection

[](#multi-connection)

Config file:

```
'connections' => [
    'default'  => ['base_url' => env('ZNUNY_BASE_URL'), ...],
    'tenant-a' => ['base_url' => env('TENANT_A_BASE_URL'), ...],
],
```

```
Znuny::connection('tenant-a')->tickets()->find('12345');
```

Runtime credentials (for dynamic tenants):

```
Znuny::usingCredentials(
    baseUrl: 'https://otrs.tenant-x.com/...',
    username: 'apiuser',
    password: 'secret',
)->tickets()->find('12345');
```

### Dynamic fields (three ways)

[](#dynamic-fields-three-ways)

```
// 1. Raw array -- always works, no setup.
Znuny::tickets()->create([...])->withDynamicFields([
    'CustomerSegment' => 'business',
    'OrderId'         => 'ORD-001',
])->save();

// 2. Config-based validation (config/znuny.php)
'dynamic_fields' => [
    'CustomerSegment' => ['type' => 'string', 'allowed' => ['business', 'private']],
    'OrderId'         => ['type' => 'string'],
    'Priority'        => ['type' => 'integer', 'min' => 1, 'max' => 5],
],
// Invalid values throw InvalidDynamicFieldException.

// 3. Generated typed helper
php artisan znuny:generate-fields

use App\Znuny\DynamicFields;

Znuny::tickets()->create([...])->withDynamicFields(
    DynamicFields::make()
        ->customerSegment('business')
        ->orderId('ORD-001')
        ->priority(3)
        ->toArray(),
)->save();
```

### Events

[](#events)

EventFired when`ZnunyRequestSent`before an HTTP call`ZnunyResponseReceived`after a successful response`ZnunyRequestFailed`on any exception`ZnunyTicketCreated`after `TicketCreate` succeeds`ZnunyTicketUpdated`after `TicketUpdate` (ticket data)`ZnunyArticleAdded`after `TicketUpdate` (article only)`ZnunySessionRefreshed`when a cached session was recreated### Logging

[](#logging)

Add a dedicated channel to `config/logging.php`:

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

Then set `ZNUNY_LOG_CHANNEL=znuny` and `ZNUNY_LOGGING_ENABLED=true`.

### Exceptions

[](#exceptions)

```
ZnunyException (abstract)
├── ZnunyConnectionException        // network / timeout / SSL
├── ZnunyAuthenticationException
│   └── ZnunySessionExpiredException // handled by auto-retry
├── ZnunyValidationException
│   ├── InvalidQueueException
│   ├── InvalidStateException
│   ├── InvalidPriorityException
│   └── InvalidDynamicFieldException
├── ZnunyNotFoundException
│   ├── TicketNotFoundException
│   ├── CustomerNotFoundException
│   └── QueueNotFoundException
├── ZnunyRateLimitException
└── ZnunyServerException

```

Every exception carries `operation`, `errorCode`, `connection`, sanitized `requestPayload`, and raw `responseBody`.

### Artisan commands

[](#artisan-commands)

CommandPurpose`znuny:test-connection [conn]`Verify credentials by calling `SessionCreate` + `QueueList``znuny:cache-clear [conn] [--resource=... | --all]`Flush lookup caches`znuny:generate-fields`Generate a typed `DynamicFields` helper from config### Webhooks (experimental)

[](#webhooks-experimental)

Inbound webhooks (Znuny -&gt; Laravel) are a planned feature. The current release ships a disabled-by-default route that returns HTTP 501. Signature verification and payload mapping will arrive in a later release.

Migration from handwritten OTRSService
--------------------------------------

[](#migration-from-handwritten-otrsservice)

See [docs/MIGRATION.md](docs/MIGRATION.md).

License
-------

[](#license)

MIT.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance82

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 50% 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 ~7 days

Total

3

Last Release

92d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/21318499?v=4)[itsjustvita](/maintainers/itsjustvita)[@itsjustvita](https://github.com/itsjustvita)

---

Top Contributors

[![itsjustvita](https://avatars.githubusercontent.com/u/21318499?v=4)](https://github.com/itsjustvita "itsjustvita (1 commits)")[![td-jmohr](https://avatars.githubusercontent.com/u/257970256?v=4)](https://github.com/td-jmohr "td-jmohr (1 commits)")

---

Tags

apilaravelsdkrestOTRShelpdeskticketznuny

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/itsjustvita-laravel-znuny/health.svg)

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

###  Alternatives

[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k9.0M69](/packages/spatie-laravel-responsecache)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k96.5k1](/packages/mike-bronner-laravel-model-caching)[aedart/athenaeum

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

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

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