# Support tickets — PapaProxy.net API reference

Page: https://papaproxy.net/developers/reference/support-tickets.php
Last updated: November 9, 2026
Base URL: `https://papaproxy.net/account_new`. Authentication and conventions: https://papaproxy.net/developers/reference/

### List support tickets

`GET /api/v1/customer/tickets`

- Access: API key required · scope `tickets:read`

List your support tickets, newest first.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `offset (query)` | integer | no | Number of items to skip. · Default: `0` |
| `limit (query)` | integer | no | Page size. · Default: `50` |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/tickets" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/tickets",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/tickets", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/tickets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/tickets", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Paginated ticket list.

Example response:

```json
{
  "tickets": [
    {
      "id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
      "customer_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
      "subject": "Proxy question",
      "status": "closed",
      "service_id": null,
      "last_message_at": "2026-11-07T14:09:52.876903Z",
      "created_at": "2026-11-07T14:09:52.876903Z",
      "updated_at": "2026-11-07T14:24:19.868992Z"
    }
  ],
  "total": 11,
  "offset": 0,
  "limit": 1
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `tickets` | array of object | yes |  |
| `tickets[].id` | string (uuid) | yes | Unique ID. |
| `tickets[].customer_id` | string (uuid), nullable | yes | ID of your account. |
| `tickets[].subject` | string | yes | Ticket subject. |
| `tickets[].status` | string | yes | Ticket status. · One of: `open`, `in_progress`, `waiting`, `customer_replied`, `closed` |
| `tickets[].service_id` | string (uuid), nullable | yes | ID of the service. |
| `tickets[].last_message_at` | string (date-time), nullable | yes | When the last message was posted (ISO 8601, UTC). |
| `tickets[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `tickets[].updated_at` | string (date-time), nullable | yes | When it was last changed (ISO 8601, UTC). |
| `total` | integer | yes | Total number of items across all pages. |
| `offset` | integer | no | Number of items skipped. · Default: `0` |
| `limit` | integer | no | Page size. · Default: `50` |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `tickets:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: tickets:read"}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Open a support ticket

`POST /api/v1/customer/tickets`

- Access: API key required · scope `tickets:write`

Create a new support ticket.

Request body (JSON):

| Field | Type | Required | Description |
|---|---|---|---|
| `subject` | string | yes | Ticket subject. · Min length: 1 · Max length: 500 |
| `message` | string | yes | Min length: 1 · Max length: 10000 |
| `service_id` | string (uuid), nullable | no | ID of the service. |
| `attachments` | array of object | no | Attached files. · Max items: 5 |
| `attachments[].filename` | string | yes | File name. · Min length: 1 · Max length: 255 |
| `attachments[].content_type` | string | yes | MIME type of the file. · Min length: 1 · Max length: 127 |
| `attachments[].data_base64` | string | yes | Min length: 1 · Max length: 28000000 |

Request examples:

cURL:

```bash
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/tickets" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subject": "Proxy question", "message": "Two IPs in my US package time out on HTTPS. Could you check them?"}'
```

Python:

```python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/tickets",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "subject": "Proxy question",
        "message": "Two IPs in my US package time out on HTTPS. Could you check them?"
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/tickets", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "subject": "Proxy question",
    "message": "Two IPs in my US package time out on HTTPS. Could you check them?"
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/tickets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'subject' => 'Proxy question',
        'message' => 'Two IPs in my US package time out on HTTPS. Could you check them?'
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/tickets", strings.NewReader(`{"subject": "Proxy question", "message": "Two IPs in my US package time out on HTTPS. Could you check them?"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `201` — Ticket with full message history.

Example response:

```json
{
  "id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
  "customer_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
  "subject": "Proxy question",
  "status": "closed",
  "service_id": null,
  "last_message_at": "2026-11-07T14:09:52.876903Z",
  "created_at": "2026-11-07T14:09:52.876903Z",
  "updated_at": "2026-11-07T14:24:19.868992Z",
  "messages": [
    {
      "id": "101deaaa-d993-5b5a-8826-13a213959f27",
      "ticket_id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
      "author_kind": "customer",
      "author_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
      "message": "Hi! Two IPs in my US package time out on HTTPS. Could you check them?",
      "created_at": "2026-11-07T14:09:52.876903Z",
      "attachments": [],
      "detected_lang": null,
      "translated_body": null,
      "translation_target": null
    }
  ]
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string (uuid) | yes | Unique ID. |
| `customer_id` | string (uuid), nullable | yes | ID of your account. |
| `subject` | string | yes | Ticket subject. |
| `status` | string | yes | Ticket status. · One of: `open`, `in_progress`, `waiting`, `customer_replied`, `closed` |
| `service_id` | string (uuid), nullable | yes | ID of the service. |
| `last_message_at` | string (date-time), nullable | yes | When the last message was posted (ISO 8601, UTC). |
| `created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `updated_at` | string (date-time), nullable | yes | When it was last changed (ISO 8601, UTC). |
| `messages` | array of object | yes |  |
| `messages[].id` | string (uuid) | yes | Unique ID. |
| `messages[].ticket_id` | string (uuid) | yes |  |
| `messages[].author_kind` | string | yes |  |
| `messages[].author_id` | string (uuid), nullable | yes |  |
| `messages[].message` | string | yes |  |
| `messages[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].attachments` | array of object | no | Attached files. |
| `messages[].attachments[].id` | string (uuid) | yes | Unique ID. |
| `messages[].attachments[].message_id` | string (uuid) | yes |  |
| `messages[].attachments[].uploader_type` | string | yes |  |
| `messages[].attachments[].filename` | string | yes | File name. |
| `messages[].attachments[].content_type` | string | yes | MIME type of the file. |
| `messages[].attachments[].size` | integer | yes |  |
| `messages[].attachments[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].detected_lang` | string, nullable | no |  |
| `messages[].translated_body` | string, nullable | no |  |
| `messages[].translation_target` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `tickets:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: tickets:write"}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Get a support ticket

`GET /api/v1/customer/tickets/{ticket_id}`

- Access: API key required · scope `tickets:read`

Get a single ticket with its full message history.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `ticket_id (path)` | string (uuid) | yes | ID of the ticket. |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Ticket with full message history.

Example response:

```json
{
  "id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
  "customer_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
  "subject": "Proxy question",
  "status": "closed",
  "service_id": null,
  "last_message_at": "2026-11-07T14:09:52.876903Z",
  "created_at": "2026-11-07T14:09:52.876903Z",
  "updated_at": "2026-11-07T14:24:19.868992Z",
  "messages": [
    {
      "id": "101deaaa-d993-5b5a-8826-13a213959f27",
      "ticket_id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
      "author_kind": "customer",
      "author_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
      "message": "Hi! Two IPs in my US package time out on HTTPS. Could you check them?",
      "created_at": "2026-11-07T14:09:52.876903Z",
      "attachments": [],
      "detected_lang": null,
      "translated_body": null,
      "translation_target": null
    }
  ]
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string (uuid) | yes | Unique ID. |
| `customer_id` | string (uuid), nullable | yes | ID of your account. |
| `subject` | string | yes | Ticket subject. |
| `status` | string | yes | Ticket status. · One of: `open`, `in_progress`, `waiting`, `customer_replied`, `closed` |
| `service_id` | string (uuid), nullable | yes | ID of the service. |
| `last_message_at` | string (date-time), nullable | yes | When the last message was posted (ISO 8601, UTC). |
| `created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `updated_at` | string (date-time), nullable | yes | When it was last changed (ISO 8601, UTC). |
| `messages` | array of object | yes |  |
| `messages[].id` | string (uuid) | yes | Unique ID. |
| `messages[].ticket_id` | string (uuid) | yes |  |
| `messages[].author_kind` | string | yes |  |
| `messages[].author_id` | string (uuid), nullable | yes |  |
| `messages[].message` | string | yes |  |
| `messages[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].attachments` | array of object | no | Attached files. |
| `messages[].attachments[].id` | string (uuid) | yes | Unique ID. |
| `messages[].attachments[].message_id` | string (uuid) | yes |  |
| `messages[].attachments[].uploader_type` | string | yes |  |
| `messages[].attachments[].filename` | string | yes | File name. |
| `messages[].attachments[].content_type` | string | yes | MIME type of the file. |
| `messages[].attachments[].size` | integer | yes |  |
| `messages[].attachments[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].detected_lang` | string, nullable | no |  |
| `messages[].translated_body` | string, nullable | no |  |
| `messages[].translation_target` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `tickets:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: tickets:read"}
  ```

- `404` — Ticket not found, or it doesn't belong to your account.
- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Reply to a support ticket

`POST /api/v1/customer/tickets/{ticket_id}/reply`

- Access: API key required · scope `tickets:write`

Reply to an existing ticket. Closed tickets can't receive replies: the response is `400` (`Cannot reply to a closed ticket. Reopen it first.`).

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `ticket_id (path)` | string (uuid) | yes | ID of the ticket. |

Request body (JSON):

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | Min length: 1 · Max length: 10000 |
| `attachments` | array of object | no | Attached files. · Max items: 5 |
| `attachments[].filename` | string | yes | File name. · Min length: 1 · Max length: 255 |
| `attachments[].content_type` | string | yes | MIME type of the file. · Min length: 1 · Max length: 127 |
| `attachments[].data_base64` | string | yes | Min length: 1 · Max length: 28000000 |

Request examples:

cURL:

```bash
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6/reply" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "Thanks, both IPs work now."}'
```

Python:

```python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6/reply",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "message": "Thanks, both IPs work now."
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6/reply", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "message": "Thanks, both IPs work now."
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6/reply');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'message' => 'Thanks, both IPs work now.'
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/tickets/3fa85f64-5717-4562-b3fc-2c963f66afa6/reply", strings.NewReader(`{"message": "Thanks, both IPs work now."}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Ticket with full message history.

Example response:

```json
{
  "id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
  "customer_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
  "subject": "Proxy question",
  "status": "closed",
  "service_id": null,
  "last_message_at": "2026-11-07T14:09:52.876903Z",
  "created_at": "2026-11-07T14:09:52.876903Z",
  "updated_at": "2026-11-07T14:24:19.868992Z",
  "messages": [
    {
      "id": "101deaaa-d993-5b5a-8826-13a213959f27",
      "ticket_id": "25d98664-5d50-59ee-974a-d7dd4773bde9",
      "author_kind": "customer",
      "author_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
      "message": "Hi! Two IPs in my US package time out on HTTPS. Could you check them?",
      "created_at": "2026-11-07T14:09:52.876903Z",
      "attachments": [],
      "detected_lang": null,
      "translated_body": null,
      "translation_target": null
    }
  ]
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string (uuid) | yes | Unique ID. |
| `customer_id` | string (uuid), nullable | yes | ID of your account. |
| `subject` | string | yes | Ticket subject. |
| `status` | string | yes | Ticket status. · One of: `open`, `in_progress`, `waiting`, `customer_replied`, `closed` |
| `service_id` | string (uuid), nullable | yes | ID of the service. |
| `last_message_at` | string (date-time), nullable | yes | When the last message was posted (ISO 8601, UTC). |
| `created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `updated_at` | string (date-time), nullable | yes | When it was last changed (ISO 8601, UTC). |
| `messages` | array of object | yes |  |
| `messages[].id` | string (uuid) | yes | Unique ID. |
| `messages[].ticket_id` | string (uuid) | yes |  |
| `messages[].author_kind` | string | yes |  |
| `messages[].author_id` | string (uuid), nullable | yes |  |
| `messages[].message` | string | yes |  |
| `messages[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].attachments` | array of object | no | Attached files. |
| `messages[].attachments[].id` | string (uuid) | yes | Unique ID. |
| `messages[].attachments[].message_id` | string (uuid) | yes |  |
| `messages[].attachments[].uploader_type` | string | yes |  |
| `messages[].attachments[].filename` | string | yes | File name. |
| `messages[].attachments[].content_type` | string | yes | MIME type of the file. |
| `messages[].attachments[].size` | integer | yes |  |
| `messages[].attachments[].created_at` | string (date-time) | yes | When it was created (ISO 8601, UTC). |
| `messages[].detected_lang` | string, nullable | no |  |
| `messages[].translated_body` | string, nullable | no |  |
| `messages[].translation_target` | string, nullable | no |  |

- `400` — The ticket is closed.

  Example:

  ```json
  {"detail": "Cannot reply to a closed ticket. Reopen it first."}
  ```

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `tickets:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: tickets:write"}
  ```

- `404` — Ticket not found, or it doesn't belong to your account.
- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```

