Skip to main content

Chat File Sharing API

These two endpoints back file attachments in the Video SDK's native

in-meeting chat. Sharing a file is a two-step flow: **upload** the bytes to get a file reference, then send a chat message that points at it with `meeting.sendChatFileMessage(...)`.

Authentication

Both endpoints use the chat access token returned by meeting.getChatAccessToken(), sent in the Authorization: Bearer <token> header.

Header only

The chat access token is accepted in the Authorization header only. It is not read from the query string.


Upload a file


POST
    https://<appname>.metered.live/api/v1/chat/upload

<appname> - replace it with the name of your app.

Description

Upload a file and get back a reference you pass to meeting.sendChatFileMessage(...).

Request

  • Auth: Authorization: Bearer <chatAccessToken>
  • Content-Type: multipart/form-data
  • Body: a single field named file.

Constraints

ConstraintValue
Max size10 MB
Rate limit10 uploads per minute
MIME typesmust be on the allowlist below

Allowed MIME types:

  • image/png
  • image/jpeg
  • image/gif
  • image/webp
  • application/pdf
  • text/plain
  • text/csv
  • application/zip
  • application/x-zip-compressed
  • application/msword
  • application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • application/vnd.ms-excel
  • application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Request Samples

cURL
curl --request POST \
--url 'https://appname.metered.live/api/v1/chat/upload' \
--header 'Authorization: Bearer <chatAccessToken>' \
--form 'file=@/path/to/photo.png'

Responses

200
{
"fileS3Key": "<opaque file reference>",
"fileName": "photo.png",
"fileMimeType": "image/png",
"fileSizeBytes": 12345
}

Pass those four fields, in order, to meeting.sendChatFileMessage(fileS3Key, fileName, fileMimeType, fileSizeBytes).

All errors use the same shape: { "error": "<message>" }.

400
{
"error": "No file uploaded"
}

Also "File type not allowed" when the MIME type is not on the allowlist, or "Invalid upload" for a malformed multipart body (for example extra form fields).

401
{
"error": "chat access token is required"
}

Also "unauthorized" when the token is present but invalid, expired, or the participant is no longer in the meeting.

403
{
"error": "Chat is disabled for this participant"
}

Also "Chat is not available for this meeting" when the room has chat turned off.

413
{
"error": "File size exceeds 10MB limit"
}

Returned when the file is over 10 MB.

429
{
"error": "Too many uploads, please wait a moment"
}

Returned when the per-participant limit of 10 uploads per minute is exceeded. A separate per-IP limit of 120 requests per minute applies to both chat endpoints and returns { "error": "Too many requests" }.


Download a file


GET
    https://<appname>.metered.live/api/v1/chat/file/{messageId}

<appname> - replace it with the name of your app.

{messageId} - the _id of the file chat message.

Description

Download the attachment of a file chat message.

Authentication options

Choose one:

  • Download token (query string): ?dl=<downloadToken> — the per-message token delivered in the chatMessageReceived / chatHistory payload. Use this for links you render in your UI; it is the option the built-in UI uses.
  • Chat access token (header): Authorization: Bearer <chatAccessToken> — for SDK callers. This is subject to the same visibility rules as history: you can only fetch a file you were allowed to see (a broadcast file, or a directed file you sent or received). When the room stores history, it is also scoped to the retention window — a message older than the window is no longer reachable this way. The ?dl= download token is not affected by the window and stays valid for the life of the attachment.

Response

302 redirect to a short-lived (1 hour) signed URL. The file is served as an attachment.

Request Samples

cURL — per-message download token
curl -L \
--url 'https://appname.metered.live/api/v1/chat/file/<messageId>?dl=<downloadToken>' \
--output attachment

-L tells curl to follow the 302 redirect to the signed URL.

Responses

All errors use the same shape: { "error": "<message>" }.

401
{
"error": "unauthorized"
}

Returned when neither a valid download token nor a valid chat access token is provided.

403
{
"error": "Chat is disabled for this participant"
}

Returned on the chat-access-token path when chat is disabled for the requesting participant.

404
{
"error": "File not found"
}

Returned when the message does not exist, or the attachment is not visible to you.

410
{
"error": "File has expired"
}

Returned when the attachment has expired — file attachments are deleted after 24 hours.

429
{
"error": "Too many downloads, please wait a moment"
}

Returned on the chat-access-token path when the per-participant limit of 60 downloads per minute is exceeded. The shared per-IP limit of 120 requests per minute also applies and returns { "error": "Too many requests" }.


Full flow example

Upload → send → (recipient) download
// 1. Upload the file (sender)
const form = new FormData();
form.append("file", file); // a File / Blob

const res = await fetch("https://<appname>.metered.live/api/v1/chat/upload", {
method: "POST",
headers: { Authorization: `Bearer ${meeting.getChatAccessToken()}` },
body: form,
});
const { fileS3Key, fileName, fileMimeType, fileSizeBytes } = await res.json();

// 2. Send the file message (sender)
meeting.sendChatFileMessage(fileS3Key, fileName, fileMimeType, fileSizeBytes);

// 3. Download the attachment (recipient)
meeting.on("chatMessageReceived", (message) => {
if (message.type === "file" || message.type === "image") {
const url =
`https://<appname>.metered.live/api/v1/chat/file/${message._id}` +
`?dl=${message.downloadToken}`;
// e.g. render <a href={url}>{message.fileName}</a>
}
});