File Type
TailorDB File Type enables developers to attach files to records in their data model, providing seamless file management capabilities integrated with GraphQL queries and HTTP operations. This feature eliminates the need for separate file storage solutions by providing:
- Integrated file storage with TailorDB records
- Attachment file management (size, checksum, content type, timestamps)
- Permission-based access control aligned with record-level permissions
- GraphQL query integration for file metadata filtering
Basic Workflow
- Define file attachments in your schema (CUE or Terraform)
- Create records with file attachment fields
- Upload files via HTTP PUT to auto-generated URLs
- Query file info through GraphQL
- Download files via HTTP GET
- Delete files via HTTP DELETE
Schema Definition
Files are defined in the Files section (not Fields) of your type definition. Each file type field in a record has a reserved URL endpoint that serves as both the upload and download location for that specific field. This URL is automatically generated when the record is created and remains constant throughout the record's lifecycle.
<span><span style="color: var(--shiki-color-text)">Starship: tailordb.#Type </span><span style="color: var(--shiki-token-keyword)">&</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> Name: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Starship</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> Description: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">A transport craft with file attachments</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> Fields: {</span></span>
<span><span style="color: var(--shiki-color-text)"> name: {</span></span>
<span><span style="color: var(--shiki-color-text)"> Type: tailordb.#TypeString</span></span>
<span><span style="color: var(--shiki-color-text)"> Description: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Name of the starship</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> Files: {</span></span>
<span><span style="color: var(--shiki-color-text)"> blueprint: tailordb.#Attachment </span><span style="color: var(--shiki-token-keyword)">&</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> Description: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Technical blueprint file</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> thumbnail: tailordb.#Attachment </span><span style="color: var(--shiki-token-keyword)">&</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> Description: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Thumbnail image</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
GraphQL Operations
Querying File Metadata
When you query a record with file attachments, each file field returns metadata about the attached file:
<span><span style="color: var(--shiki-token-keyword)">query</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">show</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> starship(id:</span><span style="color: var(--shiki-token-comment)">"72f157d3-9f3f-40f8-9517-7627909d3580"</span><span style="color: var(--shiki-color-text)">){</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> blueprint{ url size contentType lastUploadedAt sha256sum }</span></span>
<span><span style="color: var(--shiki-color-text)"> thumbnail{ url size contentType lastUploadedAt sha256sum }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"data"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"starship"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"name"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Millennium Falcon"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"blueprint"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"url"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://app.tailor.tech/files/tailordb/galaxy/Starship/blueprint/72f157d3-9f3f-40f8-9517-7627909d3580"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"size"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">6542</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"contentType"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"image/png"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"lastUploadedAt"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"2025-08-26T10:09:13.452171+09:00"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"sha256sum"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"a6034bb72c22843b3b06e59a8a9bf85b58fec62d71e69fe9c2ab61924fc25a98"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"thumbnail"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"url"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://app.tailor.tech/files/tailordb/galaxy/Starship/thumbnail/72f157d3-9f3f-40f8-9517-7627909d3580"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"size"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"contentType"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"lastUploadedAt"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"sha256sum"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
File Metadata Properties
Property | Type | Description |
---|---|---|
url | String! | Upload/download endpoint URL |
size | Int | File size in bytes (null before upload) |
sha256sum | String | SHA256 checksum of file content |
lastUploadedAt | DateTime | Timestamp of last upload |
contentType | String | MIME type of the file |
Filtering by File Existence
You can filter records based on whether files exist:
<span><span style="color: var(--shiki-token-keyword)">query</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">getStarshipsWithFiles</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> starships(query: {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">blueprint</span><span style="color: var(--shiki-color-text)">: { </span><span style="color: var(--shiki-token-string)">exists</span><span style="color: var(--shiki-color-text)">: </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }) {</span></span>
<span><span style="color: var(--shiki-color-text)"> edges {</span></span>
<span><span style="color: var(--shiki-color-text)"> node {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> blueprint {</span></span>
<span><span style="color: var(--shiki-color-text)"> url</span></span>
<span><span style="color: var(--shiki-color-text)"> size</span></span>
<span><span style="color: var(--shiki-color-text)"> contentType</span></span>
<span><span style="color: var(--shiki-color-text)"> sha256sum</span></span>
<span><span style="color: var(--shiki-color-text)"> lastUploadedAt</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
HTTP File Operations
Upload File
Use HTTP PUT to upload a file to the auto-generated URL endpoint:
<span><span style="color: var(--shiki-token-function)">curl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-X</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">PUT</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://app.tailor.tech/files/tailordb/galaxy/Starship/cd7b898e-3779-4e3f-b484-607e92df1ebc/blueprint"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-H</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Authorization: Bearer YOUR_TOKEN"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-H</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Content-Type: application/pdf"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--data-binary</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">@blueprint.pdf</span></span>
<span></span>
Download File
Use HTTP GET to download a file from the endpoint:
<span><span style="color: var(--shiki-token-function)">curl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-X</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">GET</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://app.tailor.tech/files/tailordb/galaxy/Starship/cd7b898e-3779-4e3f-b484-607e92df1ebc/blueprint"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-H</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Authorization: Bearer YOUR_TOKEN"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-o</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">downloaded_blueprint.pdf</span></span>
<span></span>
Delete File
Use HTTP DELETE to remove a file:
<span><span style="color: var(--shiki-token-function)">curl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-X</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">DELETE</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://app.tailor.tech/files/tailordb/galaxy/Starship/cd7b898e-3779-4e3f-b484-607e92df1ebc/blueprint"</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">-H</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Authorization: Bearer YOUR_TOKEN"</span></span>
<span></span>
Limitations and Notes
- You can specify up to 10 file types in the Files section of your schema
- The maximum file size allowed for upload is 100 MB
- If you upload a file to the same endpoint, the existing file will be overwritten
- File access permissions are aligned with record-level permissions
- Each file attachment has a unique, persistent URL that remains constant throughout the record's lifecycle
- When a record is deleted, all attached files are automatically deleted as well
Related Documentation
- Fields - Learn about other field types in TailorDB
- Auto-generated API - Understand the GraphQL API structure
- Permission - Configure access control for your data