Tickets
Full REST API for ticket lifecycle management, replies, time tracking, support contracts, teams, and analytics.
Base URL: /api/v1/tickets (core), /api/v1/ticketing (sub-resources)
Auth required: Yes (auth:api) for all endpoints.
Tickets are the support ticketing system within BlueRockTEL. The Ticketing module provides a full REST API for ticket lifecycle management, replies, time tracking, support contracts, teams, and analytics.
Model Properties
Ticket
| Property | Type | Required | Description |
|---|---|---|---|
id |
integer | auto | Unique identifier |
number |
string | auto | Human-readable ticket number (random 6-char string) |
subject |
string | Yes (create) | Ticket subject. HTML stripped on save |
body |
string | Yes (create) | Ticket body (HTML). Sanitized on save (allowed tags: br, img, ul, ol, li, strong, i, p, a) |
ticketable_type |
string | Yes (create) | Polymorphic type of the linked entity. Currently only App\Customer |
ticketable_id |
integer | Yes (create) | ID of the linked entity |
priority_id |
integer | Yes (create) | FK to priorities |
ticket_category_id |
integer | Yes (create) | FK to ticket categories |
ticket_sub_category_id |
integer | Yes (create) | FK to ticket sub-categories |
status_id |
integer | No | FK to ticketing statuses. Defaults to the default auto-status on creation |
team_id |
integer | No | FK to support teams |
contract_id |
integer | No | FK to support contracts |
assignee_id |
integer | auto | FK to users. Auto-set to creating user on creation |
assigned_by |
integer | auto | FK to users. User who made the assignment |
author_type |
string | auto | Polymorphic type of the author |
author_id |
integer | auto | FK to the author |
opener_id |
integer | auto | FK to users. User who opened the ticket |
contact_id |
integer | No | FK to contacts (primary contact) |
open |
boolean | auto | Whether the ticket is open (default: true) |
closure |
boolean | auto | Whether a closure has been requested |
origin |
string | auto | Origin of the ticket (e.g. admin, email) |
opened_via |
string | auto | How the ticket was opened (e.g. application) |
estimated_resolution_date |
datetime | auto | Expected resolution date. Defaults to 4 hours after creation (format: Y-m-d H:i:s) |
tags |
json | No | Array of tag strings |
exchanges |
integer | auto | Number of reply exchanges |
time |
integer | auto | Total time tracked (minutes) |
points |
float | auto | Support contract points consumed |
billable |
boolean | No | Whether this ticket is billable |
billed |
boolean | No | Whether this ticket has been billed |
opened_at |
datetime | auto | When the ticket was opened |
closed_at |
datetime | auto | When the ticket was closed |
assigned_at |
datetime | auto | When the ticket was assigned |
auto_closure_alerts |
array | auto | Timestamps of auto-closure alert emails sent |
created_at |
datetime | auto | Creation timestamp |
updated_at |
datetime | auto | Last update timestamp |
Read-only computed fields (returned in responses):
| Property | Type | Description |
|---|---|---|
has_unread_replies |
boolean | Whether the latest reply has not been seen (appended on show) |
replies_count |
integer | Number of replies (appended on list endpoints) |
last_reply_seen_at |
datetime | seen_at of the latest reply (appended on list endpoints) |
Reply
| Property | Type | Required | Description |
|---|---|---|---|
id |
integer | auto | Unique identifier |
ticket_id |
integer | auto | FK to ticket |
body |
string | Yes | Reply body (HTML, sanitized on save) |
origin |
string | auto | Reply origin (admin for API-created replies) |
author_type |
string | auto | Polymorphic type of the author |
author_id |
integer | auto | FK to the author |
contact_id |
integer | No | FK to contact (recipient contact) |
seen_at |
datetime | auto | When the reply was read by the admin |
notify_team |
boolean | No | Trigger team notification (not persisted) |
notify_customer |
boolean | No | Trigger customer notification (not persisted) |
customer_visible |
boolean | auto | Whether the reply is visible to the customer |
copy_to_sales |
boolean | auto | Whether a copy was sent to sales |
auto_closure_message |
boolean | auto | Whether this is an auto-closure notification message |
created_at |
datetime | auto | Creation timestamp |
updated_at |
datetime | auto | Last update timestamp |
GET /v1/tickets
List open tickets, ordered by ID descending.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ticketable_type |
string | No | Filter by ticketable type. If provided together with ticketable_id, returns all tickets for that entity regardless of open/closed state |
ticketable_id |
integer | No | Filter by ticketable ID |
Response 200: Array of ticket objects with ticketable, assignee (id, name, email), replies_count, and last_reply_seen_at.
POST /v1/tickets
Create a new ticket. The authenticated user is set as the author, assignee, and opener.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ticketable_type |
string | Yes | Polymorphic type (currently only App\Customer) |
ticketable_id |
integer | Yes | ID of the entity to attach the ticket to |
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
subject |
string | Yes | Ticket subject |
body |
string | Yes | Ticket body (HTML) |
priority_id |
integer | Yes | Priority ID |
ticket_category_id |
integer | Yes | Category ID |
ticket_sub_category_id |
integer | Yes | Sub-category ID |
estimated_resolution_date |
datetime | No | Format: Y-m-d H:i:s. Defaults to now + 4 hours |
tags |
array | No | Array of tag strings |
team_id |
integer | No | Support team ID |
status_id |
integer | No | Initial status ID |
close |
boolean | No | If true, immediately close the ticket after creation |
Response 201: Created ticket object. Response 400: Bad request (missing mandatory fields or invalid ticketable type). Response 404: Ticketable entity not found.
GET /v1/tickets/{id}
Get a single ticket with all related data.
Response 200: Ticket object with replies (including author), ticketable, contacts, category, sub_category, assignee, opener, attachments, has_unread_replies. Template variables in reply bodies are resolved.
Response 404: Not found.
PUT /v1/tickets/{id}
Update a ticket. Only the fields present in the body are updated.
Body (JSON): Any subset of:
| Field | Type | Description |
|---|---|---|
subject |
string | Ticket subject (HTML stripped) |
body |
string | Ticket body (HTML sanitized) |
ticketable_type |
string | Polymorphic type |
ticketable_id |
integer | Entity ID |
team_id |
integer | Support team |
priority_id |
integer | Priority |
ticket_category_id |
integer | Category |
ticket_sub_category_id |
integer | Sub-category |
status_id |
integer | Status |
tags |
array | Tags |
estimated_resolution_date |
datetime | Format: Y-m-d H:i:s |
assignee_id |
integer | Assignee user |
opened_at |
datetime | Format: Y-m-d H:i:s |
contract_id |
integer | Support contract |
close |
boolean | If true, sets open=false and closed_at=now() |
Response 201: Updated ticket object with replies. Response 404: Not found.
DELETE /v1/tickets/{id}
Delete a ticket and all its replies.
Response 200: {"response": "element deleted"}
Response 404: Not found.
GET /v1/tickets/counts
Get ticket counts summary for the current day and week.
Response 200:
{
"total": 150,
"open": 42,
"unassigned": 5,
"assigned_to_myself": 12,
"daily": 8,
"weekly": 30,
"closed": 108
}
GET /v1/tickets/search
Search and filter tickets using Spatie QueryBuilder.
Query parameters (filters):
| Parameter | Type | Description |
|---|---|---|
filter[number] |
string | Filter by ticket number (partial match) |
filter[email] |
string | Filter by email (partial match) |
filter[body] |
string | Filter by body (partial match) |
filter[ticketable_type] |
string | Exact match on ticketable type |
filter[ticketable_id] |
integer | Exact match on ticketable ID |
filter[assignee_id] |
integer | Exact match on assignee |
filter[status_id] |
integer | Exact match on status |
filter[priority_id] |
integer | Exact match on priority |
filter[team_id] |
integer | Exact match on team |
filter[open] |
boolean | Scope: open tickets only |
filter[closed] |
boolean | Scope: closed tickets only |
filter[my_tickets] |
boolean | Scope: tickets assigned to the authenticated user |
filter[my_teams_tickets] |
boolean | Scope: tickets belonging to the authenticated user's teams |
Includes (comma-separated include param): assigner, contract, customer, documents, replies, team, ticketable
Response 200: Filtered array of ticket objects.
POST /v1/tickets/invoicing
Create a billing ticket (used to record time spent and deduct from a support contract). The ticket is created as already closed.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ticketable_type |
string | Yes | Currently only App\Customer |
ticketable_id |
integer | Yes | Customer ID |
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
time |
integer | Yes | Time in minutes (must be >= 1) |
reference |
string | No | Reference string for the ticket subject |
ticket_date |
date | No | Date for the ticket (format: Y-m-d). Defaults to now |
contact_id |
integer | No | Contact ID |
Response 201: {"response": "ticket created", "ticket": {...}}
PUT /v1/tickets/assign/{id}
Assign a ticket to a user.
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
assignee_id |
integer | Yes | ID of the user to assign |
Response 201: Assignee user object.
Response 400: Missing assignee_id.
Response 404: Ticket or assignee not found.
PUT /v1/tickets/free/{id}
Remove the assignee from a ticket.
Response 201: {"response": "ticket freed"}
Response 404: Not found.
PUT /v1/tickets/close/{id}
Close a ticket.
Response 201: {"response": "ticket closed"}
PUT /v1/tickets/open/{id}
Re-open a ticket. If the ticket has a pending closure, calls reopen instead (cancels the closure).
Response 201: {"response": "ticket open"}
PUT /v1/tickets/reopen/{id}
Reopen a ticket by cancelling any pending closure.
Response 201: Refreshed ticket object.
PUT /v1/tickets/amend/{id}
Amend the tracked time on a ticket.
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
time |
numeric | Yes | Time adjustment in minutes |
Response 201: {"response": "ticket time amended"}
PUT /v1/tickets/export/{customer_id}
Export tickets for a customer to an Excel file.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
with_segments |
boolean | If true, includes time segments in the export |
Response 200: Excel file download. Response 404: Customer not found.
POST /v1/tickets/{id}/read-replies
Mark all unread replies of a ticket as read (sets seen_at = now()).
Response 201: {"success": true}
Response 404: Not found.
GET /v1/tickets/{id}/customer
Get the customer linked to a ticket (follows the ticketable relationship chain).
Response 200: Customer object with contacts. Response 404: Not found.
PUT /v1/tickets/{id}/associates
Manage the contacts associated with a ticket (attach and detach).
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
associated |
array | Yes | Array of contact IDs to attach |
unassociated |
array | Yes | Array of contact IDs to detach |
Contacts must belong to the same contactable as the ticket's existing contacts. A contact will not be detached if it is the last one.
Response 201: {"response": "N associated and M unassociated"}
GET /v1/replies
List all replies for a ticket.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ticket_id |
integer | Yes | Ticket ID |
Response 200: Array of reply objects. Response 404: Ticket not found.
POST /v1/replies
Add a reply to a ticket.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ticket_id |
integer | Yes | Ticket ID |
Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
body |
string | Yes | Reply body (HTML, sanitized on save) |
close |
boolean | Yes | If true, closes the ticket after the reply |
send_to_assignee |
boolean | Yes | Whether to notify the assignee |
send_to_contacts |
boolean | Yes | Whether to send the reply to the ticket's contacts |
Response 201: Created reply object. Response 404: Ticket not found.
Ticket Analytics
| Endpoint | Method | Description |
|---|---|---|
GET /v1/tickets-insights |
GET | Full ticket analytics including statistics, averages, and history |
GET /v1/tickets-insights/aggregations |
GET | Aggregated ticket statistics only |
GET /v1/tickets-insights/averages |
GET | Average metrics (e.g. average resolution time) |
GET /v1/tickets-insights/yearly-averages |
GET | Average metrics broken down by year |
Ticketing Statuses
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/statuses |
GET | List all statuses |
/v1/ticketing/statuses |
POST | Create a status |
/v1/ticketing/statuses/{id} |
GET | Show a status |
/v1/ticketing/statuses/{id} |
PUT | Update a status |
/v1/ticketing/statuses/{id} |
DELETE | Delete a status |
Statuses control auto-behaviour: auto_for field determines automatic transitions (e.g. default, on_admin_reply, on_customer_reply). Deleting a status updates all linked tickets to have status_id = null.
Ticketing Priorities
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/priorities |
GET | List all priorities (ordered by ID) |
Ticketing Categories
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/categories |
GET | List all categories (with sub-category counts) |
/v1/ticketing/categories |
POST | Create a category |
/v1/ticketing/categories/{id} |
GET | Show a category with sub-categories |
/v1/ticketing/categories/{id} |
PUT | Update a category |
/v1/ticketing/categories/{id} |
DELETE | Delete a category |
/v1/ticketing/sub-categories |
GET | List all sub-categories (with category and priority) |
/v1/ticketing/sub-categories |
POST | Create a sub-category |
/v1/ticketing/sub-categories/{id} |
GET | Show a sub-category |
/v1/ticketing/sub-categories/{id} |
PUT | Update a sub-category |
/v1/ticketing/sub-categories/{id} |
DELETE | Delete a sub-category |
Ticketing Attachments
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/attachments |
GET | List attachments |
/v1/ticketing/attachments |
POST | Upload a new attachment |
/v1/ticketing/attachments/{id} |
GET | Show attachment metadata |
/v1/ticketing/attachments/{id} |
PUT | Update attachment metadata |
/v1/ticketing/attachments/{id} |
DELETE | Delete an attachment |
/v1/ticketing/attachments/{id}/content |
GET | Download the attachment file |
Support Contracts
Support contracts track point-based support commitments for customers.
Model Properties
| Property | Type | Description |
|---|---|---|
id |
integer | Unique identifier |
support_contracteable_type |
string | Polymorphic type of the contract owner |
support_contracteable_id |
integer | ID of the contract owner |
type |
integer | Contract type (1-6) |
points_total |
float | Total points allocated |
points_init |
float | Initial points at contract start |
points_init_memory |
float | Memory of initial points (for history) |
points_current |
float | Current remaining points |
points_alert |
float | Points threshold for alert notification |
points_auto_renew |
float | Points added on auto-renewal |
points_auto_added |
float | Points added since last renewal |
signed_at |
date | Contract signature date (format: d/m/Y) |
started_at |
datetime | When the contract started |
expires_at |
datetime | When the contract expires |
last_notified_at |
datetime | When the last alert was sent |
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/support_contracts/customer |
GET | Get contracts for the customer specified by ?support_contracteable_type= and ?support_contracteable_id= |
/v1/ticketing/support_contracts |
GET | List all contracts |
/v1/ticketing/support_contracts |
POST | Create a contract (initializes points from points_init) |
/v1/ticketing/support_contracts/{id} |
GET | Show a contract |
/v1/ticketing/support_contracts/{id} |
PUT | Update a contract |
/v1/ticketing/support_contracts/{id} |
DELETE | Delete a contract |
Shared Support Contracts
Allows sharing a support contract's points with another customer.
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/shared_support_contracts |
GET | List shared contracts |
/v1/ticketing/shared_support_contracts |
POST | Share a contract with a customer (cannot self-share) |
/v1/ticketing/shared_support_contracts/{id} |
GET | Show a shared contract |
/v1/ticketing/shared_support_contracts/{id} |
DELETE | Remove a contract share |
Support Sheets
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/support_sheets |
GET | List support sheets (filterable by ?customer_id=) |
/v1/ticketing/support_sheets |
POST | Create a support sheet |
/v1/ticketing/support_sheets/{id} |
GET | Show a support sheet |
/v1/ticketing/support_sheets/{id} |
PUT | Update a support sheet |
/v1/ticketing/support_sheets/{id} |
DELETE | Delete a support sheet |
Support Teams
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/support-teams |
GET | List all support teams (with user counts) |
/v1/ticketing/support-teams |
POST | Create a support team |
/v1/ticketing/support-teams/{id} |
GET | Show a support team with counts |
/v1/ticketing/support-teams/{id} |
PUT | Update a support team |
/v1/ticketing/support-teams/{id} |
DELETE | Delete a support team |
/v1/ticketing/support-teams/{id}/members |
GET | List team members |
/v1/ticketing/support-teams/{id}/members |
POST | Add members (does not detach existing) |
/v1/ticketing/support-teams/{id}/members |
PUT | Sync members (replaces existing list) |
/v1/ticketing/support-teams/{id}/members |
DELETE | Remove members |
Time Segments
Time segments track billable time on tickets.
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/time_segments |
GET | List time segments |
/v1/ticketing/time_segments |
POST | Create a time segment |
/v1/ticketing/time_segments/{id} |
GET | Show a time segment |
/v1/ticketing/time_segments/{id} |
PUT | Update a time segment |
/v1/ticketing/time_segments/{id} |
DELETE | Delete a time segment |
Time Tracking
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/start_tracking |
POST | Start tracking time on a ticket. Body: {"ticket_id": int, "previous_ticket_id": int (optional)} |
/v1/ticketing/end_tracking |
POST | Stop tracking time. Body: {"ticket_id": int (optional)} |
Templates
| Endpoint | Method | Description |
|---|---|---|
/v1/ticket_templates |
GET/POST | List / create ticket templates |
/v1/ticket_templates/{id} |
GET/PUT/DELETE | Show / update / delete ticket template |
/v1/reply_templates |
GET/POST | List / create reply templates |
/v1/reply_templates/{id} |
GET/PUT/DELETE | Show / update / delete reply template |
Customer Report
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/customer_report |
GET | Generate or retrieve a PDF ticketing report for a customer. Supports date range parameters |
Daily Points Summary
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/daily_points_summary |
GET | List daily points summary records, ordered by ID descending |
Ticketing Config
| Endpoint | Method | Description |
|---|---|---|
/v1/ticketing/config |
GET | Get all ticketing configuration values |
/v1/ticketing/config |
PUT | Update configuration values (point values, closure delays, auto-closure settings, team report emails) |
On this page