Download attachment API

This article and the rest of the API documentation in this section are written for a technical audience — integrators and developers connecting external systems to Tickiti. Familiarity with HTTP, REST, JSON and bearer-token authentication is assumed.

The download endpoint returns the bytes of a single response attachment. Discover an attachment’s id from Show ticket or List responses, then fetch its content here. To keep the API uniformly JSON, the bytes are returned base64-encoded in the response body rather than as a binary download.

Endpoint

POST /api/v1/tickets/attachment

Headers

  1. Authorization: Bearer YOUR_TOKEN — required. Token must have the tickets:read ability. A tickets:write token also works (write implies read).
  2. Content-Type: application/json — required. No Idempotency-Key is needed (this is a read).

Body

Required fields:

  1. ticket_number — the ticket the attachment belongs to, as a string (or send ticket_id, the ticket’s internal id, instead — exactly one of the two). Used to authorise the request (same queue-access check as the rest of the API) and to scope the lookup; the attachment must belong to this ticket.
  2. response_attachment_id — the attachment’s id from Show ticket / List responses.

Optional fields:

  1. intent — set to "review_ok" to confirm download of an attachment type that is review-gated (see Error responses). Has no effect on always-allowed types.
  2. offset, length — read a byte range instead of the whole file: offset is the first byte (from 0) and length the number of bytes, up to 25 MB (26,214,400 bytes) per request. Sending either one makes the request a ranged read; length defaults to that maximum. See Large files.

Example

curl -X POST https://support.sole-provider.example/api/v1/tickets/attachment \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ticket_number": "220009",
    "response_attachment_id": "14494"
  }' | jq -r '.data.content_base64' | base64 -d > attachment.bin

Successful response

The attachment’s metadata and its bytes as content_base64. mime_type is detected from the bytes; file_size is the whole file’s byte count (the base64 string is about a third larger). offset, bytes_returned and eof describe the range returned — for a whole-file read they are 0, the file size and true.

{
  "ok": true,
  "data": {
    "id": "14494",
    "response_id": "42",
    "name": "UPDD Diag.zip",
    "mime_type": "application/zip",
    "sha256": "cc9b8a68...608baf",
    "file_size": 1196962,
    "is_inline": false,
    "offset": 0,
    "bytes_returned": 1196962,
    "eof": true,
    "content_base64": "UEsDBBQAAAAIA..."
  }
}

Large files

A whole-file read returns files up to 25 MB. Read a larger file in pieces: request offset 0 with a length, append the decoded bytes, then request the next offset (the previous offset plus bytes_returned) until eof is true. Compare the assembled file against sha256 to confirm it is complete. mime_type is detected on the range that starts at offset 0; later ranges report application/octet-stream.

{
  "ticket_number": "220009",
  "response_attachment_id": "14494",
  "offset": 0,
  "length": 10485760
}

Error responses

  1. 422 validation_failed — response_attachment_id missing, neither or both of ticket_number and ticket_id, an out-of-range length, or an offset past the end of the file.
  2. 404 not_found — the ticket or attachment does not exist, the attachment does not belong to that ticket, or its stored file is missing.
  3. 403 attachment_blocked — the attachment’s file type is hard-blocked by an administrator and cannot be downloaded.
  4. 403 attachment_review_required — the file type is review-gated; resend with "intent": "review_ok" to confirm.
  5. 413 attachment_too_large — a whole-file read of a file over 25 MB. data gives the file_size and the limit; read it in ranges as described in Large files.
  6. 401 unauthenticated — bad or missing token.
  7. 403 forbidden — token lacks the tickets:read (or tickets:write) ability, the user it acts as lacks access to the ticket’s queue, or the token owner is not a staff account.

What happens server-side

  1. Tickiti locates and queue-authorises the ticket, then loads the attachment and verifies it belongs to that ticket.
  2. For non-inline attachments it applies the administrator’s file-type rules (allowed / review / blocked), honouring intent for review-gated types.
  3. It reads the stored file (attachments are content-addressed by SHA-256) — the whole file, or the requested range — and returns it base64-encoded, with a detected MIME type.