Add file attachments to a support request
Section: DOC-CP-files-data-files#upload-and-download-files.
A customer reporting a bug needs to send a recording and open it again when they return to the case. Build an attachment flow that uploads the recording, confirms it is stored, and retrieves a fresh download link whenever the customer opens it.
This recipe uses video.mp4 as an example. The same flow works for documents and other files. Your application owns the support request and associates it with Travila's returned fileId; Travila provides file storage, metadata and temporary upload/download URLs.
Before you start: use an authenticated application user, a backend credential kept off the browser, and a test file you are allowed to store. Create the /media folder through the folder recipe if your application needs a folder entry. Use the same user for every storage call in this recipe.
Build the upload interaction
Section: DOC-CP-files-data-files#uploading-files.
When the customer selects a file, your application knows its name, content type and byte size. Keep the attachment in a pending state while the upload and registration finish. Only a registered file is ready to show as an attachment.
Use a pre-signed upload for new integrations, including small files. The file bytes go directly to the returned upload destination, while your backend handles the authenticated Travila requests. This avoids sending a base64 copy through your API request.
The flow has three stages: request an upload URL, send the file bytes, then register the uploaded file. Keep the returned file ID across those stages so an interrupted request can be checked without starting another attachment.
Upload and confirm the recording
Section: DOC-CP-files-data-files#pre-signed-upload-large-files.
1. Request a destination for the selected file. Supply its actual byte size. This example declares a 50 MiB recording; use the size of your own file. The upload URL expires after the requested period.
curl -X POST https://api.travila.ai/api/v1/storage/generate-upload-url \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"folderPath": "/media",
"fileName": "video.mp4",
"contentType": "video/mp4",
"sizeBytes": 52428800,
"expiresSeconds": 3600
}'
Reference: Generate a pre-signed upload URL · Request fields.
Travila returns the file ID to keep with the pending attachment, the upload URL and the headers your uploader must send:
{
"url": "https://storage.googleapis.com/bucket/...",
"fileId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"fullPath": "/media/video.mp4",
"requiredHeaders": {
"content-type": "video/mp4",
"x-goog-content-length-range": "0,52428800"
}
}
Reference: Generate a pre-signed upload URL · Response fields.
Check that the upload finished before registering it. If a response is lost, keep the same file reference while recovering the attachment.
2. Send the selected file to that URL. Use the returned URL and every requiredHeaders value unchanged. The example below shows the values from the response above; your application must use its own response.
curl -X PUT "https://storage.googleapis.com/bucket/..." \
-H "Content-Type: video/mp4" \
-H "x-goog-content-length-range: 0,52428800" \
--data-binary @video.mp4
3. Register the uploaded file. Use the same ID, folder and name to make it available for listing and download:
curl -X POST https://api.travila.ai/api/v1/storage/register-uploaded-file \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"fileId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"folderPath": "/media",
"fileName": "video.mp4"
}'
Reference: Register a file uploaded via pre-signed URL · Request fields.
After registration succeeds, save the fileId on your application's support request and mark the attachment ready. The customer can leave and return to the case without uploading it again. If registration returns 404, the object is not yet available; check the upload before registering again.
Exact request and response fields: upload URL and registration.
Let the customer reopen the attachment
Section: DOC-CP-files-data-files#downloading-files.
When the customer opens the case, load the saved fileId from your application record. Authenticate that same user and request a fresh download URL:
curl -X POST https://api.travila.ai/api/v1/storage/generate-download-url \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"fileId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"expiresSeconds": 3600
}'
Reference: Generate a pre-signed download URL · Request fields.
{
"url": "https://storage.googleapis.com/bucket/...",
"file": {
"name": "video.mp4",
"path": "/media/video.mp4",
"sizeBytes": "52428800",
"contentType": "video/mp4"
}
}
Reference: Generate a pre-signed download URL · Response fields.
Use the returned URL to open or download the recording. The response also provides its name, type and size for your attachment row. The completed feature lets the customer reopen the stored recording after a page reload; it does not depend on keeping the original upload URL.
To offer a download with a chosen filename, use the operation's responseContentDisposition field, for example:
{
"fileId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"responseContentDisposition": "attachment; filename=my-video.mp4"
}
Reference: Generate a pre-signed download URL · Request fields.
Request a URL when it is needed and keep it out of public logs or messages. Its expiry limits the link's lifetime; anyone who possesses a still-valid URL can use it. Do not treat the URL as the permanent attachment record. See the download reference for the exact contract.
Show several attachments on the case
Section: DOC-CP-files-data-files#many-urls-at-once.
For a case with several attachments, use the saved file IDs to request download links in a batch of 1–50 files. This prepares the attachment list without a separate request for every link:
curl -X POST https://api.travila.ai/api/v1/storage/batch-generate-download-urls \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"fileIds": [
"a1b2c3d4e5f60718293a4b5c6d7e8f90",
"b2c3d4e5f60718293a4b5c6d7e8f901a"
],
"expiresSeconds": 3600
}'
Reference: Generate pre-signed download URLs for multiple files · Request fields.
{
"results": [
{
"fileId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"url": "https://storage.googleapis.com/bucket/...",
"success": true,
"contentType": "video/mp4"
},
{
"fileId": "b2c3d4e5f60718293a4b5c6d7e8f901a",
"error": "file not found"
}
]
}
Reference: Generate pre-signed download URLs for multiple files · Response fields.
Render each result independently. Show a link only when success is true and a usable URL is present. A missing success flag means false; show an unavailable attachment for that entry while leaving successful attachments usable. Match the result by fileId, not by assuming the whole batch succeeded.
The batch can return different outcomes even when its HTTP request succeeds. Use the batch reference for all fields.
Recover an attachment that cannot be opened
Section: DOC-CP-files-data-files#file-references-and-expiry.
| Customer sees | Application recovery |
|---|---|
| Upload did not finish | Keep the attachment pending. Check the transfer before attempting registration; a URL response alone did not store the file. |
| Registration response was lost | Register the same file ID again and use its existing result. |
| Download link expired | Request a new authorized link for the saved file ID. Do not ask the customer to upload the file again solely because a link expired. |
| File is no longer available or access is denied | Show that attachment as unavailable and keep other attachments usable. A saved ID does not guarantee permanent retention or access. |
| An assistant cannot read a required attachment | Explain that the file could not be used; do not present an answer as if it included that file. See conversation attachments. |
The supplied contentType is metadata. It does not independently verify the bytes or establish that a file is safe to display. Apply the file handling rules your application needs before rendering customer content.
Move an existing inline uploader to this flow
Section: DOC-CP-files-data-files#inline-upload-small-files.
If your application already sends base64 content to upload-file, replace that path with the three stages above and keep associating the resulting file ID with the same application record. Inline upload is deprecated; it is not the recommended path for a new attachment feature. Its exact legacy contract remains in the inline upload reference.
Complete one upload and reopen it through a fresh download link before switching the rest of your application. Existing registered files can continue to be retrieved by their IDs.
Document ID: DOC-CP-files-data-files. Section identities and revisions.