Skip to content
Docs
opendesk.shOpen app

Messages and attachments

Read a ticket's conversation, send replies and notes, and upload attachments.

Scopes: tickets:read to read, tickets:write to send.

Method Path Description
GET /v1/tickets/{id}/messages All messages, ascending
POST /v1/tickets/{id}/messages Send a reply or add a note
GET /v1/messages/{id}/original The full original, including quoted history
POST /v1/attachments Upload a file
GET /v1/attachments/{id} Download a file
type Message = {
id: string;
ticket_id: string;
kind: "reply" | "note";
direction: "inbound" | "outbound";
author: { type: "contact" | "user" | "system" | "api"; user: UserRef | null; contact: ContactRef | null };
body_html: string;
body_text: string;
has_quoted: boolean;
subject: string;
from_email: string;
from_name: string;
to: string[];
cc: string[];
bcc: string[];
attachments: Attachment[];
delivery_status: "none" | "pending" | "sent" | "failed" | "bounced";
delivery_error: string;
reply_to: string;
auth_failed: boolean;
form_sender: string;
created_at: string;
};

body_html is sanitized before storage. For inbound email, quoted history is trimmed from the body and has_quoted is true; fetch /v1/messages/{id}/original for the full text.

Inbound email also carries what the sender checks found. reply_to is the Reply-To the message named when it differs from from_email. auth_failed is true when its From failed DMARC at a trusted receiving server: treat the message as unverified. form_sender is set when the message came through a trusted website contact form (see Mailboxes); from_email is then the visitor. The widget never receives these three.

Terminal window
curl https://api.opendesk.sh/v1/tickets/1042/messages \
-H "Authorization: Bearer od_live_..." \
-H "Content-Type: application/json" \
-d '{
"kind": "reply",
"body_html": "<p>Thanks Ana, this is fixed now.</p>",
"cc": ["[email protected]"],
"attachment_ids": ["0192f0c5-..."],
"status": "solved"
}'

status sets the ticket status in the same step. A reply on an email ticket is queued for delivery through the mailbox; watch delivery_status change from pending to sent (or failed or bounced) through the message.updated event.

Terminal window
curl https://api.opendesk.sh/v1/tickets/1042/messages \
-H "Authorization: Bearer od_live_..." \
-H "Content-Type: application/json" \
-d '{ "kind": "note", "body_html": "<p>Refund approved by finance.</p>" }'

Notes are never sent to the customer.

Upload first, then reference the id when you send:

Terminal window
curl https://api.opendesk.sh/v1/attachments \
-H "Authorization: Bearer od_live_..." \
{ "id": "0192f0c5-...", "filename": "invoice.pdf", "content_type": "application/pdf", "size_bytes": 48211, "inline": false, "url": "..." }

Uploaded attachments are unattached until a message that references them is sent. GET /v1/attachments/{id} redirects to a short-lived signed URL, or streams the file when the storage driver cannot sign. For <img> tags, where you cannot set headers, the url carries a ?token=.

Edit this page on GitHub