link is a Daysync-owned storage key, and Daysync builds the public URL from it on read.
Every attachment flow is upload, then attach. What has changed is that there are now three ways to upload and a first-class way to attach, list and download:
POST /v1/attachments is unchanged and still supported; the newer endpoints mint the same kind of key, so a key from any upload source works with any attach path.
All endpoints require the standard authentication headers.
Upload an attachment
url and stores it in Daysync-hosted storage. Returns the storage key to use as attachment.link.
Scope: schedule.write
Body
Example
data
Upload the bytes directly
schedule.write.
Returns
{ key, link, fileName, fileSizeBytes, contentType }. key and link are the same value under two names, so you can use either the newer attach endpoint or the existing attachment.link field without renaming anything.
Get a signed upload ticket
schedule.write.
Returns
{ uploadUrl, method, headers, key, expiresInSeconds, expiresAt, contentLength, contentType }.
PUT the raw bytes to uploadUrl and send the returned headers exactly as given, then call the attach endpoint with key.
Attach an uploaded file
schedule.write.
Returns
{ fileId, entityType, entityId, key, fileName, fileSizeBytes, alreadyAttached }.
This is additive — it never touches the entity’s existing attachments — and idempotent: attaching the same key to the same entity again returns the first attachment with alreadyAttached: true, so a retry is safe.
Prefer this over re-sending an entity’s whole update body with
attachments, which replaces the entity’s attachment set. If you only want to add a file, use this endpoint.List a tour’s files
tours.read, and it also requires schedule.read, venues.read, accommodation.read and guestlist.read — the listing can surface rows from all of them.
Returns
{ items, totalCount, returnedCount, hasMore }. Each item carries fileId, key, fileName, name, description, fileSize, fileSizeBytes, contentTypeHint, entityType, entityId, entityName, dayId and createdAt.
totalCount is the total before paging, so hasMore is exact rather than inferred from a full page.
Only files you are allowed to see are listed: a file on a private item you are not on does not appear, and files on other tours are not reachable. contentTypeHint is inferred from the file name and is advisory — the download endpoint reports the authoritative type.
Chat files are not included here; use the chat file search.
Download a file
{ fileId, downloadUrl, expiresInSeconds, expiresAt, fileName, fileSizeBytes, contentType, entityType, entityId }.
Returns 404 both when the file does not exist and when you are not allowed to see it, so it cannot be used to probe for files on other tours.
Allowed content types
Applies to every upload source, includingPOST /v1/attachments.
Images (JPEG, PNG, GIF, WebP, HEIC/HEIF, BMP, TIFF, ICO) · PDF · Word, Excel, PowerPoint, RTF · plain text, CSV, Markdown, iCalendar, JSON · ZIP · audio (MP3, M4A, AAC, WAV, WebM) · video (MP4, MOV, WebM).
image/svg+xml, text/html, scripts and executables are not allowed. Anything else returns 415 and the error lists the accepted types.
Attaching the file to a resource
Use the returnedlink in the attachment (single) or attachments (array) field on a create or update:
link is required. Attachments are supported on:
- Schedule items —
attachment/attachmentson create and update (with upsert/delete semantics on update). - Venues —
attachments. - Accommodation —
attachment/attachments. - Pass types —
attachmenton create and update.
These four — schedule items, venues, accommodation and pass types — are exactly the entity kinds
POST /v1/tours/{tourId}/files/attach accepts and GET /v1/tours/{tourId}/files lists. Guest list entries are not among them: a attachment field sent on a guest-list body is not stored, so it will not appear in the file listing or be downloadable. Attach the file to the day’s schedule item or pass type instead.Always obtain
link from POST /v1/attachments. Don’t pass an external URL (e.g. your own CDN link) directly as attachment.link — Daysync treats link as one of its own storage keys and builds the public URL from it, so a foreign URL renders as a broken link.See also: Schedule, Venues, Scopes & Permissions.

