When you build AI media workflows, you quickly run into a small but annoying problem: many APIs want a public file URL, while your source asset is sitting on a local disk, in a temporary upload, or inside your own backend.
What you can do
The AceDataCloud platform file upload API is a small utility endpoint for turning a local file into a permanently accessible CDN URL. The uploaded file returns a file_url such as:
{
"file_url": "https://cdn.acedata.cloud/qrd7gw.jpg"
}
That URL can then be passed into downstream APIs that expect URL inputs, for example fields like image_url, image_urls, or reference_url in media generation workflows.
This is not a general marketing feature; it is a practical glue step. If your pipeline needs to call an image, video, or music API that cannot read your local file directly, you upload once, get a URL, and pass that URL forward.
How it works
The upload endpoint belongs to the AceDataCloud Platform Management API, whose unified prefix is:
https://platform.acedata.cloud/api/v1/
The concrete endpoint is:
POST https://platform.acedata.cloud/api/v1/files/
The important request details are:
- Authentication: account token in
Authorization: Bearer ... - Content type:
multipart/form-data, not JSON - Form field:
file - Default single file limit: 28 MB
- Response field:
file_url
A minimal cURL request looks like this:
curl -X POST 'https://platform.acedata.cloud/api/v1/files/' \
-H 'accept: application/json' \
-H 'authorization: Bearer platform-v1-92eb****629c' \
-F 'file=@./photo.jpg'
The response is intentionally small:
{
"file_url": "https://cdn.acedata.cloud/qrd7gw.jpg"
}
The returned CDN URL is publicly accessible without authentication. That makes it convenient for machine-to-machine workflows, but it also means you should not upload sensitive data unless you have a clear retention plan.
Use case: prepare a base image for a generation pipeline
A common pattern is to let a user upload an image, store it briefly in your backend, then pass it to a generation API as a reference. Many APIs do not want base64 in those fields; they want a URL.
The platform file upload endpoint solves the transition:
- Receive
photo.jpgfrom the user or from an internal job. - Upload it to
POST /api/v1/files/asmultipart/form-data. - Read
data.file_urlfrom the response. - Use that URL in the next API call.
The documentation gives examples such as using CDN URLs with Midjourney image_urls, Flux image_url, and Veo reference_url. The upload step is the same regardless of which downstream service you call next.
Python example
Here is the Python version from the same workflow, adapted as a small function. Notice that the request uses files=..., not a JSON body.
import requests
PLATFORM_TOKEN = "platform-v1-92eb****629c"
def upload_to_cdn(path: str) -> str:
with open(path, "rb") as f:
resp = requests.post(
"https://platform.acedata.cloud/api/v1/files/",
headers={
"accept": "application/json",
"authorization": f"Bearer {PLATFORM_TOKEN}",
},
files={"file": ("photo.jpg", f, "image/jpeg")},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
return data["file_url"]
file_url = upload_to_cdn("photo.jpg")
print("CDN URL:", file_url)
In a real service, you would keep PLATFORM_TOKEN in your secret manager or environment, not inside source code. The token shown above is a masked example from the docs.
Once you have file_url, the next request can reference it directly. The docs show the idea with a downstream image call:
# requests.post(
# "https://api.acedata.cloud/midjourney/imagine",
# json={"prompt": "...", "image_urls": [file_url]},
# ...
# )
The key point is not the specific downstream model. The important contract is: local binary file in, stable CDN URL out.
Node.js example
For Node.js, use form-data and stream the file from disk:
const fs = require('fs')
const FormData = require('form-data')
const form = new FormData()
form.append('file', fs.createReadStream('./photo.jpg'))
const r = await fetch('https://platform.acedata.cloud/api/v1/files/', {
method: 'POST',
headers: {
authorization: 'Bearer platform-v1-92eb****629c',
...form.getHeaders(),
},
body: form,
})
const data = await r.json()
console.log('CDN URL:', data.file_url)
One detail that often causes bugs: do not manually set Content-Type: multipart/form-data without the boundary. Libraries such as form-data generate the correct headers for you through form.getHeaders().
Error handling you should implement
There are three practical failures to handle:
-
400with{"error":"No file provided"}: the request did not include thefilefield, or the field name was wrong. -
401: the account token is missing or invalid. -
413with{"error":"File too large","max_bytes":...}: the file exceeds the default 28 MB limit.
In a backend service, I would treat these differently. A 400 is usually a developer or form-data bug. A 401 should alert you to configuration or secret rotation. A 413 is a product constraint: validate file size before upload and show the user a clear message.
Operational tips
A few details matter in production:
- The returned
file_urlis permanent and publicly accessible, so avoid uploading secrets, private user files, or unreleased assets unless that is intended. - For bulk uploads, the docs recommend 2–4 concurrent uploads.
- A single connection can reach around 10 MB/s, which is usually enough for image and short media preprocessing.
- Because the endpoint expects a single
filefield, keep batch logic in your client rather than trying to send many unrelated files in one request.
Closing thoughts
This endpoint is useful because it removes a boring infrastructure step. Instead of standing up temporary object storage just to satisfy URL-based AI APIs, you can upload a file, receive file_url, and continue the workflow.
If you want the exact request and response reference, see the platform file upload documentation.
Top comments (0)