API reference
File upload policy
/v1/media/upload-policy/v1/media/upload-policyUpload image, video, audio, and generic files to file storage, then pass the returned public URL to a model request. The gateway only creates a short-lived, user-scoped upload policy; file bytes do not pass through the API server.
{
"image_max_bytes": 52428800,
"video_max_bytes": 209715200,
"audio_max_bytes": 104857600,
"file_max_bytes": 52428800
}#Create an upload policy
kindstringrequired"image", "video", "audio", or "file".
content_typestringrequiredA concrete MIME type matching kind. file accepts non-image/video/audio MIME types such as application/pdf or text/plain.
sizeintegerrequiredExact file size in bytes. GET this endpoint with the same API key to read all four user-specific limits.
curl https://www.aisplice.store/v1/media/upload-policy \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "image",
"content_type": "image/avif",
"size": 1048576
}'{
"upload_url": "https://uploads.example.com/",
"public_url": "https://media.example.com/media/user-upload/image/...",
"fields": {
"key": "media/user-upload/image/...",
"policy": "...",
"...": "Pass every returned field unchanged"
},
"expires_at": "2026-07-25T10:05:00Z"
}#Upload to file storage
Send every returned fields entry and the file in one multipart POST to upload_url. The policy expires after five minutes, is bound to one generated file path, and cannot overwrite an existing file.
# Save the policy response as policy.json first.
upload_args=()
while IFS=$'\t' read -r key value; do
upload_args+=(-F "$key=$value")
done < <(jq -r '.fields | to_entries[] | [.key, .value] | @tsv' policy.json)
# Keep the file field last for storage compatibility.
curl "$(jq -r .upload_url policy.json)" \
"${upload_args[@]}" \
-F "file=@reference.avif"#Use the public URL
After file storage returns success, use public_url in the media field supported by the selected model. Upload acceptance does not guarantee that every model can decode every media format; check the model request contract.
{
"model": "gpt-image-2",
"prompt": "Turn this reference into a watercolor",
"images": ["https://media.example.com/media/user-upload/image/..."]
}#Related errors
This endpoint reports failures through error.type rather than error.code, so match on the values below together with the status.
- 400 invalid_request_errorkind, content_type, and size must describe one upload file.
- 401 unauthorizedInvalid or missing bearer token.
- 413 payload_too_largeThe declared file size exceeds the configured upload limit.
- 415 unsupported_media_typecontent_type does not match the selected image, video, audio, or generic file family.
Still stuck?
Send us the request ID or the error message and we will look into it.