file param should have the following attributes
uploadFileStreamToAzureAsync and uploadFileBufferToAzureAsync
omitPrefix (boolean, optional): When set to true, the uploaded file’s name will be set to the original name or the provided filename without a timestamp prefix. If set to false, the filename will include a timestamp prefix.
Public vs private files
Every application has an access-level switch (multimediaAccessLevel, public or private) that controls whether new multimedia files are stored publicly (direct, non-expiring URL) or privately (isolated container, only accessible through a short-lived signed URL). This switch is set at the application level, not per file — existing apps keep working exactly as before (public) until an app owner opts into private.
When a hook uploads a file, it can let the app’s switch decide, or explicitly force one behavior with the accessLevel parameter — the last argument of the upload/delete functions. Accepted values are "public" and "private"; anything else (including omitting it) falls back to the app’s switch.
If the app’s switch is set to
private, requesting accessLevel: "public" from a hook will not make the file public unless the app owner has also enabled the separate “allow public override” setting for that app. This is a security floor: it stops an unauthenticated caller (Codenull’s multimedia upload endpoint doesn’t require login, since some anonymous features depend on it) from forcing a file that should stay private into a public, permanent URL. A hook can always tighten access to private on an otherwise-public app — that never needs any extra setting.Response shape for private files
A private upload does not return aurl — there is no permanent public URL for a private file. Instead you get a path (the blob’s location inside the private container) and accessLevel: "private":
path if you need to reference the file later (e.g. to delete it). To let a user view/download a private file, request a short-lived signed URL through GET /api/multimedia/sas?path=<path> rather than trying to build a URL by hand — private files live in a container with no anonymous/direct access. The signed URL expires 2 minutes after it’s issued by default; this is configurable per application (not exposed in the UI yet, ask support/engineering to adjust it if a longer window is genuinely needed).