RealTimeX
Start For Free

RealTimeX

API Documentation

IntroductionAuthenticationBase URLHeadersError codes
Presigned URLs
Sample requestsSample responsesStatus codesAppendixChangelog

API Reference

Get Presigned URLs (S3 Upload)

Overview

Get short-lived S3 presigned URLs so your chat package / client can upload files directly to storage — without sending file bytes through the RealtimeX API server.

For each file you request, the API returns an uploadUrl (PUT the file here) and a fileUrl (the permanent URL to use in messages, profiles, or group images after upload succeeds).

When to use this endpoint?

Use Get Presigned URLs when:

  • A chat user attaches an image, video, audio, or document in the composer.
  • They update a profile avatar or group image from the chat SDK.
  • You need to upload several files in one batch (request multiple entries in files).
  • You want direct-to-S3 uploads for better performance and smaller API payload size.

Part of the Chat Uploads flow for the chat package / SDK. Requires a chat user Access Token and tenant headers. Presigned URLs expire quickly (see X-Amz-Expires in the URL, often ~300 seconds) — upload promptly after you receive them.

Upload Workflow

Follow these steps in your chat client every time a user sends or attaches a file. Skipping the PUT step will leave you with a fileUrl that has no file behind it.

  1. 1

    Pick the file(s)

    In your chat or profile UI, let the user choose one or more files (image, document, or other supported types). Read each file’s name and MIME type.

  2. 2

    Request presigned URLs

    Call this endpoint with a files array of { filename, fileType }. Use the chat user Access Token and tenant headers.

  3. 3

    Upload bytes to uploadUrl

    For each item in data, PUT the raw file body to uploadUrl. Do not send the file through your API server — upload goes directly to S3.

  4. 4

    Keep the permanent fileUrl

    After a successful PUT, store fileUrl. This is the public/stable URL you attach to messages, avatars, or group images.

  5. 5

    Send or save with fileUrl

    Include fileUrl in your chat message payload (or profile update). The chat UI can then render the media from that URL.

  6. 6

    Confirm in the UI

    Show a success state (thumbnail, attachment chip, or avatar). If upload or send fails, let the user retry without creating orphan messages.

End-User Guidelines

Guidance for product and SDK implementers so uploads feel reliable for people using the chat app:

  • Show progress — while PUT is in flight, show an upload indicator on the attachment bubble or composer. Do not mark the message as sent until both S3 upload and your message API succeed.
  • Validate before requesting URLs — check file size, type, and count in the UI first. Avoid calling this endpoint for empty selections or unsupported MIME types.
  • Match Content-Type — the fileType you send in the request and the Content-Type header on the PUT must match the real file MIME type, or S3 may reject the upload.
  • Upload before sending the chat message — put fileUrl into the message only after PUT returns success. Otherwise peers open a broken attachment link.
  • Handle expiry — if the user stays on a slow network and the presigned URL expires, request new URLs and retry the PUT. Do not reuse an expired uploadUrl.
  • Allow cancel / retry — if the user cancels mid-upload, discard the pending message draft. On failure, offer Retry without creating duplicate messages.
  • Keep order — data array items align with your request files array order. Map each response pair back to the correct local file.

Request Fields

FieldTypeRequiredDescription
filesarrayRequiredNon-empty list of files to upload. Each item needs filename and fileType.
files[].filenamestringRequiredOriginal file name (for example profile-photo.png). Used when generating the storage key.
files[].fileTypestringRequiredMIME type (for example image/png, application/pdf). Must match the PUT Content-Type.
POST{baseUrl}/api/{apiVersion}/aws/upload/get-presigned-urls

Authentication

Required (Bearer token)

Tenant-scoped

Yes (tenant DB — requires x-client-id)

Request Headers

HeaderValueDescription
AuthorizationBearer <access_token>Chat user Access Token (Bearer) for the signed-in messaging participant.
is-tenanttrueTargets the tenant DB ("true", needs x-client-id).
x-client-id{{clientId}}Tenant (client) id. Required when is-tenant=true.
Content-Typeapplication/jsonJSON body for this endpoint (not the file bytes).

Request Payload

Example requesting presigned URLs for an image and a PDF in one call:

json
{
  "files": [
    {
      "filename": "profile-photo.png",
      "fileType": "image/png"
    },
    {
      "filename": "report.pdf",
      "fileType": "application/pdf"
    }
  ]
}

Success Response (HTTP 200 OK)

data is an array aligned with your files input. Each entry has:

FieldDescription
uploadUrlTemporary signed URL. PUT the file bytes here. Expires after a short window — upload immediately.
fileUrlPermanent URL of the object. Use this in chat messages, avatars, or group images after a successful PUT.
json
{
  "success": true,
  "message": "Presigned URLs generated successfully",
  "data": [
    {
      "uploadUrl": "https://example.amazonaws.com/uploads/images/avatar-7f8c9d12.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE123456789%2F20260719%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20260719T134500Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=9f8a7b6c5d4e3f210987654321abcdef1234567890abcdef1234567890abcdef",
      "fileUrl": "https://example.com/avatar-7f8c9d12.png"
    },
    {
      "uploadUrl": "https://example.amazonaws.com/uploads/files/report-7f8c9d12.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE123456789%2F20260719%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20260719T134500Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=9f8a7b6c5d4e3f210987654321abcdef1234567890abcdef1234567890abcdef",
      "fileUrl": "https://example.com/report-7f8c9d12.pdf"
    }
  ],
  "error": null
}

Upload the File to S3

This API does not accept file bytes. After you receive uploadUrl, upload directly to S3 with PUT:

javascript
// After you receive uploadUrl + fileUrl from this API:
const file = selectedFile; // File from <input type="file"> or picker

const putResponse = await fetch(uploadUrl, {
  method: "PUT",
  headers: {
    "Content-Type": file.type, // must match fileType you sent above
  },
  body: file,
});

if (!putResponse.ok) {
  throw new Error("Upload to storage failed");
}

// Use permanent fileUrl in your chat message / profile payload:
// e.g. { type: "image", attachmentUrl: fileUrl }

Do not attach Authorization headers from RealtimeX when calling uploadUrl — authentication is already embedded in the query string signature. Only send the file body and the correct Content-Type.

Common Errors

This endpoint fails when the token is missing or the files array is empty. S3 PUT errors happen separately after you receive the URLs.

HTTP 400 Bad Request — No files provided

json
{
  "success": false,
  "message": "No files provided",
  "data": null,
  "error": "No files provided"
}

HTTP 401 Unauthorized — No token

json
{
  "success": false,
  "message": "No token, authorization denied",
  "data": null,
  "error": "Unauthorized"
}
CodeReason
400 Bad Requestfiles is missing or empty.
401 UnauthorizedAccess Token is missing, invalid, or expired.
500 Internal Server ErrorAn unexpected error occurred while generating presigned URLs.

Best Practices

  • Request URLs only for files the user has confirmed — then PUT immediately while the signature is valid.
  • Never log full uploadUrl values in production (they are temporary credentials in URL form).
  • Prefer batching a small number of attachments in one files request when the user multi- selects media.
  • After upload, persist fileUrl only — not the expired uploadUrl.
  • Always send tenant headers with the chat user Bearer token over HTTPS when calling this API.

Ready to upload

Once PUT succeeds, attach fileUrl to your chat message or profile update. For media already in a thread, browse them later with Conversation → Attachments.

PreviousAudit LogsNextSample requests

On this page

OverviewWhen to use this endpoint?Upload WorkflowEnd-User GuidelinesRequest FieldsRequest HeadersRequest PayloadSuccess ResponseUpload the File to S3Common ErrorsBest Practices