Contracts and limits
The rules that apply to every method: how requests and results pair up, how failures surface, and the limits you have to design around.
Bulk-first. Every method takes List<...Request> and returns a
parallel-index List<...Result>. Single-item callers pass a one-element list
and read index [0].
Per-item outcomes. Each result carries success, errorCode,
errorMessage. A failing item does not abort the rest of the list. Branch on
errorCode, not on errorMessage text.
Call-level exception. FilesApiException is thrown only for whole-call
failures: missing custom permission, null/empty request list, unknown Callable
action, malformed Callable args. In Flow, this maps to the fault path.
Opaque fileId. A ContentDocumentId for Salesforce-stored files, the
storage object key otherwise. Pass it back verbatim; do not parse it. One id
works across all providers and all methods.
Callouts. uploadFiles, requestUploadUrls, getDownloadUrls (external),
and getFileBodies (external) perform HTTP callouts: max 100 per transaction,
cannot run after DML in the same transaction, cannot run directly in triggers
(use a Queueable). listFiles, renameFiles, relocateFiles (accept), and
getStorageReadiness are callout-free. deleteFiles performs a callout on a
last-attachment delete (the strict external byte-delete), and moveFiles performs
callouts on SharePoint, where the physical file moves too.
Error codes
Section titled “Error codes”| Constant | Meaning |
|---|---|
ERROR_ACCESS_DENIED | Missing custom permission, or no access to the record/file |
ERROR_NOT_FOUND | File or record does not exist / is not visible |
ERROR_INVALID_INPUT | Required field missing or malformed |
ERROR_UNSUPPORTED_PROVIDER | Operation unavailable on the active provider |
ERROR_FILE_TOO_LARGE | Exceeds the ~4MB Apex byte-relay cap |
ERROR_STREAMING_NOT_ENABLED | relocateFiles: large-file streaming not entitled for the org |
ERROR_RELOCATION_PENDING | A relocate handle was used as a fileId before its async copy finished |
ERROR_PROVIDER_FAILED | Downstream storage/database failure (cause in the message) |
ERROR_EXTERNAL_DELETE_FAILED | deleteFiles: the external byte-delete failed, or the file belongs to a non-active provider, so nothing changed in Salesforce |
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Base64 upload / file-body read | ~4MB binary per file (Apex heap + provider cap) |
listFiles | active provider only (opt out with includeAllProviders), max 200 files per record, createdDate DESC |
| Download URLs (external) | presigned, expire within minutes - fetch just before use |
confirmUploads | idempotent per uploadKey (replay returns the existing file) |
relocateFiles | async, no size ceiling (multipart); accept is callout-free; idempotent per (source file, record) |