PHP code example of zammad / zammad-api-client-php

1. Go to this page and download the library: Download zammad/zammad-api-client-php library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

zammad / zammad-api-client-php example snippets




use ZammadAPIClient\Core\Auth;
use ZammadAPIClient\ZammadClient;

$client = ZammadClient::create('https://zammad.example', Auth::token('your-token'));

use ZammadAPIClient\Endpoints\Tickets\TicketDTO;

// Fetch
$ticket = $client->ticket()->find(1);
echo $ticket->title; // typed property, IDE autocomplete

// Create (customer_id is ew TicketDTO(
    title: 'Hello from v3',
    customer_id: 1,
    group_id: 1,
    priority_id: 2,
    state_id: 1,
    article: [
        'subject' => 'Hello',
        'body'    => 'Message body',
        'type'    => 'note',
    ],
));

// Partial update
$client->ticket()->patch($created->id, ['title' => 'Updated']);

// Search
foreach ($client->ticket()->search('error') as $ticket) {
    echo $ticket->title;
}

use ZammadAPIClient\Core\Auth;
use ZammadAPIClient\ZammadClient;

// The URL is normalized — /api/v1 is appended automatically
$client = ZammadClient::create('https://zammad.example', Auth::token('your-token'));

// Access via typed accessor — autocomplete, type-safe
$ticket = $client->ticket()->find(1);
$user   = $client->user()->find(1);
$group  = $client->group()->find(1);

$ticket = $client->ticket()->find(1);

echo $ticket->title;          // Typed property, IDE autocomplete
echo $ticket->state_id;       // ?int
echo $ticket->created_at;     // ?DateTimeImmutable

$data = $ticket->toArray();   // All values as array
$id   = $ticket->id;          // Server-assigned ID (null before create)

$ticket = $client->ticket()->create(new TicketDTO(
    title: 'My ticket',
    customer_id: 1,
    group_id: 1,
    priority_id: 2,
    state_id: 1,
    article: [
        'subject' => 'My ticket',
        'body'    => 'First message',
        'type'    => 'note',
    ],
));

echo $ticket->id; // Server-assigned after creation

$repo = $client->ticket();

// Send a DTO — only non-null fields are transmitted
$repo->patch(1, new TicketDTO(title: 'New title', group_id: 1));

// Partial update via array — only supplied fields change
$repo->patch(1, ['title' => 'New title', 'state_id' => 3]);

// Partial update via TicketUpdateDTO — only non-null fields sent
$repo->patch(1, new TicketUpdateDTO(title: 'New title'));

$repo = $client->ticket();

$r = $repo->resource(1);          // Returns Resource, fetches ticket #1
echo $r->title;                   // Reads current title
$r->title = 'Changed';            // Tracks old → new
$r->state_id = 3;                 // Tracks old → new
$r->save();                       // PUT {title, state_id} only
$r->destroy();                    // DELETE

$repo = $client->ticket();

// Array — simplest for ad-hoc changes
$repo->patch(1, ['title' => 'New title', 'state_id' => 3]);

// TicketUpdateDTO — type-safe, IDE-friendly
$repo->patch(1, new TicketUpdateDTO(title: 'New title'));

// Full DTO — send a modified TicketDTO
$ticket = $repo->find(1);
$repo->patch(1, new TicketDTO(
    title: $ticket->title,
    group_id: 2, // changed from original
));

// Stateful resource — tracks property changes
$r = $repo->resource(1);
$r->title = 'Changed';
$r->state_id = 3;
$r->save(); // Sends only {title, state_id}

$client->ticket()->delete(1);
$client->user()->delete(1);

$repo = $client->ticket();

// Full-text search — returns a lazy Generator (page by page)
// Use foreach directly; count()/array access r AND priority_id:1') as $ticket) {
    echo $ticket->number;
}

// PaginatedList — count(), totalCount(), page navigation
$list = $repo->searchList('error', ['per_page' => 25]);
echo $list->totalCount();
$list->page(2);
$list->each(function ($t) { echo $t->title; });

$repo = $client->ticket();

// Lazy Generator — pages fetched on demand, memory-efficient
// Use in foreach; need count? Use list() for PaginatedList instead.
foreach ($repo->all() as $ticket) {
    echo $ticket->title;
}

// PaginatedList — count(), page navigation, each() callback
$list = $repo->list();
echo $list->count();                    // Items on current page
$list->page(2);                         // Jump to page 2
$list->pageNext();                      // Next page
$list->each(function ($t) { echo $t->title; });

$repo = $client->ticketArticle();

// All articles for a ticket (paginated)
foreach ($repo->getForTicket(1) as $article) {
    echo $article->body;
}

// Download raw attachment content
$binary = $repo->getAttachmentContent(
    ticketId: 1, articleId: 5, attachmentId: 23,
);

$repo = $client->tag();

$repo->add('Ticket', $ticketId, 'urgent');
$repo->remove('Ticket', $ticketId, 'urgent');

foreach ($repo->all(['object' => 'Ticket', 'o_id' => $ticketId]) as $tag) {
    echo $tag->value;
}

$results = $repo->tagSearch('urg'); // Autocomplete

$roles = [];
foreach ($client->role()->all() as $role) {
    $roles[$role->name] = $role->id; // 'Admin' => 1, 'Agent' => 2, 'Customer' => 3
}

$client->user()->create(new UserDTO(
    email: '[email protected]',
    firstname: 'New',
    lastname: 'Agent',
    role_ids: [$roles['Agent']],
));

$client->role()->create(new RoleDTO(
    name: 'Supervisor',
    permission_ids: [10, 11],
    group_ids: [1 => 'full'],   // map of group ID to access level, agent roles only
));

$csv = file_get_contents('users.csv');
$result = $client->user()->import($csv);           // Returns import summary array
$result = $client->organization()->import($csv);   // Returns import summary array
$client->textModule()->import($csv);               // Returns import summary array

use ZammadAPIClient\Core\Auth;
use ZammadAPIClient\Core\ConnectionConfig;
use ZammadAPIClient\ZammadClient;

// Token — sends Authorization: Token token=your-token (Zammad personal access token)
$client = ZammadClient::create($url, Auth::token('your-token'));

// OAuth2 — sends Authorization: Bearer your-oauth-token (OAuth2 access token)
$client = ZammadClient::create($url, Auth::oauth2('your-oauth-token'));

// Basic Auth — sends Authorization: Basic base64(user:pass)
$client = ZammadClient::create($url, Auth::basic('[email protected]', 'test'));

// Options
$client = ZammadClient::create($url, Auth::token('your-token'),
    new ConnectionConfig(verifySsl: false, maxRetries: 5),
);

// Pass a PSR-3 Logger to log HTTP requests and retries
$client = ZammadClient::create($url, Auth::token('your-token'),
    new ConnectionConfig(logger: $myLogger),
);

use ZammadAPIClient\Core\Transport\RequestHandler;

$handler = new RequestHandler($psr18Client, $psr17Factory, $url, auth: Auth::token('your-token'));
$client  = new ZammadClient($handler);

use ZammadAPIClient\ZammadClient;

class TicketController
{
    public function __construct(private ZammadClient $zammad) {}

    public function show(int $id)
    {
        return $this->zammad->ticket()->find($id);
    }
}

// Or resolve manually: app(ZammadClient::class)

ZammadAPIClient\Bridge\SymfonyBundle::class => ['all' => true],

use ZammadAPIClient\ZammadClient;

class TicketService
{
    public function __construct(private ZammadClient $zammad) {}

    public function findTicket(int $id)
    {
        return $this->zammad->ticket()->find($id);
    }
}

use ZammadAPIClient\Exceptions\{
    AuthenticationException,
    ForbiddenException,
    NotFoundException,
    ValidationException,
    RateLimitException,
    ServerErrorException,
    NetworkException,
};

try {
    $client->ticket()->find(999999);
} catch (NotFoundException $e) {
    echo $e->getMessage();          // "Resource not found: tickets/999999"
} catch (ValidationException $e) {
    print_r($e->errors);            // Per-field validation messages
} catch (AuthenticationException $e) {
    // Invalid credentials (401)
} catch (ForbiddenException $e) {
    // Valid credentials but insufficient permissions (403)
} catch (RateLimitException $e) {
    echo $e->retryAfterSeconds;     // Auto-retried, thrown on exhaustion (429)
} catch (ServerErrorException $e) {
    // Server error (5xx)
} catch (NetworkException $e) {
    // DNS, timeout, connection refused
}

// Example: reassign ticket and leave an internal note
$client->ticket()->patch(42, new TicketUpdateDTO(
    owner_id: 7,
    note: 'Reassigned from support queue.',
));

use ZammadAPIClient\Core\Auth;
use ZammadAPIClient\Core\Transport\ImpersonationHandler;
use ZammadAPIClient\ZammadClient;

$client = ZammadClient::create('https://zammad.example', Auth::token('your-token'));

// Accepts user ID (int), login, or email (string); no credentials needed here —
// they come from $client's handler
$asUser = new ZammadClient(new ImpersonationHandler($client->getHandler(), 1));
$ticket = $asUser->ticket()->find(42);

$asAgent = new ZammadClient(new ImpersonationHandler($client->getHandler(), '[email protected]'));

// $client itself is unaffected
bash
ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_URL=https://your-zammad.example \
ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_TOKEN=your-token \
php examples/cookbook/01-quick-start.php
bash
php artisan vendor:publish --tag=zammad-config   # copies config to config/zammad.php