Files & Attachments
Send files with a message: upload them once through IFiles and name them by
fileId, or carry them as parts of the
IMessages/Send request itself.
Overview #
A message carries up to 10 attachments of any type, each up to 10 MiB.
The bot needs AttachFiles in the channel on top of
SendMessages. There are two ways to hand the files over:
Only IMessages/Send takes attachments;
IInteractions/Reply does not.
Sticker and emoji files go through the same IFiles/Upload with another purpose —
see Stickers & Custom Emoji → Files.
Uploading with IFiles #
POST /IFiles/v1/Upload is a multipart/form-data
request with a file part and
purpose=attachment. Any type is taken, up to 10 MiB.
The part's file name and Content-Type are kept as the attachment's
fileName and contentType
(application/octet-stream when the part declares none).
Upload
curl -X POST \
-H "Authorization: Bot YOUR_TOKEN" \
-F "purpose=attachment" \
-F "[email protected];type=application/pdf" \
https://gateway.argon.zone/IFiles/v1/Upload Response (BotFileV1)
{
"fileId": "5f1d0c3a-...",
"size": 482113,
"contentType": "application/pdf",
"url": ".../files/5f1d0c3a-...",
"fileName": "report.pdf"
} An upload lives 24 hours. Within them its fileId can go into any number of messages;
a sent message keeps its files after that. A bot holds at most 100 unused uploads at a time — the next returns
422 quota_exceeded — and an upload stops counting once a message carries it.
GET /IFiles/v1/Get?fileId=… describes an upload again.
Sending by fileId #
Name the uploads in the attachments list of an ordinary JSON
IMessages/v1/Send. Only uploads of this bot with purpose
attachment are taken; a sticker or emoji upload is 404 not_found here.
Request
curl -X POST \
-H "Authorization: Bot YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channelId":"c0ffee00-...","text":"Weekly report","randomId":7311,"attachments":["5f1d0c3a-..."]}' \
https://gateway.argon.zone/IMessages/v1/Send Response
{
"messageId": 42,
"attachments": [
{
"fileId": "5f1d0c3a-...",
"url": ".../files/5f1d0c3a-...",
"fileName": "report.pdf",
"size": 482113,
"contentType": "application/pdf",
"width": null,
"height": null
}
]
} The response describes every attachment in the order given (BotAttachmentV1), so the bot has the file URLs without reading the message back.
Multipart Requests #
IMessages/v1/Send also takes multipart/form-data
with the same fields. Every field is a text part; entities and
controls are one field holding their JSON. The
attachments field is repeated once per file, and each file can be given three ways:
chart). A name that matches no part returns 400 invalid_request. fileId of an earlier upload, as in JSON. Three files: a named part, an upload and a part of its own
curl -X POST \
-H "Authorization: Bot YOUR_TOKEN" \
-F "channelId=c0ffee00-..." \
-F "text=Chart, report and raw data" \
-F "randomId=7312" \
-F "attachments=attach://chart" \
-F "attachments=5f1d0c3a-..." \
-F "[email protected];type=image/png" \
-F "[email protected];type=text/csv" \
https://gateway.argon.zone/IMessages/v1/Send
The text fields come first in the message, in their order, then the parts named attachments:
the example sends chart.png, the uploaded report and data.csv.
A part sent this way does not count against the 100 unused uploads.
One multipart request carries about 10 MiB of parts in total — one file at its largest — and more is refused with
413 too_large. Upload larger sets first and send them by
fileId. An attach://
reference in a JSON body is 400 invalid_request: there are no parts to name.
Reading Attachments #
Messages carry their files as attachments — in
GET /IMessages/v1/History, in the
messageCreate event
and in the Send response — whoever sent them. On a message without files it is
null (an empty list in the Send response).
null for anything else. SSE example — event: messageCreate, data: (excerpt)
{
"spaceId": "aaaabbbb-...",
"channelId": "c0ffee00-...",
"message": {
"messageId": 44,
"text": "This week's chart",
"attachments": [
{
"fileId": "9e8d7c6b-...",
"url": ".../files/9e8d7c6b-...",
"fileName": "chart.png",
"size": 48211,
"contentType": "image/png",
"width": 1200,
"height": 800
}
]
}
}
The message's attachment entities describe the same files and carry the same
url — see Message Entities.
Read attachments; it is the simpler of the two.
Errors #
Besides the refusals every message can get (cannot_send, slow_mode, …),
a message with files, or an upload, can be refused with these. Nothing is sent when one of them comes back.
attach:// names no part, or an attach:// is in a JSON body. AttachFiles in this channel. fileId names no attachment upload of this bot: it is unknown, over 24 hours old, or was uploaded for a sticker or emoji. IFiles/Upload only: the bot holds 100 unused uploads. Send some, or wait for them to expire.
Branch on the error code, not the status — see Error Handling.
Limits & Permissions #
validation_error. Send or IFiles/Upload: 10 MiB of parts plus the form around them. IFiles · IMessages, sliding window per bot.