First 200 users get the Growth plan for $19/mo.

Claim
Browse the docs

Guides

Media by URL and presigned uploads

When to pass a URL, when to upload, and the exact three-call upload sequence.

By URL

Put public https URLs in mediaUrls on the post. The server downloads each one into overads storage before the post is saved, so the source can go away afterwards. Up to 10 URLs, 15 MB per image, 25 MB per video. The file type is sniffed from the bytes, not the extension.

curlbash
curl -X POST https://api.overads.io/public/v1/posts -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{ "content": "Two angles.", "connectionIds": ["…"], "mediaUrls": ["https://cdn.example.com/a.jpg", "https://cdn.example.com/b.jpg"] }'

A refusal is MEDIA_URL_REFUSED with the reason and the host. Private addresses, plain http, non-2xx answers and non-media content are all refused. Signed URLs work as long as they are public https and still valid when the server fetches them.

By upload

For private files, or video over 25 MB, reserve a presigned PUT, send the bytes, then complete. Images up to 15 MB, video up to 500 MB. The reserved URL lasts 15 minutes.

Nodejavascript
const base = "https://api.overads.io/public/v1";
const headers = { Authorization: "Bearer " + process.env.OVERADS_API_KEY, "Content-Type": "application/json" };
const file = await fs.promises.readFile("reel.mp4");

// 1. reserve
const reserve = await fetch(base + "/media/upload-url", {
  method: "POST", headers,
  body: JSON.stringify({ kind: "video", contentType: "video/mp4", bytes: file.byteLength }),
}).then((r) => r.json());
const { media, uploadUrl, headers: putHeaders } = reserve.data;

// 2. PUT the bytes with exactly the returned headers
await fetch(uploadUrl, { method: "PUT", headers: putHeaders, body: file });

// 3. complete, then attach by id
await fetch(base + "/media/" + media.id + "/complete", { method: "POST", headers });
await fetch(base + "/posts", {
  method: "POST", headers,
  body: JSON.stringify({ content: "New reel", connectionIds: ["…"], mediaIds: [media.id] }),
});
  • complete answers MEDIA_NOT_READY (409) if the PUT has not landed. Wait for the PUT to return 200 before completing.
  • complete answers MEDIA_TOO_LARGE if the object in storage is over the cap for its kind, and marks the asset failed.
  • An asset stays uploading until completed; only ready assets can be attached through mediaIds.
  • DELETE /media/:id removes the object. A post that already references its URL keeps the string but the file is gone.

Both on one post

mediaUrls and mediaIds can be mixed. The post stores the final list of URLs in overads storage in the order given: URLs first, then ids.