Browse docs

Downloading files

Overview

Every message in a ticket payload carries its files in two arrays. attachments holds the files that were sent alongside the message, and inline_images holds the images that appear inside the message body. Both entries carry a url and a download_url that you can fetch with your API token.

{
    "id": 101,
    "type": "inbound",
    "body_html": "<p>Here is what I see:</p><p><img src=\"https://there-there.app/api/attachments/01hx9f3k2q...\"></p>",
    "attachments": [
        {
            "id": 44,
            "name": "invoice.pdf",
            "mime_type": "application/pdf",
            "size": 84213,
            "url": "https://there-there.app/api/attachments/01hx9f3k2p...",
            "download_url": "https://there-there.app/api/attachments/01hx9f3k2p...?download=1"
        }
    ],
    "inline_images": [
        {
            "id": 45,
            "name": "screenshot.png",
            "mime_type": "image/png",
            "size": 12044,
            "content_id": "shot1",
            "url": "https://there-there.app/api/attachments/01hx9f3k2q...",
            "download_url": "https://there-there.app/api/attachments/01hx9f3k2q...?download=1"
        }
    ]
}

Use the URLs as they are returned rather than building them yourself. The same file is also reachable from the There There app on a different URL, and which one you get back depends on the credential that fetched the payload. The <img> tags in body_html point at the same URL as the matching inline_images entry, so an HTML body you fetched with an API token stays renderable.

Fetch a file

GET /api/attachments/{media_ulid}

Example Request

curl https://there-there.app/api/attachments/01hx9f3k2p... \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -o invoice.pdf

The response is the file itself, with its own Content-Type. Add ?download=1 to get a Content-Disposition: attachment header, which is what download_url does. Without it the file is served inline, which is what a browser or an image renderer wants.

Files stored on object storage are served through a redirect to a short lived storage URL, so follow redirects (curl -L, or the default in most HTTP clients).

Access rules

A file inherits the access rules of the ticket it hangs on. A token that cannot read the ticket cannot read its files either, and a token restricted to a set of channels only reaches the files of tickets in those channels. Attachments on brain articles follow the access rules of their brain.

You do not have to send an X-Workspace-Id header on this endpoint. The workspace is derived from the file itself.

Errors

Status Meaning
403 The token may not access the channel the file's ticket belongs to
404 No such file, or it lives in a workspace this token cannot reach