Customer Service, Help Desk, Tickets, SLAs, and Knowledge Base for Focal CRM
focalcrm/service is a Laravel package for customer service, help desk, tickets, slas, and knowledge base for focal crm.
It currently has 0 GitHub stars and 9 downloads on Packagist (latest version v0.2.3).
Install it with composer require focalcrm/service.
Discover more Laravel packages by focalcrm
or browse all Laravel packages to compare alternatives.
Last updated
focalcrm/service)This is a read-only split of the focalcrm/focal monorepo. Please open issues and pull requests there.
The customer support, helpdesk, and SLA orchestration engine for the Focal RevOps platform. Delivers multi-channel ticketing (Email, Web, Chat, API), business-hours SLA policy enforcement, knowledge deflection, automated ticket routing, thread merging, and an embeddable customer portal.
+-------------------------------------------------------------------------+
| FOCAL SERVICE |
| |
| +--------------------+ +--------------------+ +-----------------+ |
| | Multi-Channel | | Inbound Webhooks & | | Embeddable Help | |
| | Ticketing (Email) | | Thread Parsers | | Widget & Portal | |
| +--------------------+ +--------------------+ +-----------------+ |
| \ | / |
| v v v |
| +---------------------------------------------------------+ |
| | SLA Engine & Breach Watchdogs | |
| | (Business hours calendar, First Response & Resolv) | |
| +---------------------------------------------------------+ |
| | | | |
| v v v |
| +--------------------+ +--------------------+ +-----------------+ |
| | Skill-Based Ticket | | Canned Responses & | | Knowledge Base | |
| | Routing Rules | | Private Agent Notes| | & Deflections | |
| +--------------------+ +--------------------+ +-----------------+ |
+-------------------------------------------------------------------------+
Urgent, High, Medium, Low). Supports customizable operating hours (e.g., 9-to-5 weekdays) and holiday calendar pauses.widget.js): Lightweight, zero-dependency JavaScript drawer embeddable on any web property for on-site help, knowledge lookups, and ticket creation.composer require focalcrm/service
Publish configuration and migrations:
php artisan vendor:publish --tag=focal-service-migrations
php artisan vendor:publish --tag=focal-service-config
Run migrations:
php artisan migrate
use Focal\Service\Actions\CreateTicketAction;
use Focal\Service\Enums\TicketPriority;
use Focal\Service\Enums\TicketSource;
$ticket = app(CreateTicketAction::class)->execute([
'contact_id' => $contact->id,
'subject' => 'Production API returning 504 Gateway Timeout',
'body' => 'Our billing batch failed at 03:00 UTC due to gateway timeouts.',
'priority' => TicketPriority::Urgent,
'source' => TicketSource::Email,
]);
// SLA response deadlines are automatically calculated based on the priority policy
echo "First response due: " . $ticket->first_response_due_at->toIso8601String();
use Focal\Service\Actions\ReplyTicketAction;
use Focal\Service\Enums\MessageSenderType;
// Public response to customer (stops SLA first-response clock)
app(ReplyTicketAction::class)->execute(
ticket: $ticket,
body: 'We have identified an upstream cache lock and applied a hotfix. Please retry.',
senderType: MessageSenderType::Agent,
senderId: auth()->id(),
isPrivate: false
);
// Private internal note between support engineers
app(ReplyTicketAction::class)->execute(
ticket: $ticket,
body: 'Escalated to DevOps on-call. Redis connection pool exhausted during cron.',
senderType: MessageSenderType::Agent,
senderId: auth()->id(),
isPrivate: true
);
use Focal\Service\Actions\MergeTicketsAction;
// Merges $duplicateTicket into $primaryTicket, moving all messages and closing the duplicate
app(MergeTicketsAction::class)->execute(
primaryTicket: $primaryTicket,
secondaryTicket: $duplicateTicket,
agentId: auth()->id()
);
use Focal\Service\Actions\CheckSlaBreachesAction;
// Identified tickets nearing or past breach deadline; dispatches SlaBreachAlertNotification
$breachedTickets = app(CheckSlaBreachesAction::class)->execute();
// Or run via Artisan in cron:
// php artisan focal:service-check-sla
Point the widget at the chat API base URL, including any configured prefix (defaults to the same-origin /api/service), then load resources/js/widget.js:
<script>
window.FOCAL_CHAT_API_URL = 'https://crm.yourcompany.com/api/service';
</script>
<script src="https://raw.githubusercontent.com/FocalCRM/service/refs/heads/main/js/focal-chat-widget.js" async></script>
The help center (/help) and support portal (/support) are registered in the web group with no prefix by default. The inbound email webhook, knowledge deflection and chat widget APIs are registered in the api group under /api/service.
Configure them in config/focal-service.php (publish with php artisan vendor:publish --tag=focal-service-config) or through environment variables:
FOCAL_SERVICE_PREFIX=care # /help becomes /care/help
FOCAL_SERVICE_API_PREFIX=api/service
FOCAL_SERVICE_DOMAIN=support.example.com # optional, applies to both groups
FOCAL_SERVICE_ROUTES_ENABLED=true
Each group also accepts middleware. To register the routes yourself, set routes.enabled to false and define routes with the same names (focal.help.*, focal.support.*, focal.service.*), because models, emails and notifications generate links from those names.
The inbound email webhook (POST /api/service/inbound-email) requires the service API token. Until FOCAL_SERVICE_API_TOKEN is set, it responds with 403 and creates no tickets.
FOCAL_SERVICE_API_TOKEN= # e.g. php -r "echo bin2hex(random_bytes(32));"
Send it as Authorization: Bearer <token>, an X-Focal-Token header, or a ?token=<token> query parameter (for email providers that only accept a webhook URL).
The chat widget, help center votes, knowledge deflection, and support portal submissions stay public and are rate limited per IP (FOCAL_PUBLIC_RATE_LIMIT, requests per minute; see config/focal-core.php).
| Model | Table | Responsibility |
| :--- | :--- | :--- |
| Ticket | service_tickets | Support tickets with priority, status, SLA deadlines, CSAT rating, and portal tokens. |
| TicketMessage | service_ticket_messages | Threaded customer messages, agent replies, and private internal notes. |
| SlaPolicy | service_sla_policies | Target resolution and response durations with business-hour definitions. |
| TicketRoutingRule | service_ticket_routing_rules | Assignment rules mapping priority, language, and keywords to agents. |
| KnowledgeArticle | service_knowledge_articles | Public self-service troubleshooting guides with deflection tracking. |
| CannedResponse | service_canned_responses | Reusable response snippets with dynamic variable interpolation. |
vendor/bin/pest packages/service/tests --compact