Docs menu

REST API · Creatives

Create uploads

Signed upload URLs for files on the caller's machine (PUT each file, then POST /uploads/confirm)

POSThttps://api.apogee.ad/api/v1/uploads

What it does

For a Meta, TikTok or Snapchat launch: ad_account_id is the account the files are for (GET /ad-accounts?platform=…). Up to 50 files per call, 500 MB per file; the URLs are valid 1 hour and never stored (an Idempotency-Key is accepted, nothing is replayed). Each file's size is required: an Apogee account may ask for 2000 files and 100 GB a day through the API and the MCP (429 rate_limited past it).

Request

POST /uploads on https://api.apogee.ad/api/v1.

Headers

  • Authorization string header required

    Bearer apk_…: an API key with the scope of this route.

  • Idempotency-Key string header optional

    Accepted and checked, never replayed (signed URLs are not stored).

    1 to 255 visible ASCII characters

  • Content-Type string header required

    application/json

Body

  • ad_account_id string required

    Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)

    Matches ^(act_\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$

  • files array of objects required

    1 to 50 items

    Fields of each item (3)
    • name string required

      File name with its extension

      1 to 255 characters

    • size integer required

      Bytes (the daily upload budget counts them)

      > 0 · ≤ 524,288,000

    • mime_type string optional

      up to 100 characters

Response

201.

  • files array of objects
    Fields of each item (8)
    • name string
    • upload_url string (uri)
    • method string

      One of PUT

    • headers map

      Each value: string

    • path string
    • ref string
    • expires_at string (date-time)
    • error string

Every answer carries X-Request-Id (give it to support), Apogee-Version: 2026-10-06, and the RateLimit and RateLimit-Policy headers; a replayed answer also carries Idempotent-Replayed: true.

Errors

Errors are application/problem+json with a stable code to switch on (all the codes).

Example

With your key in APOGEE_API_KEY (create one):

Request
curl -X POST 'https://api.apogee.ad/api/v1/uploads' \
  -H "Authorization: Bearer $APOGEE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "ad_account_id": "act_1234567890",
  "files": [
    {
      "name": "NORDLICHT_RAIN_HOOK1_9x16.mp4",
      "size": 48213112,
      "mime_type": "video/mp4"
    }
  ]
}'
Response 201 (shape)
{
  "files": [
    {
      "name": "Nordlicht | Spring launch",
      "upload_url": "https://www.example.com/products/nordlicht-jacket",
      "method": "PUT",
      "headers": {
        "key": "120200000000000001"
      },
      "path": "120200000000000001",
      "ref": "120200000000000001",
      "expires_at": "2026-10-23T09:00:00.000Z",
      "error": "120200000000000001"
    }
  ]
}

Access and cost

PlansPro and Scale.
Scopelaunch (scopes).
CreditsFree up to the daily free reads (5,000 a day on Pro, 10,000 on Scale), then 1 credit per read. A request that fails costs nothing, a replayed one neither (credits).
Rate limitWrite: 120 per 15 minutes on Pro, 240 on Scale (rate limits).
Daily capCounts 2 units toward the 2,000 units one API key can use in 24 hours.

In the MCP

An AI assistant does the same with this tool of the MCP server:

Last updated on . The parameters, limits, credits and error codes of these pages are generated from the code of the Apogee API (contract 2026-10-06).

A question, something missing? Write to hello@apogee.ad.

Book a demo

Pick the time that suits you.

Open in a new tab

Loading the calendar…

Talk to Founder