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

Claim
Browse the docs

API reference

Media

Two ways to attach media: public URLs the server downloads, or presigned uploads for large files.

Base URL https://api.overads.io/public/v1. Every route needs a key with the scope shown, sent as Authorization: Bearer sk_live_YOUR_KEY. The machine-readable contract is at https://api.overads.io/public/v1/openapi.json, no key needed. Scope for this family: media:write.

Which path

  • mediaUrls on the post: the fast path. Public https, up to 10 URLs, 15 MB per image and 25 MB per video. The server downloads the file into overads storage; the post cannot tell how the media arrived.
  • Presigned upload: for anything private or larger, up to 500 MB of video. Three calls: get a URL, PUT the bytes, complete.

Every URL is fetched through the same guard the rest of the platform uses: public addresses only, redirects re-checked, the socket pinned to the vetted address. A refusal names the host, never the full URL, because signed URLs carry tokens.

POST/media/upload-url

Scope media:write. A presigned PUT for a direct upload to overads storage.

Images up to 15 MB (image/jpeg, image/png, image/gif, image/webp); video up to 500 MB (video/mp4, video/quicktime, video/webm). The URL is valid for 15 minutes.

PUT the bytes to uploadUrl with exactly the returned headers, then call complete. For a file already on the public web skip this and pass mediaUrls on the post.

BodyTypeMeaning
kindenumrequiredimage or video.
contentTypestringrequiredThe Content-Type the PUT will send.
bytesintegerrequiredExact byte length of the file the PUT will send.

Response: { data: { media, uploadUrl, method: "PUT", headers, expiresAt }, warnings: [] }. media.status is uploading until completed.

200json
{
  "data": {
    "media": { "id": "7c2e…", "url": "https://media.overads.io/social-media/…/7c2e….mp4", "kind": "video", "status": "uploading", "source": "upload", "bytes": 48213004, "width": null, "height": null, "durationMs": null, "createdAt": "…" },
    "uploadUrl": "https://….amazonaws.com/…?X-Amz-Signature=…",
    "method": "PUT",
    "headers": { "Content-Type": "video/mp4", "Content-Length": "48213004" },
    "expiresAt": "2026-09-11T09:45:00.000Z"
  },
  "warnings": []
}
curlbash
curl -X POST https://api.overads.io/public/v1/media/upload-url -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{ "kind": "video", "contentType": "video/mp4", "bytes": 48213004 }'

POST/media/:id/complete

Scope media:write. Confirm the upload landed. The asset becomes ready and can be attached through mediaIds.

Refused with MEDIA_NOT_READY when no object is in storage yet, and with MEDIA_TOO_LARGE when the uploaded object is over the cap for its kind.

Response: { data: Media, warnings: [] }.

curlbash
curl -X POST https://api.overads.io/public/v1/media/7c2e1b0a-4f3d-4e2b-9a1c-2d3e4f5a6b7c/complete -H "Authorization: Bearer sk_live_YOUR_KEY"

DELETE/media/:id

Scope media:write. Delete a media asset and its stored object.

Posts that already reference the URL keep the string, but the object is gone. Delete only media no post still needs.

Response: 204, no body.

curlbash
curl -X DELETE https://api.overads.io/public/v1/media/7c2e1b0a-4f3d-4e2b-9a1c-2d3e4f5a6b7c -H "Authorization: Bearer sk_live_YOUR_KEY"

The upload, end to end

bashbash
# 1. reserve
RES=$(curl -s -X POST https://api.overads.io/public/v1/media/upload-url -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d "{ \"kind\": \"video\", \"contentType\": \"video/mp4\", \"bytes\": $(stat -f%z reel.mp4) }")
URL=$(echo "$RES" | jq -r .data.uploadUrl)
ID=$(echo "$RES" | jq -r .data.media.id)

# 2. put the bytes with the returned headers
curl -X PUT "$URL" -H "Content-Type: video/mp4" --data-binary @reel.mp4

# 3. complete, then attach
curl -X POST https://api.overads.io/public/v1/media/$ID/complete -H "Authorization: Bearer sk_live_YOUR_KEY"
curl -X POST https://api.overads.io/public/v1/posts -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d "{ \"content\": \"New reel\", \"connectionIds\": [\"...\"], \"mediaIds\": [\"$ID\"] }"