Skip to main content
POST
/
v1
/
uploads
Create an upload
curl --request POST \
  --url https://app.loops.so/api/v1/uploads \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "contentType": "<string>",
  "contentLength": 123
}
'
{
  "success": true,
  "emailAssetId": "asset_01hxyz",
  "presignedUrl": "https://storage.example.com/upload?signature=..."
}

Documentation Index

Fetch the complete documentation index at: https://loops.so/docs/llms.txt

Use this file to discover all available pages before exploring further.

Content API endpoints are currently in an open alpha and are subject to change.
Request a pre-signed URL to upload an image asset. Upload the file with an HTTP PUT to the returned presignedUrl (sending the same Content-Type and Content-Length), then call Complete an upload to finalize the asset.

Request

Body

contentType
string
required
The MIME type of the file to upload. Supported types are image/jpeg, image/png, image/gif, and image/webp.
contentLength
integer
required
The size of the file in bytes. Must be a positive integer no greater than 4,000,000 bytes.

Response

Success

success
boolean
required
emailAssetId
string
required
The ID of the created asset. Pass this as id to Complete an upload once the file has been uploaded.
presignedUrl
string
required
The pre-signed URL to upload the file to with an HTTP PUT request. Send the same Content-Type and Content-Length used in the create request.

Error

If the request body is invalid, or if contentType is unsupported, a 400 Bad Request is returned. The response may include a supportedContentTypes array listing accepted MIME types. If the upload exceeds the maximum allowed size, a 413 Payload Too Large is returned. The response may include a maxBytes field with the size limit. If the upload limit is exceeded, a 429 Too Many Requests is returned. The response may include maxUploads and windowHours fields describing the limit window. If the API key is invalid (or content API is not enabled for your team), a 401 Unauthorized is returned.
success
boolean
required
message
string
required
An error message describing what went wrong.
supportedContentTypes
string[]
Present when the request was rejected for an unsupported contentType. Lists the accepted MIME types.
maxBytes
integer
Present when the upload exceeds the size limit. The maximum allowed size in bytes.
maxUploads
integer
Present when the upload limit is exceeded. The maximum number of uploads allowed per window.
windowHours
integer
Present when the upload limit is exceeded. The number of hours in the upload limit window.
{
  "success": true,
  "emailAssetId": "asset_01hxyz",
  "presignedUrl": "https://storage.example.com/upload?signature=..."
}
Last modified on May 27, 2026