Uploads
Mint An Image Upload URL
Mint a short-lived, single-use Convex storage upload URL, then PUT image bytes to it to receive a storageId for a downstream write.
POST
Permission Required
This endpoint requiresuploads.upload:read-write on your API key, plus the writes feature. The owner is always the API key owner, derived from the key itself - it is never accepted as a body field. A free (api_free) key receives 403 error_api_feature_required; this requires an api_pro+ plan.
Access / Membership Rules
This is a user-self route (binding: "none") - it is not bound to a game or league. The minted URL belongs to the API key owner. The endpoint takes no request body and no parameters.
What’s Returned
Returns{ uploadUrl } - a short-lived, single-use Convex storage upload URL. The bytes do not exist yet at mint time, so no validation happens here.
The Upload Flow
The image upload is a two-step, mint-then-upload flow:Mint the URL
Call this endpoint to get a fresh
uploadUrl. The URL is single-use and short-lived, so mint it
just before you upload.POST the image bytes
POST the raw image bytes to the
uploadUrl with the matching Content-Type header. The response
body is { "storageId": "..." }.Size And Content-Type Limits
This endpoint mints the URL only - it does not validate the bytes. Validation happens on the consuming write when you attach thestorageId:
| Limit | Value |
|---|---|
| Max size | 5 MB |
| Allowed types | image/png, image/jpeg, image/gif, image/webp, image/avif |
400 INVALID_INPUT. image/svg+xml is intentionally not allowed (SVG can carry script).
The
storageId is bound to you, the uploader. The consuming write rejects a storageId minted for
or by another tenant, so you cannot attach someone else’s blob.Authorizations
Send your API key as: Authorization: Bearer tb_
Response
A freshly minted upload URL.
A freshly minted Convex storage upload URL. POST the image to it to receive a storageId for use on a downstream write.
Short-lived, single-use URL to POST the image bytes to.