Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.eachlabs.ai/llms.txt

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

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