Skip to main content
POST
/
uploads
/
url
Create Upload Url
curl --request POST \
  --url https://api.moda.app/v1/uploads/url \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "filename": "<string>",
  "mime_type": "<string>",
  "expires_in_seconds": 600
}
'
{
  "upload_url": "<string>",
  "storage_key": "<string>",
  "mime_type": "<string>",
  "expires_in_seconds": 123,
  "instructions": "<string>"
}

Documentation Index

Fetch the complete documentation index at: https://docs.moda.app/llms.txt

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

Authorizations

Authorization
string
header
required

API key from Settings > Developer > REST API

Headers

Moda-Version
enum<string>
default:2026-05-01

Calendar-dated API version pin. New integrations should pin 2026-05-01 to opt into the newest response shapes. For back-compat the server also accepts requests with no header and resolves them to the current default (today: 2026-04-12); that default advances on each sunset date. Any unsupported value returns 400 unsupported_version.

Available options:
2026-04-12,
2026-05-01
Example:

"2026-05-01"

Body

application/json

Request a signed PUT URL for direct-to-storage upload.

The multipart POST /uploads endpoint funnels bytes through the API gateway, which caps inbound bodies at ~32 MiB (Cloud Run HTTP/1 limit) — files above that size are rejected with a 413 before the handler runs. This two-step flow sidesteps the cap by letting the client PUT bytes directly to storage.

filename
string
required

Original filename. Only the basename is used; path components are stripped.

Required string length: 1 - 512
mime_type
string
required

MIME type of the file (e.g. application/vnd.openxmlformats-officedocument.presentationml.presentation for PPTX, application/pdf, image/png). Must be on the allow-list.

expires_in_seconds
integer
default:600

How long the signed URL is valid (60–3600 seconds, default 600).

Required range: 60 <= x <= 3600

Response

Successful Response

upload_url
string
required

Pre-signed URL. PUT the raw file bytes here with Content-Type: <mime_type> within expires_in_seconds. No auth header on the PUT — the URL itself is the capability.

storage_key
string
required

Opaque key identifying the pending upload. Pass back to POST /v1/uploads/register after the PUT completes to finalize the file.

mime_type
string
required

Resolved MIME type the signed URL is bound to.

expires_in_seconds
integer
required

How long the upload URL remains valid (seconds).

instructions
string
required

Human-readable usage hint describing the PUT + register contract.