Files

A file is a document your team has exchanged by email. Carom groups every attachment with the same file name into one file, so a proposal sent back and forth three times is one file with three attachments, each tied to the message that carried it. Use this resource to find documents by type, sender, or the people involved, name and describe them, and download any attachment.

A file is visible to your key when a message it was attached to is visible, or when someone shared the file with your key’s user. Files come only from mail; the API can’t create them. The one endpoint here that accepts bytes, Upload an image, stores avatars for contacts and logos for organizations, and its uploads never become files.

#The file object

Returned by every file endpoint. List responses add shared_with_me; retrieving or updating a single file adds its tasks, comments, and shares.

Attributes

  • idstring · uuid

    Unique identifier for the file.

  • namestring · nullable

    Display name. Starts as the name the file was first attached under; change it with Update a file.

  • file_namestring · nullable

    The file name as attached. Carom groups attachments by this value, and downloads use it.

  • extensionstring · nullable

    The part of file_name after the last dot, such as pdf.

  • descriptionstring · nullable

    Free-form notes about the file.

  • attachment_countinteger · nullable

    How many times the file has been attached to a message.

  • pinnedboolean · nullable

    Whether your key’s user has pinned this file.

  • first_sent_atstring · date-time · nullable

    When the earliest attachment was sent.

  • last_sent_atstring · date-time · nullable

    When the most recent attachment was sent. The default sort for List files.

  • sender_email_addressesarray of strings

    Every address that sent a message carrying the file.

  • recipient_email_addressesarray of strings

    Every address those messages went to, including cc and bcc.

  • participantsobject

    Keyed by each sender and recipient address. The value is the contact with that address when one is visible to your key, and null otherwise.

  • attachmentsarray of objects · nullable

    Each time the file was attached to a message visible to your key. Pass an attachment’s id to Download an attachment or Create a download URL.

    Show 12 child attributesHide child attributes
    • idstring · uuid
    • file_idstring · uuid · nullable
    • sizeinteger · nullable

      Size in bytes, as the mail provider reported it.

    • content_typestring · nullable

      The MIME type the message declared.

    • inlineboolean · nullable

      True for an image embedded in the body of the message rather than attached to it.

    • content_idstring · nullable

      The MIME Content-ID the message’s HTML body uses to reference this attachment as cid:content_id.

    • decorativeboolean

      True for a signature logo, a tracking pixel, or an image that appears only in quoted earlier messages, rather than a file someone meant to send. List files and Count files leave these out unless you pass include_decorative=true.

    • sent_atstring · date-time · nullable
    • sender_email_addressstring · nullable
    • recipient_email_addressesarray of strings
    • threadobject · nullable

      The thread the message belongs to, with its id, subject, snippet, participant_email_addresses, participant_names, created_at, and updated_at. participant_names maps each address to the display name in the mail headers, or null when the headers carried none.

    • messageobject · nullable

      The message that carried the attachment, with its id and snippet.

  • tagsarray of tags · nullable

    Tags applied to this file.

  • shared_with_meboolean

    List responses only. True when the file was shared with your key’s user directly or through a group.

The file object
{
  "id": "2f74c67f-f5c9-4c1b-9dfc-15095b59207f",
  "name": "Wildgrove renewal proposal",
  "file_name": "Wildgrove-Renewal-2027.pdf",
  "extension": "pdf",
  "description": "Final pricing for the 14 existing properties. Oakland is priced separately.",
  "attachment_count": 2,
  "pinned": true,
  "first_sent_at": "2026-09-02T22:14:08.614Z",
  "last_sent_at": "2026-09-09T16:31:45.287Z",
  "sender_email_addresses": ["dana@harborline.example", "priya@wildgrove.example"],
  "recipient_email_addresses": ["priya@wildgrove.example", "dana@harborline.example"],
  "participants": {
    "dana@harborline.example": null,
    "priya@wildgrove.example": {
      "id": "1f3c9a52-7b0e-4d4a-9c1e-2a6f0d8b3e41",
      "name": "Priya Natarajan",
      …
    }
  },
  "attachments": [
    {
      "id": "522c93e3-bf69-4a33-9747-f39a51034d6e",
      "file_id": "2f74c67f-f5c9-4c1b-9dfc-15095b59207f",
      "size": 482117,
      "content_type": "application/pdf",
      "inline": false,
      "content_id": null,
      "decorative": false,
      "sent_at": "2026-09-09T16:31:45.287Z",
      "sender_email_address": "dana@harborline.example",
      "recipient_email_addresses": ["priya@wildgrove.example"],
      "thread": {
        "id": "f06a7a5f-4a85-423e-8adc-1c26a059eab3",
        "subject": "Renewal proposal, revised",
        …
      },
      "message": {
        "id": "5fa35c09-d87c-4ff8-99e5-3e078b10267a",
        "snippet": "Revised numbers attached. The Oakland pricing is in a separate sheet."
      }
    },
    …
  ],
  "tags": [
    {
      "id": "0f1e2d3c-4b5a-4968-8776-655443322110",
      "name": "Customer",
      "color": "#66b185"
    }
  ]
}
get/files Read key

#List files

Returns the files visible to your key, 50 per page, most recently sent first. Filter by name, type, sender, participant, dates, tags, or the records involved, and page through the result with a cursor.

A contact_id, organization_id, or space_id must name a record visible to your key. When that record has no email addresses whose correspondence is visible to your key, the list is empty.

By default the list leaves out decorative attachments: signature logos, tracking pixels, and images that appear only in quoted earlier messages. A file whose every attachment is decorative isn’t listed, and the counts, sizes, and dates of the other files cover only their other attachments. Pass include_decorative=true to include them.

Query parameters

  • querystring

    Match against name and file_name. Up to 500 characters.

  • typestring

    Only files with this extension, such as pdf, without the dot.

  • senderstring

    Only files sent from this email address.

  • participantstring

    Only files sent from or to this email address, including cc and bcc.

  • first_sent_beforestring

    An ISO 8601 date. Only files first sent before it.

  • last_sent_afterstring

    An ISO 8601 date. Only files most recently sent after it.

  • scopestring

    Restrict by which mail a file came through. Takes one of the values below or a mailbox id: personal, your key’s user’s primary mailbox; subscribed, every mailbox they subscribe to; a mailbox id, mail that reached that mailbox. shared returns files shared with your key’s user, the same as slice=shared. all applies no restriction, the same as omitting the parameter.

    personalsubscribedsharedall
  • slicestring

    tasked: files with a task that belongs to your key’s user. shared: files shared with your key’s user, directly or through a group. pinned: files your key’s user has pinned.

    taskedsharedpinned
  • contact_idstring · uuid

    Only files sent from or to this contact’s email addresses.

  • organization_idstring · uuid

    Only files sent from or to people at this organization.

  • space_idstring · uuid

    Only files in this space.

  • tagsstring

    Comma-separated tag ids, at most 50.

  • tag_operatorstringdefault any

    Whether a file must carry any of the given tags, or all of them.

    anyall
  • include_decorativebooleandefault false

    Include decorative attachments, and the files that have only those.

  • sortstringdefault last_sent_at

    Field to sort by. size is the largest attachment’s size.

    last_sent_atnamesizeattachment_count
  • orderstring

    Defaults to asc for name and desc for the other sorts.

    ascdesc
  • next_cursorstring

    Opaque token from the previous page’s page_info.next_cursor. Omit to start from the beginning. See Pagination.

Returns

  • collectionobject

    A page of files and the cursor to the next one.

    Show 6 child attributesHide child attributes
    • recordsarray of files

      Up to 50 files in the requested order.

    • page_infopage info

      Where this page sits in the full list. Pass next_cursor back to fetch the next page while has_more_after is true.

    • sortstring · nullable

      The sort you passed, or null when you used the default.

    • orderstring · nullable

      The order you passed, or null when you used the default.

    • filtersobject · nullable

      The filters that were applied, echoed back.

    • slice_keystring · nullable

      The slice that was applied.

Errors

  • 400invalid_requestA parameter is malformed, for example a date that isn’t ISO 8601 or more than 50 tag ids.
  • 400invalid_cursorThe cursor is unreadable, or came from another list or sort.
  • 400unsupported_cursor_directionYou passed prev_cursor. This list pages forward only.
  • 404record_not_foundcontact_id, organization_id, or space_id names a record that isn’t visible to your key.
get/files
curl "https://api.carom.io/files?type=pdf&participant=priya@wildgrove.example" \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "collection": {
    "records": [
      {
        "id": "2f74c67f-f5c9-4c1b-9dfc-15095b59207f",
        "name": "Wildgrove renewal proposal",
        "file_name": "Wildgrove-Renewal-2027.pdf",
        "attachment_count": 2,
        "last_sent_at": "2026-09-09T16:31:45.287Z",
        "shared_with_me": false,
        …
      },
      {
        "id": "b826560b-7df7-4790-bc71-5e994767fb84",
        "name": "Oakland site survey",
        "file_name": "Oakland-Site-Survey.pdf",
        "attachment_count": 1,
        "last_sent_at": "2026-09-04T19:05:22.539Z",
        "shared_with_me": false,
        …
      }
    ],
    "page_info": {
      "limit": 50,
      "next_cursor": null,
      "prev_cursor": null,
      "has_more_after": false,
      "has_more_before": false
    },
    "sort": null,
    "order": null,
    "filters": {
      "type": "pdf",
      "participant": "priya@wildgrove.example"
    },
    "slice_key": null
  }
}
get/files/{id} Read key

#Retrieve a file

Returns a single file with its attachments, participants, and tags, plus the open tasks, comments, and shares attached to it.

Path parameters

  • idstring · uuidrequired

    The file’s id.

Returns

The file object, wrapped in file, without shared_with_me and with these additional attributes.

  • tasksarray of tasks · nullable

    Incomplete tasks attached to the file that are visible to your key.

  • commentsarray of comments · nullable

    Comments your team has left on the file.

  • sharesarray of shares · nullable

    Who the file has been shared with, and how.

Errors

  • 404record_not_foundNo file with that id is visible to your key.
get/files/{id}
curl https://api.carom.io/files/2f74c67f-f5c9-4c1b-9dfc-15095b59207f \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "file": {
    "id": "2f74c67f-f5c9-4c1b-9dfc-15095b59207f",
    "name": "Wildgrove renewal proposal",
    "file_name": "Wildgrove-Renewal-2027.pdf",
    …
    "tasks": [
      {
        "id": "7c6dc498-83ce-44ae-8afd-8b1a3641ed8f",
        "description": "Send Priya the renewal redline before the call",
        "due": "2026-09-21",
        …
      }
    ],
    "comments": [],
    "shares": []
  }
}
patch/files/{id} Write key

#Update a file

Changes a file’s display name or description and leaves the rest alone. Anyone who can see a file can edit these two fields, and everyone who can see it sees the change. The attachments and their file names are not affected.

Path parameters

  • idstring · uuidrequired

Request body application/json

  • fileobjectrequired
    Show 2 child attributesHide child attributes
    • namestring · nullable

      New display name.

    • descriptionstring · nullable

      Free-form notes about the file.

Returns

The updated file, wrapped in file, in the same shape as Retrieve a file.

Errors

  • 400invalid_requestThe body has no file object, or a field isn’t a string.
  • 404record_not_foundNo file with that id is visible to your key.
patch/files/{id}
curl -X PATCH https://api.carom.io/files/2f74c67f-f5c9-4c1b-9dfc-15095b59207f \
  -H "Authorization: Bearer $CAROM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": {
      "name": "Wildgrove renewal proposal",
      "description": "Final pricing for the 14 existing properties. Oakland is priced separately."
    }
  }'
Response200
{
  "file": {
    "id": "2f74c67f-f5c9-4c1b-9dfc-15095b59207f",
    "name": "Wildgrove renewal proposal",
    "file_name": "Wildgrove-Renewal-2027.pdf",
    "description": "Final pricing for the 14 existing properties. Oakland is priced separately.",
    …
  }
}
get/files/count Read key

#Count files

Counts the files that List files would return for the same filters, without fetching them. Counting stops at cap when you give one, which keeps the call fast on large accounts.

Query parameters

  • query, type, sender, participant, first_sent_before, last_sent_after, scope, slice, contact_id, organization_id, space_id, tags, tag_operator, include_decorative

    As on List files.

  • capinteger

    Stop counting at this many. When the cap is reached, total equals cap and exact is false.

Returns

  • countcount
    Show 4 child attributesHide child attributes
    • totalinteger
    • exactboolean

      False when counting stopped at cap.

    • cappedboolean

      True when counting stopped at cap.

    • capinteger · nullable

      The cap that was applied, or null.

Errors

  • 400invalid_requestA parameter is malformed, for example a date that isn’t ISO 8601.
  • 404record_not_foundcontact_id, organization_id, or space_id names a record that isn’t visible to your key.
get/files/count
curl "https://api.carom.io/files/count?type=pdf&cap=1000" \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "count": {
    "total": 263,
    "exact": true,
    "capped": false,
    "cap": 1000
  }
}
get/files/{id}/download Read key

#Download an attachment

Returns the bytes of one attachment of the file. Attachments of the same file can differ, since each is whatever was attached to its message, so name the one you want with attachment_id.

Downloading an attachment larger than 25 MB can fail with 413 source_too_large.

Path parameters

  • idstring · uuidrequired

    The file’s id.

Query parameters

  • attachment_idstring · uuidrequired

    An id from the file’s attachments.

Returns

The raw bytes. Content-Type is the type the bytes themselves show when Carom recognizes them (common image formats, PDF, HTML, and SVG), whatever the file’s extension says. Otherwise it is chosen from the file’s extension, or is application/octet-stream when the extension is unknown. Content-Disposition is attachment with the file’s file_name, including a UTF-8 filename* form for names outside ASCII.

Errors

  • 400invalid_requestattachment_id is missing.
  • 404record_not_foundNo attachment with that attachment_id is visible to your key, or it belongs to a different file.
  • 413source_too_largeThe attachment is larger than 25 MB and can’t be retrieved.
  • 502source_fetch_failedThe mail provider didn’t return the attachment.
  • 502source_handle_unavailableThe attachment can no longer be retrieved from the mail provider.
  • 502storage_unavailableCarom’s file storage didn’t respond. Retry later.
get/files/{id}/download
curl -OJ "https://api.carom.io/files/2f74c67f-f5c9-4c1b-9dfc-15095b59207f/download?attachment_id=522c93e3-bf69-4a33-9747-f39a51034d6e" \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response headers200
Content-Type: application/pdf
Content-Disposition: attachment; filename="Wildgrove-Renewal-2027.pdf"; filename*=UTF-8''Wildgrove-Renewal-2027.pdf
post/attachments/{id}/presigned_urls Read key

#Create a download URL

Returns a temporary URL for one attachment that can be fetched without an API key, valid for one hour. Use it to hand a download to a browser or another service instead of proxying the bytes through your own server. Anyone who has the URL can download the attachment until it expires.

The 25 MB limit on Download an attachment applies here too. The URL opens most types in the browser; HTML, SVG, and XML files are served as downloads instead, including an HTML or SVG file with another extension.

Path parameters

  • idstring · uuidrequired

    An attachment’s id, from a file’s attachments.

Returns

  • presigned_urlstring

    The download URL, a signed URL that needs no API key.

  • expires_atstring · date-time

    When the URL stops working, one hour after the request.

  • filenamestring

    The file’s file_name.

  • content_typestring

    The type the URL serves, chosen as on Download an attachment: from the bytes when Carom recognizes them, otherwise from the file’s extension.

Errors

  • 404record_not_foundNo attachment with that id is visible to your key.
  • 413source_too_largeThe attachment is larger than 25 MB and can’t be retrieved.
  • 502source_fetch_failedThe mail provider didn’t return the attachment.
  • 502source_handle_unavailableThe attachment can no longer be retrieved from the mail provider.
  • 502storage_unavailableCarom’s file storage didn’t respond. Retry later.
post/attachments/{id}/presigned_urls
curl -X POST https://api.carom.io/attachments/522c93e3-bf69-4a33-9747-f39a51034d6e/presigned_urls \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "presigned_url": "https://files.carom.io/…?signature=…",
  "expires_at": "2026-09-19T15:04:10.771Z",
  "filename": "Wildgrove-Renewal-2027.pdf",
  "content_type": "application/pdf"
}
post/uploads Write key

#Upload an image

Stores an image to use as a contact’s avatar or an organization’s logo. An upload is not a file: it never appears in List files, and the only thing you can do with it is attach it to a record. Upload with kind set to avatar, then pass the returned id as avatar_upload_id when you create or update a contact; for a logo, pass it as logo_upload_id when you create or update an organization.

Each upload can be attached once, only by the user who uploaded it, and only to a record of its kind. Carom deletes uploads that are still unattached 24 hours after they were made.

Carom checks and re-encodes every image. It accepts JPEG, PNG, WebP, GIF, and HEIC files up to 10 MB and 8000 pixels on each side, shrinks the image to at most 512 pixels on its long edge for an avatar or 1024 for a logo, and saves it as PNG if it has transparency and JPEG otherwise. Metadata such as the location a photo was taken is removed. Animated images keep their first frame.

Request body multipart/form-data

  • kindstringrequired

    What the image is for.

    avatarlogo
  • filebinaryrequired

    The image, as a file part. Carom identifies the format from the bytes and ignores the declared type and file name.

Returns

HTTP 201 and the upload, wrapped in upload.

  • idstring · uuid

    Pass this as avatar_upload_id or logo_upload_id.

  • source_urlstring

    Where the processed image is served, for a preview.

Errors

  • 400invalid_requestkind is missing or not avatar or logo, or file isn’t a file part.
  • 413upload_too_largeThe image is larger than 10 MB.
  • 422unsupported_image_typeThe bytes aren’t a JPEG, PNG, WebP, GIF, or HEIC image Carom can read.
  • 422image_dimensions_too_largeThe image is wider or taller than 8000 pixels.
  • 422image_decode_failedThe image could not be re-encoded.
  • 502storage_unavailableCarom’s file storage didn’t accept the image. Retry later.
post/uploads
curl https://api.carom.io/uploads \
  -H "Authorization: Bearer $CAROM_API_KEY" \
  -F "kind=avatar" \
  -F "file=@priya.jpg"
Response201
{
  "upload": {
    "id": "e9525330-ab78-4b0d-83ba-f6bc669d7ed4",
    "source_url": "https://usercontent.carom.io/3f9c1a7e5b2d4086a1c7e9f0b3d5a8c2.jpg"
  }
}