Helpdesk API

29 PracBill API endpoints for helpdesk. Base URL https://billing.pracbill.com.au/api.

Get tickets for a customer (any status unless filtered), newest first. Failure: `customer not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/customer/{cid}/tickets

Parameters

NameInTypeDescription
statusqueryintegerFilter by status (0=open, 1=closed, 2=void); all statuses when omitted
limitqueryintegerMaximum rows (default 50)

Responses

  • 200 — Customer tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a specific note. Failure: `note not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/note/{noteid}

Responses

  • 200 — Note retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Soft-delete a note (POST or DELETE, same behaviour). Failure: `note not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

DELETE /{api_key}/helpdesk/note/{noteid}/delete

Responses

  • 200 — Note deleted successfully (failures: HTTP 200 with the ErrorResponse envelope)

Soft-delete a note (POST or DELETE, same behaviour). Failure: `note not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/note/{noteid}/delete

Responses

  • 200 — Note deleted successfully (failures: HTTP 200 with the ErrorResponse envelope)

Update a note (POST or PUT, same behaviour). The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `note not found`, `no update data provided`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/note/{noteid}/update

Request body

FieldTypeDescription
notestringNew note text
internalintegerTruthy = internal (1), otherwise 0
ignore_responseintegerTruthy = exclude from response statistics (1), otherwise 0

Responses

  • 200 — Note updated successfully (failures: HTTP 200 with the ErrorResponse envelope)

Update a note (POST or PUT, same behaviour). The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `note not found`, `no update data provided`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

PUT /{api_key}/helpdesk/note/{noteid}/update

Request body

FieldTypeDescription
notestringNew note text
internalintegerTruthy = internal (1), otherwise 0
ignore_responseintegerTruthy = exclude from response statistics (1), otherwise 0

Responses

  • 200 — Note updated successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get helpdesk statistics for the department. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/stats

Responses

  • 200 — Statistics retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get helpdesk statistics for the department, filtered to one assignee. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/stats/{uid}

Responses

  • 200 — Statistics retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Create a new helpdesk ticket (status open). The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `customer id (cid) is required`, `subject is required`, `customer not found`, `failed to create ticket`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/create

Request body

FieldTypeDescription
cid requiredobjectCustomer: accepts cid, crm_id or customers_id (resolved by getCustomer()). Required, must not be empty/0
subject requiredstringRequired, must not be empty
bodystringOptional. When non-empty an initial note (hlpjob_note) is created from it; the ticket's own `body` column is stored as an empty string
uidintegerAssigned user id (also recorded as the author of the initial note, 0 when omitted)
priorityinteger1=Low, 2=Medium, 3=High, 4=Critical. Invalid or omitted values default to 1
ostypestringStored in helptickets.ostype when non-empty
internalintegerInternal flag of the initial note (cast with intval, default 0)
contactsarray of objectExtra ticket contacts (helptickets_contacts)

Responses

  • 200 — Ticket created successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a ticket with its customer, assigned user, notes, attachments and contacts. Failure: `ticket not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/ticket/{htid}

Responses

  • 200 — Ticket retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Assign a ticket to a user. Failures: `ticket not found`, `user not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/assign/{uid}

Responses

  • 200 — Ticket assigned successfully (failures: HTTP 200 with the ErrorResponse envelope)

Upload a single attachment to an existing helpdesk ticket. The request must be multipart/form-data with the binary in the `file` field; JSON or base64 bodies are not accepted. Files larger than 10MB are rejected. The new attachment is listed by the ticket detail endpoint and served by the attachment download endpoint.

POST /{api_key}/helpdesk/ticket/{htid}/attachment

Responses

  • 200 — Attachment stored successfully, or a JSON error describing why it was rejected

Download a single attachment belonging to a helpdesk ticket. The file content is base64 encoded in the JSON response. Files larger than 10MB are not served.

GET /{api_key}/helpdesk/ticket/{htid}/attachment/{rdid}

Responses

  • 200 — Attachment retrieved successfully, or a JSON error describing why it could not be served

Close a helpdesk ticket, optionally adding a note. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found`, `ticket is already closed`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/close

Request body

FieldTypeDescription
notestringOptional. When non-empty a customer-visible note is added, prefixed `Ticket Closed: ` / `Ticket Voided: ` / `Ticket Reopened: `
uidintegerAuthor of that note (default 0)

Responses

  • 200 — Ticket closed successfully (failures: HTTP 200 with the ErrorResponse envelope)

Merge source tickets into the primary ticket {htid}, mirroring the helpdesk merge screen: each source's notes, helpdesk attachments (every legacy helpdesk module-type spelling; other modules' attachments sharing the numeric id never move) and ticket contacts move to the primary, the source gets an internal `Job Merged with: {htid}` note and is closed (status 1). The primary ticket is otherwise unchanged and no notification is sent. Sources must exist in the API key's department and belong to the primary ticket's customer. Every source is validated before anything is written, so a rejected request makes no changes. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found` (primary or any source missing or in another department), `ticket_ids must be a non-empty array of ticket ids`, `ticket_ids must only contain positive integer ticket ids`, `ticket_ids contains duplicate ticket id {id}`, `a ticket cannot be merged into itself`, `ticket {id} belongs to a different customer`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/merge

Request body

FieldTypeDescription
ticket_ids requiredarray of integerSource ticket ids to merge into the primary ticket. Unique positive integers (numeric strings are accepted); must not include the primary ticket id

Responses

  • 200 — Tickets merged successfully (failures: HTTP 200 with the ErrorResponse envelope)

Add a note to a ticket. Optionally stores base64 encoded file attachments against the ticket (up to 10, each at most 10MB decoded) and, with send_notification set, sends the standard helpdesk update email for the note with those files attached. Invalid attachment input is rejected before the note or any attachment is written. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/note/add

Request body

FieldTypeDescription
note requiredstringRequired, must not be empty
uidintegerAuthor user id (default 0 = system/API)
internalintegerTruthy = internal only (stored 1), otherwise 0 (default)
ignore_responseintegerTruthy = exclude from response-time statistics (stored 1/0). Omitted = column default
send_notificationinteger1 to send the standard helpdesk update email for this note (attachments from this request included). Default 0: nothing is emailed. Internal notes/tickets keep the notifier's customer-email suppression.
attachmentsarray of objectFiles to attach to the ticket. Each is stored in the department's attacheddocs directory and listed on the ticket, exactly as a UI upload. Names must be plain file names (no path separators or control characters); content must be valid base64 decoding to 1..10485760 bytes.

Responses

  • 200 — Note added successfully, or a failure envelope

Get all notes for a ticket (newest first). Failure: `ticket not found`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/ticket/{htid}/notes

Responses

  • 200 — Notes retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Set ticket priority. Failures: `ticket not found`, `invalid priority (must be 1, 2, 3, 4)`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/priority/{priority}

Responses

  • 200 — Priority updated successfully (failures: HTTP 200 with the ErrorResponse envelope)

Reopen a helpdesk ticket, optionally adding a note. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found`, `ticket is already open`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/reopen

Request body

FieldTypeDescription
notestringOptional. When non-empty a customer-visible note is added, prefixed `Ticket Closed: ` / `Ticket Voided: ` / `Ticket Reopened: `
uidintegerAuthor of that note (default 0)

Responses

  • 200 — Ticket reopened successfully (failures: HTTP 200 with the ErrorResponse envelope)

Update a helpdesk ticket (POST or PUT, same behaviour). The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found`, `invalid status` (a supplied `status` outside 0-4 rejects the whole request and nothing is written), `no update data provided`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/update

Request body

FieldTypeDescription
subjectstring
uidintegerAssign to user id
priorityinteger1-4; values outside the accepted levels are silently ignored
statusinteger (0 | 1 | 2 | 3 | 4)0=open, 1=closed, 2=void, 3=awaiting customer input, 4=awaiting supplier input. Any other value rejects the whole request with `invalid status` and nothing is written
ostypestring
cidobjectMove the ticket to another customer (cid/crm_id/customers_id); company is updated too. An unknown customer is silently ignored

Responses

  • 200 — Ticket updated successfully (failures: HTTP 200 with the ErrorResponse envelope)

Update a helpdesk ticket (POST or PUT, same behaviour). The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found`, `invalid status` (a supplied `status` outside 0-4 rejects the whole request and nothing is written), `no update data provided`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

PUT /{api_key}/helpdesk/ticket/{htid}/update

Request body

FieldTypeDescription
subjectstring
uidintegerAssign to user id
priorityinteger1-4; values outside the accepted levels are silently ignored
statusinteger (0 | 1 | 2 | 3 | 4)0=open, 1=closed, 2=void, 3=awaiting customer input, 4=awaiting supplier input. Any other value rejects the whole request with `invalid status` and nothing is written
ostypestring
cidobjectMove the ticket to another customer (cid/crm_id/customers_id); company is updated too. An unknown customer is silently ignored

Responses

  • 200 — Ticket updated successfully (failures: HTTP 200 with the ErrorResponse envelope)

Void a helpdesk ticket, optionally adding a note. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failures: `ticket not found`, `ticket is already voided`. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/ticket/{htid}/void

Request body

FieldTypeDescription
notestringOptional. When non-empty a customer-visible note is added, prefixed `Ticket Closed: ` / `Ticket Voided: ` / `Ticket Reopened: `
uidintegerAuthor of that note (default 0)

Responses

  • 200 — Ticket voided successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a paginated list of helpdesk tickets (page 1). GET and POST behave identically. Filters are read from $_REQUEST, so they may be sent in the query string (GET) or as query/form-encoded parameters on a POST; a JSON body is not read. Results are scoped to the API key's department. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/tickets

Parameters

NameInTypeDescription
statusqueryintegerStatus filter (0=open, 1=closed, 2=void). Defaults to 0 (open) when not supplied
cidqueryintegerFilter by customer id (ignored when 0/empty)
uidqueryintegerFilter by assigned user id; 0 returns unassigned tickets
priorityqueryintegerFilter by priority (1=Low..4=Critical; ignored when 0)
date_fromquerystringTickets with date >= this value (YYYY-MM-DD)
date_toquerystringTickets with date <= this value (YYYY-MM-DD)
searchquerystringSearch in subject and company
limitqueryintegerRecords per page (default 20)
order_byquerystringSort column (default lastupdate; other values fall back to lastupdate)
order_dirquerystringASC or DESC (default DESC; anything other than ASC is treated as DESC)

Responses

  • 200 — Tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a paginated list of helpdesk tickets (page 1). GET and POST behave identically. Filters are read from $_REQUEST, so they may be sent in the query string (GET) or as query/form-encoded parameters on a POST; a JSON body is not read. Results are scoped to the API key's department. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/tickets

Parameters

NameInTypeDescription
statusqueryintegerStatus filter (0=open, 1=closed, 2=void). Defaults to 0 (open) when not supplied
cidqueryintegerFilter by customer id (ignored when 0/empty)
uidqueryintegerFilter by assigned user id; 0 returns unassigned tickets
priorityqueryintegerFilter by priority (1=Low..4=Critical; ignored when 0)
date_fromquerystringTickets with date >= this value (YYYY-MM-DD)
date_toquerystringTickets with date <= this value (YYYY-MM-DD)
searchquerystringSearch in subject and company
limitqueryintegerRecords per page (default 20)
order_byquerystringSort column (default lastupdate; other values fall back to lastupdate)
order_dirquerystringASC or DESC (default DESC; anything other than ASC is treated as DESC)

Responses

  • 200 — Tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get all open (status 0) tickets across the department, ordered by priority DESC then lastupdate ASC. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/tickets/outstanding

Responses

  • 200 — Outstanding tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get open tickets assigned to a specific user. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/tickets/outstanding/{uid}

Responses

  • 200 — Outstanding tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a paginated list of helpdesk tickets. GET and POST behave identically. Filters are read from $_REQUEST, so they may be sent in the query string (GET) or as query/form-encoded parameters on a POST; a JSON body is not read. Results are scoped to the API key's department. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

GET /{api_key}/helpdesk/tickets/page/{page_number}

Parameters

NameInTypeDescription
statusqueryintegerStatus filter (0=open, 1=closed, 2=void). Defaults to 0 (open) when not supplied
cidqueryintegerFilter by customer id (ignored when 0/empty)
uidqueryintegerFilter by assigned user id; 0 returns unassigned tickets
priorityqueryintegerFilter by priority (1=Low..4=Critical; ignored when 0)
date_fromquerystringTickets with date >= this value (YYYY-MM-DD)
date_toquerystringTickets with date <= this value (YYYY-MM-DD)
searchquerystringSearch in subject and company
limitqueryintegerRecords per page (default 20)
order_byquerystringSort column (default lastupdate; other values fall back to lastupdate)
order_dirquerystringASC or DESC (default DESC; anything other than ASC is treated as DESC)

Responses

  • 200 — Tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Get a paginated list of helpdesk tickets. GET and POST behave identically. Filters are read from $_REQUEST, so they may be sent in the query string (GET) or as query/form-encoded parameters on a POST; a JSON body is not read. Results are scoped to the API key's department. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/tickets/page/{page_number}

Parameters

NameInTypeDescription
statusqueryintegerStatus filter (0=open, 1=closed, 2=void). Defaults to 0 (open) when not supplied
cidqueryintegerFilter by customer id (ignored when 0/empty)
uidqueryintegerFilter by assigned user id; 0 returns unassigned tickets
priorityqueryintegerFilter by priority (1=Low..4=Critical; ignored when 0)
date_fromquerystringTickets with date >= this value (YYYY-MM-DD)
date_toquerystringTickets with date <= this value (YYYY-MM-DD)
searchquerystringSearch in subject and company
limitqueryintegerRecords per page (default 20)
order_byquerystringSort column (default lastupdate; other values fall back to lastupdate)
order_dirquerystringASC or DESC (default DESC; anything other than ASC is treated as DESC)

Responses

  • 200 — Tickets retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

Search tickets by subject, company or htid. The body is parsed by the shared extractDataFromRequest() helper: a raw JSON body is normal; a url-encoded JSON string or the legacy `json={...}` / `data={...}` form-encoded wrapper is also accepted. Failure: `search query required` when `query` is empty. An invalid or unknown API key returns HTTP 200 with the `ErrorResponse` envelope `{"success": false, "description": "invalid key"}`; the handler's other failures use the same envelope with a different `description`.

POST /{api_key}/helpdesk/tickets/search

Request body

FieldTypeDescription
query requiredstringSearch term, matched (LIKE %term%) against subject, company and htid
statusintegerOptional status filter (0=open, 1=closed, 2=void). When omitted tickets of every status are searched
limitintegerMaximum rows returned (default 50)

Responses

  • 200 — Search results retrieved successfully (failures: HTTP 200 with the ErrorResponse envelope)

← All API groups