Open source
Tickets for Laravel
composer require roundly-consulting/tickets-for-laravelOverview
A headless helpdesk core for Laravel. Customers and colleagues open tickets with gap-free references, your team works them through swappable statuses, and everyone talks in one conversation per ticket — public replies plus internal notes requesters never see. Assignment, priorities, due dates, custom fields, guest requesters, merging, mail notifications in English and Slovak and an opt-in JSON API sit behind one facade. MIT-licensed and built only on official Laravel components and Roundly’s own packages for statuses, comments, custom fields, translations, files and filtering — no third-party helpdesk vendor.
What you get
Gap-free references
Human numbers like TCK-42, or SUP-42 per project — handed out in order with no gaps and no duplicates, even under concurrent creates.
Swappable statuses
Seven states in five categories on lifecycle-for-laravel, one-word transitions, automations and auto-close — or your own lifecycle.
Replies and internal notes
One conversation per ticket: public replies that can move the ticket on, and agent-only notes that never reach a requester, a mail or a count.
Assignment and due dates
Assign people or whole teams, let agents claim work, set category defaults, and flag overdue and due-soon tickets exactly once.
Custom fields
Typed fields globally, per project or per category, with allow-listed rules, encryption and requester visibility — filterable from PHP and the API.
Guests, merging and links
Requesters without an account behind revocable signed links, duplicate merging, typed ticket links, watchers and coloured tags.
Opt-in JSON API and mail
Role-aware resources, filters, bulk actions, rate limits and a policy — plus queued, visibility-checked mail in English and Slovak.
Facade, DI or actions
One Tickets facade, an injectable manager or single-purpose actions — and a recording fake that still performs every call.
Documentation
Use cases
Where the package fits — SaaS support, IT desks, agency projects, shops and public services — and the shipped capability behind each one.
Installation
Install via Composer, run tickets:install and migrate, settle key types, make your user an assignee, define the abilities and schedule the sweeps.
Configuration
Every config key with its env variable and default — keys, lifecycle, priorities, guests, watchers, authorization, attachments, routes and notifications.
Models, keys and references
Key types, gap-free references and sequences, the nine models, the Ticket model’s columns, status helpers and host metadata, model swaps and enums.
The Tickets facade
Tour the Tickets facade — make() and create(), the for($ticket) handle, categories, fields, tags, guests, projects, visibleTo() and sweep().
DI and actions
Skip the facade: inject TicketsManager or call a single-purpose action — every host-facing action with its execute() signature and facade path.
Filing and editing tickets
File tickets with the builder or CreateTicketData, fill defaults from categories, then edit, recategorise, hand over, delete and restore them.
Statuses and transitions
Seven states, five categories and nine transitions — plus named conveniences, automations, auto-close, the conversation lock and custom lifecycles.
Replies and internal notes
Public replies and agent-only notes on a comments-for-laravel thread — author roles, reply automations, first response, moderation, mentions and edits.
Categories and priorities
Nested, translatable categories with a default priority, assignee and due offset — plus the weighted priority enum and how to swap it.
Due dates and the sweep
Set, move or clear due dates, fill them from categories, and flag overdue and due-soon tickets exactly once with Tickets::sweep() or tickets:sweep.
Assignment and watchers
One assignee per ticket — a user or a team — with claim(), eligibility and default assignees, plus watchers, auto-watch and requester hand-overs.
Tags and links
Agent-only coloured tags, global or per project, with permanent names — and typed links between tickets with cycle checks.
Merging tickets
Merge a duplicate into the right ticket — conversation, watchers, tags and files move over in one transaction, and the source closes with a pointer.
Attachments
Files on the ticket itself in a private media-library bucket, served through short-lived signed URLs — plus attachments on replies and notes.
Custom fields
Typed fields globally, per project or per category, with allow-listed rules, encryption and requester visibility — set, read, filter and prune values.
Guests and guest links
Tickets from people without an account — configurable guest fields, safe matching of returning guests, conversion on sign-up and revocable signed links.
Projects
Number tickets per project (SUP-1, WEB-1) with their own categories, fields and tags through the TicketProject contract and the HasTickets trait.
Querying and the activity timeline
Eloquent scopes shared by PHP and the API — status, priority, category, assignee, fields, dates and search — plus the append-only activity timeline.
JSON API
An opt-in JSON API — routes, request bodies, bulk actions, role-aware resources, list filters and sorts, rate limits and error codes.
Policy and agent scope
The TicketPolicy behind the API, the Gate abilities you define, scoped managers, and an AgentScope that limits agents to the tickets they may work on.
Notifications
Ten queued, after-commit notifications in English and Slovak — recipients, visibility re-checks, payloads, swapping classes and other channels.
Extension points
Every swap point — contracts and their shipped implementations, the lifecycle, priority enum, models, policy and notifications — without forking.
Events
34 after-commit events, 33 of them TicketEvent — one typed listener hears every ticket change for webhooks, audit logs and dashboards.
Exceptions
Every TicketsException subclass, when it is thrown and the HTTP status the API answers with — plus how field and guest validation errors are keyed.
Artisan commands
tickets:install, tickets:doctor with its checks and exit codes, tickets:sweep for due dates and tickets:prune-fields for orphaned values.
Testing
Tickets::fake() records every operation and still performs it — every assertion and its negative twin, recorded operations, factories and app setup.
Requirements
PHP 8.4+, Laravel 12 or 13, MySQL or PostgreSQL (SQLite for tests) and the Roundly packages it builds on, installed by Composer.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.