[file:<id>:<name>] token inside its encrypted body on the ordinary send() path.
Send a file to a channel
sendFile encrypts, uploads, writes the share grant, and only then sends the message. If the grant is refused it deletes the upload and rejects, so a message never references an attachment nobody can open. Thread sends work too: pass { threadId } in the options like any other send.
The upload and grant legs are awaited and reject on failure. The final message send is fire-and-forget by default, like send(). Pass ack: true to await the server’s echo and get the persisted Message back; a denial pinned to that message then rejects with CloakActionError and the uploads are deleted, while an indeterminate outcome (CloakSendTimeoutError) leaves them, because the message may exist. Pass signal to cancel the upload and grant legs.
Send several files in one message
[file:<id>:<name>] token, which is how the Cloak clients attach several files. If any upload or grant fails, every blob uploaded so far is deleted and the call rejects, so a partial delivery never lands. sendFilesDM(userId, files, opts) is the DM form, and sendFile() is sendFiles() with one file.
Send a file in a DM
sendDM().
Receive and download
Incoming attachments are parsed out of the decrypted body and exposed on the message:msg.attachments is parse-only: an entry proves the sender named a file, not that your bot may read it. Authorization happens at download time, against the grant the server holds.
Grants are epoch-tagged.
downloadAttachment reads the epoch off the grant and acquires that epoch’s key when the keystore lacks it, so files shared before your bot’s current epoch still open. After a server root key cycle, older attachments are permanently unopenable. That is the rotation design, not a bug.Limits and metering
Per-file and total-storage limits are the bot owner’s plan tier, not a bot-specific number, and bot transfers are metered by a rolling bandwidth window in both directions. The server’s verdict surfaces verbatim as aCloakRestError:
A download can also fail with a “pre-060 raw-key grant” error: the file was shared by an outdated client using the legacy raw-key format, and its owner must re-share it. The SDK never produces raw-key grants itself.
Next
The REST lane
The credential these calls ride, and why it is off by default.
What is encrypted, and what is not
Where attachments sit among Cloak’s encryption lanes.
Crypto reference
fileCipher, parseFileKeyGrant, and the exported grant helpers.Handling errors
CloakRestError and reading errorCode.