DEV Community

Cover image for How to Upload Files to a CDN Before Calling AI Media APIs
Germey
Germey

Posted on • Originally published at platform.acedata.cloud

How to Upload Files to a CDN Before Calling AI Media APIs

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"
}
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

The concrete endpoint is:

POST https://platform.acedata.cloud/api/v1/files/
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

The response is intentionally small:

{
  "file_url": "https://cdn.acedata.cloud/qrd7gw.jpg"
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Receive photo.jpg from the user or from an internal job.
  2. Upload it to POST /api/v1/files/ as multipart/form-data.
  3. Read data.file_url from the response.
  4. 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)
Enter fullscreen mode Exit fullscreen mode

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]},
#     ...
# )
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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:

  • 400 with {"error":"No file provided"}: the request did not include the file field, or the field name was wrong.
  • 401: the account token is missing or invalid.
  • 413 with {"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_url is 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 file field, 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)