Skip to content

Commit 313f8cf

Browse files
committed
Enhance Ticket API to support email thread entries and update documentation
1 parent 2d891f7 commit 313f8cf

5 files changed

Lines changed: 321 additions & 294 deletions

File tree

include/api.tickets.php

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ private function array2XML($object, $data) {
414414
}
415415

416416
/**
417-
* Add a thread entry (reply or note) to a ticket
417+
* Add a thread entry (reply, note, or email) to a ticket
418418
*
419419
* This method allows adding a new thread entry to an existing ticket.
420420
* It supports:
@@ -428,9 +428,9 @@ private function array2XML($object, $data) {
428428
* - Alerting participants
429429
*
430430
* Request fields (Staff/API posting):
431-
* - thread_type: 'note' for internal note, 'response' for public reply (required)
431+
* - thread_type: 'note' for internal note, 'response' for public reply, 'email' for client email simulation (required)
432432
* - message: Content of the thread entry (required)
433-
* - staffId: ID of staff member making the post (optional)
433+
* - staffId: ID of staff member making the post (optional, not used for 'email' type)
434434
* - alert: Whether to alert participants (default: true)
435435
* - poster: Name of the poster (default: 'API')
436436
* - cannedId: ID of canned response to use (optional)
@@ -445,8 +445,7 @@ private function array2XML($object, $data) {
445445
* - data: File contents
446446
* - encoding: 'base64' if encoded, otherwise raw data assumed
447447
*
448-
* Request fields (Client/User reply simulation):
449-
* - as_client: Set to true to simulate a client reply (required for user replies)
448+
* Request fields (Email/Client reply simulation - when thread_type='email'):
450449
* - message: Content of the user reply (required)
451450
* - userId: ID of the user making the reply (default: ticket owner)
452451
* - attachments: Array of file attachments (optional, same format as above)
@@ -467,20 +466,21 @@ function addThread($id, $format) {
467466
// Get request data
468467
$data = $this->getRequest($format);
469468

470-
// Check if this is a user/client reply simulation
471-
$isClientReply = isset($data['as_client']) && $data['as_client'];
472-
473-
if ($isClientReply) {
474-
// Handle user reply simulation
475-
return $this->addClientReply($ticket, $data, $format);
469+
// Support legacy 'as_client' parameter for backward compatibility
470+
if (isset($data['as_client']) && $data['as_client']) {
471+
$data['thread_type'] = 'email';
476472
}
477473

478-
// Continue with staff/API post handling
479-
480474
// Validate required fields
481-
if (!isset($data['thread_type']) || !in_array($data['thread_type'], ['note', 'response']))
482-
return $this->exerr(400, __('Missing or invalid "thread_type" - must be "note" or "response"'));
475+
if (!isset($data['thread_type']) || !in_array($data['thread_type'], ['note', 'response', 'email']))
476+
return $this->exerr(400, __('Missing or invalid "thread_type" - must be "note", "response", or "email"'));
483477

478+
// Handle email thread type (client/user reply simulation)
479+
if ($data['thread_type'] === 'email') {
480+
return $this->handleEmailThreadType($ticket, $data, $format);
481+
}
482+
483+
// Continue with staff/API post handling for note and response types
484484
if (!isset($data['message']) && !isset($data['cannedId']))
485485
return $this->exerr(400, __('Either message or cannedId must be provided'));
486486

@@ -642,19 +642,19 @@ function addThread($id, $format) {
642642
}
643643

644644
/**
645-
* Handle client/user reply to a ticket
645+
* Handle client/user reply to a ticket via email simulation
646646
* This simulates a user sending an email reply to a ticket
647647
*
648648
* @param Ticket $ticket The target ticket
649649
* @param array $data Request data
650650
* @param string $format Response format (json or xml)
651651
* @return void
652652
*/
653-
private function addClientReply($ticket, $data, $format) {
653+
private function handleEmailThreadType($ticket, $data, $format) {
654654
global $ost;
655655

656656
if (!isset($data['message']) || !$data['message'])
657-
return $this->exerr(400, __('Message is required for client reply'));
657+
return $this->exerr(400, __('Message is required for email thread type'));
658658

659659
// Get the user who is replying
660660
$user = null;
@@ -674,7 +674,7 @@ private function addClientReply($ticket, $data, $format) {
674674
}
675675

676676
if (!$user)
677-
return $this->exerr(500, __('Unable to determine user for client reply'));
677+
return $this->exerr(500, __('Unable to determine user for email thread type'));
678678

679679
// Format data to mimic an email message
680680
$emailData = [
@@ -727,7 +727,7 @@ private function addClientReply($ticket, $data, $format) {
727727
$result = $this->processEmail($emailData);
728728

729729
if (!$result)
730-
return $this->exerr(500, __('Failed to add client reply'));
730+
return $this->exerr(500, __('Failed to add email reply'));
731731

732732
// Get the thread entry that was just created
733733
$thread = $ticket->getThread();
@@ -748,7 +748,7 @@ private function addClientReply($ticket, $data, $format) {
748748
'ticket_id' => $ticket->getId(),
749749
'ticket_number' => $ticket->getNumber(),
750750
'thread_id' => $entry->getId(),
751-
'thread_type' => 'message', // Client messages are of type 'message'
751+
'thread_type' => 'email',
752752
'message_id' => $entry->getEmailMessageId(),
753753
'timestamp' => $entry->getCreateDate(),
754754
'current_status' => [
@@ -783,7 +783,7 @@ private function addClientReply($ticket, $data, $format) {
783783
], $format));
784784
}
785785
} catch (Exception $e) {
786-
return $this->exerr(500, __('Failed to add client reply: ') . $e->getMessage());
786+
return $this->exerr(500, __('Failed to add email reply: ') . $e->getMessage());
787787
}
788788
}
789789

setup/doc/api/api-thread.md

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ This document describes how to use the osTicket API to add new threads (replies
66

77
**Endpoint:** `POST /api/tickets/{id}/add_thread.json`
88

9-
This endpoint allows you to post new replies or internal notes to existing tickets.
9+
This endpoint allows you to post new replies, internal notes, or simulated client/user email replies to existing tickets. There are three types of thread entries you can create:
10+
11+
1. **Internal Notes** (`thread_type=note`): Staff-only notes not visible to clients
12+
2. **Staff Responses** (`thread_type=response`): Public replies from staff members
13+
3. **Client/User Replies** (`thread_type=email`): Simulates an email reply from a client/user
1014

1115
### Authentication
1216

@@ -27,17 +31,19 @@ The API accepts both JSON and XML formats. Make sure to set the appropriate Cont
2731

2832
| Parameter | Type | Description | Required |
2933
|-----------|------|-------------|----------|
30-
| thread_type | string | Type of thread entry: 'note' for internal note, 'response' for public reply | Yes |
34+
| thread_type | string | Type of thread entry: 'note' for internal note, 'response' for public reply, 'email' for client/user reply simulation | Yes |
3135
| message | string | Content of the thread entry | Yes (unless using cannedId) |
32-
| staffId | integer | ID of staff member making the post | No |
36+
| staffId | integer | ID of staff member making the post (not used for 'email' type) | No |
3337
| alert | boolean | Whether to alert participants | No (default: true) |
34-
| poster | string | Name of the poster | No (default: 'API') |
35-
| cannedId | integer | ID of canned response to use | No |
38+
| poster | string | Name of the poster (default: 'API', not used for 'email' type) | No |
39+
| cannedId | integer | ID of canned response to use (not used for 'email' type) | No |
3640
| cannedMode | string | How to use canned response: 'prepend', 'append', 'replace' | No (default: 'replace') |
3741
| cannedAttachments | boolean | Whether to include canned response attachments | No (default: false) |
38-
| signature | string | Signature selection: 'none', 'mine', 'dept' | No (default: 'none') |
39-
| includeSignature | boolean | Whether to include signature | No (default: false) |
40-
| status_id | integer | ID of the status to set the ticket to | No |
42+
| signature | string | Signature selection: 'none', 'mine', 'dept' (not used for 'email' type) | No (default: 'none') |
43+
| includeSignature | boolean | Whether to include signature (not used for 'email' type) | No (default: false) |
44+
| status_id | integer | ID of the status to set the ticket to (not used for 'email' type) | No |
45+
| userId | integer | ID of the user making the reply (only for 'email' thread type) | No (default: ticket owner) |
46+
| as_client | boolean | Legacy parameter for backward compatibility (sets thread_type to 'email' when true) | No |
4147
| attachments | array | Array of file attachments | No |
4248

4349
#### Attachment Format
@@ -127,11 +133,35 @@ Content-Type: application/json
127133
}
128134
```
129135

136+
#### Simulating a Client/User Reply (Email)
137+
138+
The 'email' thread type simulates a user sending an email reply to the ticket. This is useful for integrations that need to add replies on behalf of clients or users. Unlike the 'note' and 'response' thread types which are posted by staff members, the 'email' thread type is associated with a user (either the ticket owner or a specified user).
139+
140+
```json
141+
POST /api/tickets/123/add_thread.json
142+
X-API-Key: 184F66085DA76CDF5300FE2C6E229238
143+
Content-Type: application/json
144+
145+
{
146+
"thread_type": "email",
147+
"message": "Thank you for your response. I have another question...",
148+
"userId": 5,
149+
"attachments": [
150+
{
151+
"name": "screenshot.png",
152+
"type": "image/png",
153+
"data": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U...",
154+
"encoding": "base64"
155+
}
156+
]
157+
}
158+
```
159+
130160
### Response
131161

132162
Upon successful creation of a thread entry, the API will respond with a 201 Created status and a JSON or XML response containing details about the created thread.
133163

134-
JSON Response Example:
164+
#### JSON Response Example for Staff Entry (note/response):
135165
```json
136166
{
137167
"ticket_id": 123,
@@ -154,6 +184,34 @@ JSON Response Example:
154184
}
155185
```
156186

187+
#### JSON Response Example for Client/User Reply (email):
188+
```json
189+
{
190+
"ticket_id": 123,
191+
"ticket_number": "ABC-123-4567",
192+
"thread_id": 457,
193+
"thread_type": "email",
194+
"message_id": "<def456@osticket.com>",
195+
"timestamp": "2023-05-24 11:15:00",
196+
"current_status": {
197+
"id": 1,
198+
"name": "Open",
199+
"state": "open"
200+
},
201+
"user": {
202+
"id": 5,
203+
"name": "John Doe",
204+
"email": "johndoe@example.com"
205+
},
206+
"attachments": [
207+
{
208+
"id": 790,
209+
"name": "screenshot.png"
210+
}
211+
]
212+
}
213+
```
214+
157215
### Error Responses
158216

159217
The API will return appropriate HTTP status codes for different error conditions:

setup/doc/api/client-reply-api-docs.md

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)