# GetUploadUrl - Advanced Documentation ## Upload Sequence Two scripts, with a direct PUT from the caller in between - the file is never embedded in a script because that is slow, the bytes become part of the prompt tokens, and it is a double hop. 1. Script one calls `FileService.GetUploadUrl(FileName, FileSize)` and returns `StorageName` and `URL` to the caller. 2. The caller PUTs the file bytes directly to `URL`, outside the sandbox, with header `Content-Type: application/octet-stream`. 3. Script two calls `SecureApi.AddClaimDocuments(ParentID, Documents)` (or `AddContactDocuments` for a contact) with a document carrying `Name`, `Type.ID`, `File.StorageName`, `File.IsURLOnly` false, and `File.ObjectSize` equal to the byte count. ## Traps - Content-Type must be `application/octet-stream` or the S3 signature check fails; the save call re-checks the object exists in S3 so the PUT must finish before script two runs; track the byte count yourself. See `SecureApi.AddClaimDocuments.md` for the document shape and per-item traps. - Avoid embedding the file as base64 inside a sandbox script. It bloats context because the file bytes become part of the prompt tokens, and it adds a slow double hop. Prefer calling `FileService.GetUploadUrl` to get the `URL`, returning it to the calling agent, and having the calling agent execute its own PUT command directly against that URL. Embedding bytes inside `ExecuteScript` is still available for cases where the calling agent has no way to issue its own PUT, but it should not be the default path. ## Script Example Script one: ```javascript async () => FileService.GetUploadUrl("invoice.pdf", 482913) ``` The caller PUTs the file bytes to the returned URL: `curl -X PUT -H "Content-Type: application/octet-stream" --data-binary @invoice.pdf ""` Script two: ```javascript async () => { const claimId = 771360, documentTypeId = 42; // supplied by the caller const documents = await SecureApi.AddClaimDocuments(claimId, [{ Name: "invoice.pdf", Type: { ID: documentTypeId }, File: { StorageName: "", IsURLOnly: false, ObjectSize: 482913 } }]); return { id: documents[0].ID, fileId: documents[0].File?.ID }; } ``` ## Cross-References | Need | Use | |------|-----| | Add multiple documents to a claim | `SecureApi.AddClaimDocuments(ParentID, Documents)` | | Add multiple documents to a contact | `SecureApi.AddContactDocuments(ParentID, Documents)` | | Create or update a claim document | `SecureApi.SaveClaimDocument(Document)` | | Create or update a contact document | `SecureApi.SaveContactDocument(Document)` |