Skip to main content

Overview

Many models accept media (images, video, audio) as input. To use your own files, upload them with this endpoint and pass the returned public_url to Create Prediction. Uploads happen in two steps:
1

Request a presigned URL

POST /v1/upload/presign with file metadata. The response contains a short-lived URL to upload to and a permanent public_url.
2

Upload the file

PUT the raw file bytes to presigned_url, applying any required_headers exactly as returned.

Step 1 — Request a presigned URL

Endpoint

POST https://api.eachlabs.ai/v1/upload/presign

Request Body

FieldTypeRequiredDescription
content_typestringYesMIME type of the file (e.g., image/png, video/mp4, audio/mpeg).
file_typestringNoHigh-level category. One of image, video, audio, other.

Code Examples

curl -X POST https://api.eachlabs.ai/v1/upload/presign \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "content_type": "image/png",
    "file_type": "image"
  }'

Response

{
  "id": "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0",
  "presigned_url": "https://eachlabs-storage.s3.amazonaws.com/uploads/...?X-Amz-Algorithm=...&X-Amz-Signature=...",
  "public_url": "https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png",
  "expires_at": "2026-04-27T18:15:00Z",
  "required_headers": {
    "x-amz-meta-file-id": "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
  }
}

Response Fields

FieldTypeDescription
idstringInternal upload identifier.
presigned_urlstringShort-lived URL to PUT the file to.
public_urlstringPermanent URL to pass as a model input once the upload succeeds.
expires_atstringISO-8601 timestamp when presigned_url stops accepting uploads.
required_headersobjectHeaders that must be sent verbatim on the PUT request. The presigned URL is signed for these exact values — missing or modified headers will fail with a signature mismatch. May be empty.

Step 2 — Upload the file

PUT the raw file bytes to presigned_url. Include every header from required_headers exactly as returned, plus a Content-Type matching the value sent in step 1.
curl -X PUT "$PRESIGNED_URL" \
  -H "Content-Type: image/png" \
  -H "x-amz-meta-file-id: 0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0" \
  --data-binary @./photo.png
A 200 OK from the PUT means the file is live. Use public_url as the input value when you create a prediction.
{
  "model": "flux-1-1-pro",
  "version": "1.0.0",
  "input": {
    "image": "https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png",
    "prompt": "Make it look cinematic"
  }
}

Limits

LimitValueNotes
Max file size100 MB per upload
Presigned URL lifetime15 minutesUse the URL before expires_at; request a new one if it lapses.

Error Responses

StatusBodyDescription
400{"error": "content_type is required"}Missing required field.
401{"error": "Invalid or missing API key"}Authentication failure.
500{"error": "Failed to generate presigned URL"}Server error.
The presigned URL expires 15 minutes after it’s issued. Upload soon after requesting — if you wait past expires_at, just request a new one.
Last modified on April 27, 2026