Skip to main content

Request a presigned URL for a media upload (dual-authenticated).

Initiate a media upload for a specific listing. Returns a presigned PUT URL the client uses to stream bytes directly to the staging bucket, plus a Celery task id that will deliver the object to the agency's connected storage (Dropbox / Google Drive) via Composio.

Authentication

Accepts EITHER:

  • Session cookie (dashboard): better-auth-session cookie. Viewer role blocked.
  • API key (external integrators): X-API-Key header. Agency-scoped at key creation.

API key takes precedence when both are present.

Rate limit

API-key callers: 20 req/min (upload_media bucket, tightest on the platform). Session callers share the dashboard's existing limits. The 202 response is cheap; the expensive work happens asynchronously after the client PUTs bytes to the presigned URL.

Webhook correlation

This endpoint fires NO webhook itself. Integrators must subscribe to media.delivery.completed / .failed (events/02) to know when bytes have actually landed in their storage. The task_id returned here appears verbatim on the later webhook event.

MethodPath
POST/api/v1/media/upload

Primary host: https://valara.cloud (legacy alias: https://dash.jacoballenmedia.com).

Parameters

(no path or query parameters)

Request body

(no request body)

Response

null

Responses

StatusDescription
202Successful Response
422Validation Error (see error codes)

Examples

curl

curl -X POST "https://valara.cloud/api/v1/media/upload" \
-H "Authorization: Bearer $VALARA_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: $(uuidgen)"

Python

import os
import uuid
import httpx
res = httpx.request(
"POST",
"https://valara.cloud/api/v1/media/upload",
headers={
"Authorization": f"Bearer {os.environ['VALARA_API_KEY']}",
"Content-Type": "application/json",
"X-Idempotency-Key": str(uuid.uuid4()),
},
)
res.raise_for_status()
print(res.json())

See also