{"openapi":"3.1.0","info":{"title":"Apogee API","version":"1.0.0","summary":"Launch Meta, TikTok and Snapchat ads from creatives, read performance and run confirmed actions.","description":"The Apogee API launches Meta, TikTok and Snapchat ads from creatives, the way the Apogee app does (an interview, a recap, the user's yes), reads ad accounts and performance, and runs actions (pause, budgets, duplicates…) after a confirmation.\n\n**Apogee has three entry points to the same server code:** the app; the **MCP** (app.apogee.ad/mcp) for AI assistants (Claude, ChatGPT…); and this **REST API** for programs.\n\n## Authentication\n`Authorization: Bearer apk_…`: an API key created in the app (Settings → API). A key is shown once; only its hash is stored. Keys never go in a browser: this API sends no CORS headers (except on this spec).\n\n## Scopes\n- `read`: Read ad accounts, campaigns, ad sets, ads, insights, and follow imports and launches.\n- `launch`: Import and upload creatives, prepare and launch ads, create a campaign.\n- `actions`: Pause, activate, change budgets and targeting, duplicate, create ad sets and ads from existing posts.\n\nA route outside the key's scopes answers 403 `insufficient_scope` with `required_scope`. Each operation lists its scope in `x-apogee-scope`.\nA route the account's plan does not include answers 403 `upgrade_required` with `feature` and `required_plan` (the plan that includes it); a key keeps working once the plan includes it again.\n\n## Limits\nPer API key, per 15 minutes: 600 reads, 120 writes, 30 confirmations (launch plans and actions). Every answer carries `RateLimit-Policy` and `RateLimit`; a 429 carries `Retry-After`. The counters live in each server replica: under load the effective ceiling can be higher, never lower.\nMeta reads also spend a budget of the Apogee account, shared by all its API keys and AI assistants: 1800 units per 15 minutes, 900 per ad account (a launch interview or a launch plan counts 15, any other route that reads Meta 1). Past it: 429 `rate_limited` with `Retry-After`.\nWhen Meta throttles an ad account, the API answers 429 `meta_rate_limited` at once and keeps answering it for 2 minutes for that ad account without calling Meta (for every ad account of the user when Meta throttles the whole Facebook connection).\nTikTok and Snapchat reads and actions spend that platform's own budget instead (never Meta's): 600 calls per 15 minutes per Apogee account and platform, 300 per ad account (a read is a few calls: the account's currency and time zone, the names, the report). Past it: 429 `rate_limited`; the platform's own throttling is 429 `platform_rate_limited`.\nRequests with an unknown, revoked or expired key are limited per address (300 per 15 minutes); a key that worked in the last few minutes is never held back.\n\n## Idempotency\nEvery write that creates something (`POST /imports`, `/launch-plans`, `/launch-plans/{id}/confirm`, `/actions`, `/actions/{id}/confirm`, `/bridge-transfers`, `/bridge-transfers/{id}/confirm`) needs an `Idempotency-Key` header (1-255 visible characters, e.g. a UUID). Retrying with the same key and the same body replays the first successful answer (`Idempotent-Replayed: true`) for 24 hours; the same key with another body is 422 `idempotency_key_reused`; while the first one runs, 409 `idempotency_in_progress`. A launch plan and an action also run once whatever the key.\n\n## Launching\n1. Creatives: `POST /uploads` (PUT each file, then `POST /uploads/confirm`; any platform's ad account), `POST /imports` (a Frame.io, Dropbox or Google Drive link), or `GET /drive-folders`. Each file gives a `ref`.\n2. `POST /ad-accounts/{acc}/launch-questions`: the questions the app asks, with the account's choices.\n3. `POST /launch-plans` with the answers: 422 `missing_answers` lists what is still open (nothing saved); 201 returns the recap and the plan id (valid 24 hours). Show the recap to the person who decides.\n4. `POST /launch-plans/{id}/confirm` after their yes: 202 with the launch id. Then `GET /launches/{id}` until `finished`.\nA launch `interrupted` was cut by a deploy of Apogee: some ads may exist, check Ads Manager before launching again.\nBy hand, as in the app: `ads[].files` links the formats of one creative into one ad (one file per format, never a video with an image), `adsets` arranges the ads into new ad sets (each ad in exactly one), `adset_variants[].ads` gives each new ad set its own existing ads. `GET /ad-accounts/{acc}/campaigns/{id}/latest` finds the latest ad set and ad of a campaign to copy (`copy_adset_from`, `copy_ad_from`).\nTikTok and Snapchat launch the same way: `platform` `tiktok` or `snapchat` in the questions and the plan, their own settings under `tiktok` / `snapchat`, groups made by hand under `adgroups` / `adsquads`. TikTok takes videos, and images as carousels (`tiktok.carousel_mode`, their music from `GET /ad-accounts/{acc}/tiktok-music`), into Standard campaigns or Upgraded Smart+ ones (`tiktok.new_campaign.smart_plus` for a new one), under one of the brand's TikTok accounts; a Spark Ad runs an existing TikTok post (`ads[].spark_post`, from `GET /ad-accounts/{acc}/tiktok-posts`); binding Spark codes (`POST /ad-accounts/{acc}/spark-codes`) answers 400 `request_refused` for now. Snapchat takes videos and images. Their ids come from the same lists with `?platform=tiktok` or `?platform=snapchat`: `GET /ad-accounts`, `/ad-accounts/{acc}/campaigns`, `/adsets` (ad groups, ad squads) and `/ads`; their targeting ids (TikTok interests, behaviors, languages; Snapchat interests, countries) from `GET /ad-accounts/{acc}/targeting-options`. An ad's `concept` is optional on every platform, as in the app: without one, its own ad set (ad group, ad squad), or \"Group 1\" once other ads have one.\n\n## Bridge\n`POST /bridge-transfers` prepares a transfer (ads of one platform launched on another, or a Meta → Meta copy across ad accounts, between ad accounts of yours) without transferring anything; `POST /bridge-transfers/{id}/confirm` runs it after the yes; `GET /bridge-transfers/{id}` follows it; `GET /bridged-ads` lists what was already bridged; `GET /bridged-ads/stats` and `/bridged-ads/daily-stats` are the app's Stats and Daily tabs (each platform in its own currency, never summed together).\n\n## Insights\n`GET /ad-accounts/{acc}/insights`: Meta by default; `platform=tiktok` or `snapchat` with that platform's ad account id (one the key's user connected in Apogee, else 403 `account_not_connected`): the account's totals, one row per campaign / ad set (TikTok ad group, Snapchat ad squad) / ad, or `breakdown=daily`, over a preset or `since` + `until` in the ad account's time zone. Each platform is read on its own: never add Meta, TikTok and Snapchat numbers up (one brand has one account per platform, named differently).\n\n## Actions\n`POST /actions` prepares (what will change is answered, nothing changes), `POST /actions/{id}/confirm` runs it once, within 24 hours. A new ad on an existing post (`create_ad_from_post`) keeps its likes, comments and shares; so does `duplicate_ad`, inside the same ad account.\nTikTok and Snapchat: `set_platform_status` (pause or activate campaigns, ad sets or ads) and `set_platform_daily_budget`, with `platform` and that platform's ad account id, prepared and confirmed the same way. Nothing is activated without the confirmation.\n\n## Errors\nRFC 9457 `application/problem+json`: `type`, `title`, `status`, `detail`, `code` (stable, switch on it), `request_id` (also in `X-Request-Id`: give it to support), and `errors` (validation), `missing` (open launch questions), `required_scope`, `retry_after`, `meta` when relevant. The credits of the plan used (the month's, then its packs): 402 `credits_exhausted` with `buy_url` (reads go on, within their daily cap); a workspace member's monthly cap: 402 `member_cap_reached`; three times the plan's daily free reads: 429 `daily_read_cap` until midnight UTC. A missing or expired Facebook connection is 412 `meta_not_connected` (log in to the app again), a revoked or expired TikTok / Snapchat one 412 `platform_not_connected` (reconnect it in the app), never 401: 401 always means the API key.\n\n## Pagination\nLists take `limit` (1-200, default 50) and `cursor`, and answer `{ data, has_more, next_cursor }`.\n\n## Versioning\n`/v1` only changes in ways that add: new routes, new optional fields, new error codes. Ignore fields you don't know. Unknown request fields are refused (400). Every answer carries `Apogee-Version: 2026-10-06`; a deprecation is announced with `Deprecation` and `Sunset` headers.","contact":{"name":"Apogee","url":"https://apogee.ad","email":"hello@apogee.ad"},"x-apogee-version":"2026-10-06","x-errors-docs":"https://app.apogee.ad/docs/api#errors-"},"servers":[{"url":"https://api.apogee.ad/api/v1","description":"Production"}],"security":[{"apiKey":[]}],"tags":[{"name":"Account","description":"Who am I, the API itself"},{"name":"Ad accounts","description":"Ad accounts and what a launch picks from"},{"name":"Structure","description":"Campaigns, ad sets, ads"},{"name":"Insights","description":"Performance"},{"name":"Creatives","description":"Imports, uploads, Drive folders"},{"name":"Launches","description":"The interview, launch plans, launches"},{"name":"Actions","description":"Prepared then confirmed changes"},{"name":"Bridge","description":"Ads of one platform launched on another, Meta → Meta copies across ad accounts"}],"paths":{"/":{"get":{"operationId":"getRoot","tags":["Account"],"summary":"The API's version and links","security":[],"responses":{"200":{"description":"Version and links","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","tags":["Account"],"summary":"This specification (OpenAPI 3.1)","security":[],"responses":{"200":{"description":"The spec","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/me":{"get":{"operationId":"getMe","tags":["Account"],"summary":"The Apogee account and the API key in use","description":"Any valid key may call it, whatever its scopes.","x-apogee-scope":"any valid key","responses":{"200":{"description":"The user and the key","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/ad-accounts":{"get":{"operationId":"listAdAccounts","tags":["Ad accounts"],"summary":"The ad accounts connected to Apogee","description":"platform: meta (default), tiktok or snapchat: the ids a launch plan, the launch questions and the lists below take with the same platform.","x-apogee-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"platform","in":"query","required":false,"description":"meta (default), tiktok or snapchat","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}}],"responses":{"200":{"description":"A page of ad accounts","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdAccount"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/pages":{"get":{"operationId":"listPages","tags":["Ad accounts"],"summary":"Facebook pages usable with the ad account, with their linked Instagram account","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of Facebook pages","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FacebookPage"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/pixels":{"get":{"operationId":"listPixels","tags":["Ad accounts"],"summary":"Meta pixels of the ad account","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of pixels","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Named"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/pixels/{pixel}/events":{"get":{"operationId":"getPixelEvents","tags":["Ad accounts"],"summary":"A pixel's events: standard events (with their volume), custom events and the account's custom conversions","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"name":"pixel","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"The events to optimize on","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PixelEvents"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/catalogs":{"get":{"operationId":"listCatalogs","tags":["Ad accounts"],"summary":"Product catalogs of the ad account","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of catalogs","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Catalog"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/catalogs/{id}/product-sets":{"get":{"operationId":"listProductSets","tags":["Ad accounts"],"summary":"Product sets of a catalog","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Catalog id","schema":{"type":"string","pattern":"^\\d{1,40}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of product sets","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Catalog"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/custom-audiences":{"get":{"operationId":"listCustomAudiences","tags":["Ad accounts"],"summary":"Custom and lookalike audiences of the ad account","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"A page of audiences","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Audience"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/templates":{"get":{"operationId":"listTemplates","tags":["Ad accounts"],"summary":"The ad set or ad templates saved in Apogee for this account","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"kind","in":"query","required":true,"description":"adset or ad","schema":{"type":"string","enum":["adset","ad"]}}],"responses":{"200":{"description":"A page of templates","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/ad-accounts/{acc}/naming-conventions":{"get":{"operationId":"listNamingConventions","tags":["Ad accounts"],"summary":"The naming conventions saved in Apogee for this account (they read the concepts, hooks and formats in file names)","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of naming conventions","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Named"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/pages/{page}/instagram-accounts":{"get":{"operationId":"listInstagramAccounts","tags":["Ad accounts"],"summary":"The Instagram accounts an ad of a Facebook page can run with","description":"With ad_account_id: the page's own first, then the ones assigned to that ad account in Business Settings, the one a launch uses marked recommended (a page without its own Instagram account runs with the ad account's). Without it: the page's linked account only.","x-apogee-scope":"read","parameters":[{"name":"page","in":"path","required":true,"description":"Facebook page id","schema":{"type":"string","pattern":"^\\d{1,40}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"ad_account_id","in":"query","required":false,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}}],"responses":{"200":{"description":"A page of Instagram accounts","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InstagramAccount"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/pages/{page}/lead-forms":{"get":{"operationId":"listLeadForms","tags":["Ad accounts"],"summary":"Instant forms (lead forms) of a Facebook page","x-apogee-scope":"read","parameters":[{"name":"page","in":"path","required":true,"description":"Facebook page id","schema":{"type":"string","pattern":"^\\d{1,40}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of instant forms","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeadForm"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/pages/{page}/partnership-creators":{"get":{"operationId":"listPartnershipCreators","tags":["Ad accounts"],"summary":"Creators with an approved partnership with the page (partnership ads): Instagram creators who approved its Instagram account, Facebook creators whose Page accepted it","description":"source instagram: give creator_ig_id in the launch plan's ad_settings.partnership; source facebook: creator_fb_page_id alone. A Facebook creator is invited from the app (Ad params → Identity → Partnership ad).","x-apogee-scope":"read","parameters":[{"name":"page","in":"path","required":true,"description":"Facebook page id","schema":{"type":"string","pattern":"^\\d{1,40}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of creators","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Creator"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/posts":{"get":{"operationId":"listAdPosts","tags":["Ad accounts"],"summary":"The posts behind the account's ads (dark posts included): reuse one with a create_ad_from_post action","description":"One row per post, with the ads using it. A new ad on the same post keeps its likes, comments and shares.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"campaign_id","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"A page of posts","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Post"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/pages/{page}/posts":{"get":{"operationId":"listPagePosts","tags":["Ad accounts"],"summary":"A page's published Facebook posts, or the posts of its Instagram account","x-apogee-scope":"read","parameters":[{"name":"page","in":"path","required":true,"description":"Facebook page id","schema":{"type":"string","pattern":"^\\d{1,40}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"source","in":"query","required":false,"description":"Default facebook","schema":{"type":"string","enum":["facebook","instagram"]}},{"name":"instagram_account_id","in":"query","required":false,"description":"source instagram","schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"A page of posts","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Post"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/targeting/search":{"get":{"operationId":"searchTargeting","tags":["Ad accounts"],"summary":"Search Meta targeting: countries, locations (regions, cities), interests, behaviors, demographics, locales","x-apogee-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"type","in":"query","required":true,"schema":{"type":"string","enum":["countries","locations","interests","locales","behaviors","demographics"]}},{"name":"q","in":"query","required":false,"description":"Required except for behaviors and demographics","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"A page of targeting items","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TargetingItem"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/targeting-options":{"get":{"operationId":"listTargetingOptions","tags":["Ad accounts"],"summary":"TikTok and Snapchat targeting choices (interests, behaviors, languages, countries), each with the launch plan field its id goes in","description":"The app's ad group / ad squad drawer pickers. platform tiktok, type interests (tiktok.adgroup_settings.interest_category_ids), behaviors (action_category_ids) or languages (languages); platform snapchat, type interests (snapchat.adsquad_settings.interest_ids) or countries (countries). The account must be one of yours on that platform (404 otherwise). Meta's targeting: GET /targeting/search.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"platform","in":"query","required":true,"description":"tiktok or snapchat","schema":{"type":"string","enum":["tiktok","snapchat"]}},{"name":"type","in":"query","required":true,"description":"TikTok: interests, behaviors, languages. Snapchat: interests, countries","schema":{"type":"string","enum":["interests","behaviors","languages","countries"]}},{"name":"country","in":"query","required":false,"description":"Snapchat interests: the targeted country, as the app reads them (its first targeted country)","schema":{"type":"string","pattern":"^[A-Za-z]{2}$"}}],"responses":{"200":{"description":"A page of targeting choices","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TargetingOption"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/campaigns":{"get":{"operationId":"listCampaigns","tags":["Structure"],"summary":"Campaigns of the ad account (id, name, objective, CBO budget, status)","description":"platform tiktok / snapchat: that platform's campaigns, with its own fields (TikTok: family, search, budget_mode, can_create_adgroup).","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"include_archived","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"platform","in":"query","required":false,"description":"meta (default), tiktok or snapchat","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}}],"responses":{"200":{"description":"A page of campaigns","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/adsets":{"get":{"operationId":"listAdsets","tags":["Structure"],"summary":"Ad sets of the ad account, optionally of one campaign","description":"platform tiktok: its ad groups; snapchat: its ad squads (insertable false: a Lens / special ad squad Apogee can't fill).","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"campaign_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"platform","in":"query","required":false,"description":"meta (default), tiktok or snapchat","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}}],"responses":{"200":{"description":"A page of ad sets","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdSet"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/ads":{"get":{"operationId":"listAds","tags":["Structure"],"summary":"Ads of the ad account, optionally of one campaign or ad set","description":"platform tiktok / snapchat: that platform's ads (adset_id = a TikTok ad group / a Snapchat ad squad).","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","required":false,"description":"Filter on the name (contains, case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"campaign_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"adset_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"platform","in":"query","required":false,"description":"meta (default), tiktok or snapchat","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}}],"responses":{"200":{"description":"A page of ads","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ad"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/campaigns/{id}/latest":{"get":{"operationId":"getLatestInCampaign","tags":["Structure"],"summary":"The most recently created ad set and ad of a campaign (\"copy the latest\")","description":"Their ids, names and creation times. A launch plan copies them with copy_adset_from / copy_ad_from (GET /adsets/{id}/template and /ads/{id}/template show what each one holds). null when the campaign has none.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"name":"id","in":"path","required":true,"description":"Campaign id","schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"The latest ad set and ad","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LatestInCampaign"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/adsets/{id}/template":{"get":{"operationId":"getAdsetTemplate","tags":["Structure"],"summary":"What a launch copying this ad set would take (targeting, event, bid, budget)","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Ad set id","schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"The ad set template (the app's fields, Meta's units)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ads/{id}/template":{"get":{"operationId":"getAdTemplate","tags":["Structure"],"summary":"What a launch copying this ad would take (page, Instagram, texts, URL, CTA, Advantage+ state)","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Ad id","schema":{"type":"string","pattern":"^\\d{1,40}$"}}],"responses":{"200":{"description":"The ad template (the app's fields)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/insights":{"get":{"operationId":"getInsights","tags":["Insights"],"summary":"Performance of one ad account: by level, or broken down by day, placement, age and gender, or device","description":"Meta (default): the numbers of Apogee's Autopilot (spend, impressions, clicks, CTR, CPC, CPM, purchases, revenue, ROAS, CPA, add to cart…), in the account currency. level=account answers one row; the other levels and the breakdowns answer at most 200 rows in all (the pages stop there). Filters: level campaign takes status; level adset and breakdown daily campaign_id; level ad and the other breakdowns campaign_id and adset_id; level account none (any other filter is refused). Dates: Meta's presets.\nTikTok and Snapchat: platform=tiktok or snapchat with that platform's ad account id (GET /ad-accounts?platform=…), an account the key's user connected. level account / campaign / adset (TikTok ad groups, Snapchat ad squads) / ad, or breakdown=daily (every day, zeros included; the account or one campaign_id / adset_id / ad_id; 92 days at most). Dates: the same presets, or since + until (YYYY-MM-DD, both included, 366 days at most), in the ad account's time zone. Levels take campaign_id, adset_id, status (active / paused), min_spend and sort (a metric: cpa, cpc, cpm the lowest first, the others the highest first; default spend), 200 rows at most. Rows carry platform, since, until and currency; the campaign / ad set rows their status and daily_budget. Purchases are TikTok's Complete Payment (website) / Snapchat's conversion_purchases (7-day swipe, no view), revenue their value; clicks = TikTok clicks / Snapchat swipes. These reads spend the user's TikTok / Snapchat budget, never Meta's.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"platform","in":"query","required":false,"description":"meta (default), tiktok or snapchat","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}},{"name":"level","in":"query","required":false,"description":"Default account","schema":{"type":"string","enum":["account","campaign","adset","ad"]}},{"name":"date_preset","in":"query","required":false,"description":"Default last_7d","schema":{"type":"string","enum":["today","yesterday","last_7d","last_14d","last_30d","last_90d","this_month","last_month"]}},{"name":"since","in":"query","required":false,"description":"TikTok / Snapchat: YYYY-MM-DD, with until (both included), instead of date_preset","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"until","in":"query","required":false,"description":"TikTok / Snapchat: YYYY-MM-DD, with since","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"breakdown","in":"query","required":false,"description":"TikTok / Snapchat: daily only","schema":{"type":"string","enum":["daily","placement","age_gender","device"]}},{"name":"campaign_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"adset_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"ad_id","in":"query","required":false,"description":"TikTok / Snapchat, breakdown daily: one ad","schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"status","in":"query","required":false,"description":"Meta: level campaign only; TikTok / Snapchat: any level","schema":{"type":"string","enum":["active","paused"]}},{"name":"sort","in":"query","required":false,"description":"TikTok / Snapchat levels: the metric the rows are sorted by","schema":{"type":"string","enum":["spend","revenue","roas","purchases","ctr","clicks","impressions","cpa","cpc","cpm"]}},{"name":"min_spend","in":"query","required":false,"description":"TikTok / Snapchat levels: only rows that spent at least this much","schema":{"type":"string","pattern":"^\\d{1,9}(\\.\\d{1,2})?$"}}],"responses":{"200":{"description":"A page of insight rows","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InsightRow"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/imports":{"post":{"operationId":"createImport","tags":["Creatives"],"summary":"Import the creatives behind a link into Apogee storage","description":"Frame.io (project, folder or file; a public share link works without a Frame.io account, 20 to 30 s to read), Dropbox (shared file or folder) or Google Drive (file or folder; Frame.io / Drive / Dropbox accounts are the ones connected in the app). Answers 202 with an import id: follow it with GET /imports/{id} until done. The first 200 files of a link at most, counted in the day's upload budget (429 rate_limited past it).","x-apogee-scope":"launch","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"The link"}},"required":["url"],"additionalProperties":false}}}},"responses":{"202":{"description":"The import started","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Import"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/imports/{id}":{"get":{"operationId":"getImport","tags":["Creatives"],"summary":"Where an import is; each COMPLETED file has its ref","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Import id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The import and its files","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Import"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/drive-folders":{"get":{"operationId":"listDriveFolder","tags":["Creatives"],"summary":"The videos and images of a Google Drive folder, with their format (through the Drive connected to Apogee)","x-apogee-scope":"read","parameters":[{"name":"url","in":"query","required":true,"description":"Drive folder link or id","schema":{"type":"string","minLength":1,"maxLength":2048}},{"name":"recursive","in":"query","required":false,"description":"Default true","schema":{"type":"string","enum":["true","false"]}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of files (ref drive:<id>)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFile"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/uploads":{"post":{"operationId":"createUploads","tags":["Creatives"],"summary":"Signed upload URLs for files on the caller's machine (PUT each file, then POST /uploads/confirm)","description":"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).","x-apogee-scope":"launch","parameters":[{"$ref":"#/components/parameters/IdempotencyKeyOptional"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$","description":"Ad account id: Meta act_…, a TikTok advertiser id or a Snapchat ad account id (GET /ad-accounts?platform=…)"},"files":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"File name with its extension"},"size":{"type":"integer","exclusiveMinimum":0,"maximum":524288000,"description":"Bytes (the daily upload budget counts them)"},"mime_type":{"type":"string","maxLength":100}},"required":["name","size"],"additionalProperties":false}}},"required":["ad_account_id","files"],"additionalProperties":false}}}},"responses":{"201":{"description":"One upload slot per file","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadSlots"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/uploads/confirm":{"post":{"operationId":"confirmUploads","tags":["Creatives"],"summary":"Check uploaded files: present and not empty; each one's ref for the launch plans","x-apogee-scope":"launch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"paths":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":2048},"description":"The paths POST /uploads returned"}},"required":["paths"],"additionalProperties":false}}}},"responses":{"200":{"description":"Each file: its ref and size, or the error","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadConfirmations"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/ad-accounts/{acc}/tiktok-posts":{"get":{"operationId":"listTikTokPosts","tags":["Creatives"],"summary":"TikTok Spark Ads: the existing posts a launch plan can run as ads (their likes and comments stay)","description":"source account (default): the video posts of one of the brand's TikTok accounts (identity_id / identity_type from the launch questions' identity choices; default: the first one), a page at a time (next_cursor). source authorized: the posts creators authorized for this ad account with a code (bound in the Apogee app). Each post says whether it can run (usable, refusals) and gives its spark_post for POST /launch-plans ads[].spark_post.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"TikTok advertiser id (GET /ad-accounts?platform=tiktok)","schema":{"type":"string","pattern":"^\\d{1,32}$"}},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["account","authorized"]}},{"name":"identity_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"name":"identity_type","in":"query","required":false,"schema":{"type":"string","enum":["TT_USER","BC_AUTH_TT"]}},{"name":"bc_id","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"}},{"$ref":"#/components/parameters/Cursor"},{"name":"page","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{1,3}$"}}],"responses":{"200":{"description":"A page of posts","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TikTokPosts"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/tiktok-music":{"get":{"operationId":"listTikTokMusic","tags":["Creatives"],"summary":"TikTok carousels: the music a launch plan can give its image ads","description":"TikTok runs images as carousels with a music, from its carousel library. q: a keyword; without one, the musics this ad account used. Each gives its music_id for POST /launch-plans tiktok.ad_settings.music_id; none given, TikTok picks one for each carousel at the launch.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"TikTok advertiser id (GET /ad-accounts?platform=tiktok)","schema":{"type":"string","pattern":"^\\d{1,32}$"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":100}},{"name":"page","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{1,2}$"}}],"responses":{"200":{"description":"A page of musics","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TikTokMusics"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/platform-templates":{"get":{"operationId":"listPlatformTemplates","tags":["Creatives"],"summary":"TikTok / Snapchat: the Quick Bulk Edit templates saved in the app, for a launch plan","description":"The templates saved in the Apogee app (\"Save as template\" in the TikTok ad group / Snapchat ad squad and ad params) for this ad account. level adgroup = an ad group's / ad squad's settings, ad = an ad's. A launch plan uses one as its base: tiktok.adgroup_template_id / tiktok.ad_template_id, snapchat.adsquad_template_id / snapchat.ad_template_id.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"TikTok advertiser id or Snapchat ad account id (GET /ad-accounts?platform=…)","schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{0,63}$"}},{"name":"platform","in":"query","required":true,"schema":{"type":"string","enum":["tiktok","snapchat"]}},{"name":"level","in":"query","required":true,"schema":{"type":"string","enum":["adgroup","ad"]}}],"responses":{"200":{"description":"The templates, newest first","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformTemplates"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/ad-accounts/{acc}/spark-codes":{"post":{"operationId":"bindSparkCodes","tags":["Creatives"],"summary":"TikTok Spark Ads: bind creators' authorization codes (refused for now)","description":"Binding creators' Spark codes is not available yet on TikTok through Apogee's MCP / API: bind them in the Apogee app (TikTok › Ad params › Source); their posts then launch with ads[].spark_post (list_tiktok_posts source authorized): this route answers 400 request_refused and binds nothing.","x-apogee-scope":"launch","parameters":[{"name":"acc","in":"path","required":true,"description":"TikTok advertiser id (GET /ad-accounts?platform=tiktok)","schema":{"type":"string","pattern":"^\\d{1,32}$"}}],"responses":{"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/ad-accounts/{acc}/launch-questions":{"post":{"operationId":"getLaunchQuestions","tags":["Launches"],"summary":"The launch interview: every question the app asks before a launch, with the choices read from the account","description":"Send files (names, refs, formats) once the creatives are known: the account's naming convention reads them and the ads are proposed (one creative in 9:16 / 4:5 / 1:1 = one ad). Send the answers so far to get the choices that depend on them.","x-apogee-scope":"read","parameters":[{"name":"acc","in":"path","required":true,"description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"description":"Default meta. tiktok / snapchat: the same interview and arguments where they mean the same, their own settings under `tiktok` / `snapchat`, groups made by hand under `adgroups` / `adsquads`","type":"string","enum":["meta","tiktok","snapchat"]},"files":{"maxItems":500,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"File name with its extension"},"ref":{"description":"drive:<id> or the URL of the file in Apogee storage","type":"string","maxLength":2048},"mimeType":{"type":"string","maxLength":100},"kind":{"type":"string","enum":["video","image"]},"format":{"description":"Measured format (list_drive_folder, ffprobe): 9:16, 4:5, 1:1, 16:9","type":"string","maxLength":10},"folder":{"description":"Subfolder (list_drive_folder)","type":"string","maxLength":500},"durationS":{"description":"Length in seconds (list_drive_folder durationS, ffprobe): files of one length in different formats are flagged as maybe one creative","type":"number","minimum":0,"maximum":36000}},"required":["name"]}},"answers":{"description":"The answers so far, with prepare_launch's argument names","anyOf":[{"type":"object","properties":{"campaign_id":{"description":"Question \"campaign\"","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"existing_adset_ids":{"anyOf":[{"type":"array","items":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]}},{"type":"null"}]},"existing_adsets":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"campaign_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},"adset_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]}},"required":["campaign_id","adset_id"],"additionalProperties":{}}},{"type":"null"}]},"copy_adset_from":{"description":"An ad set to duplicate","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"copy_ad_from":{"description":"An ad to duplicate","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"adset_settings":{"anyOf":[{"type":"object","properties":{"pixel_id":{"description":"A pixel","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"custom_conversion_id":{"description":"A custom conversion","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"application_id":{"description":"app_installs: the app to promote","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]}},"additionalProperties":{}},{"type":"null"}]},"ad_settings":{"anyOf":[{"type":"object","properties":{"page_id":{"description":"A Facebook page","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"instagram_id":{"description":"An Instagram account","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"lead_form_id":{"description":"An instant form","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"partnership":{"anyOf":[{"type":"object","properties":{"creator_ig_id":{"description":"An approved creator","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"creator_fb_page_id":{"description":"The creator's Facebook page (alone: a Facebook creator)","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]}},"additionalProperties":{}},{"type":"null"}]}},"additionalProperties":{}},{"type":"null"}]},"products":{"anyOf":[{"type":"object","properties":{"catalog_id":{"description":"A catalog","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"product_set_id":{"description":"A product set","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]}},"additionalProperties":{}},{"type":"null"}]},"ads":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"source_ad_id":{"description":"An existing ad to reuse with its post","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]}},"additionalProperties":{}}},{"type":"null"}]},"adset_variants":{"anyOf":[{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}},{"type":"null"}]},"source_campaign_id":{"description":"Lists the existing ads of this campaign only","anyOf":[{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$"},{"type":"integer","minimum":0,"maximum":9007199254740991}]},{"type":"null"}]},"nomenclature":{"anyOf":[{"type":"object","properties":{"config_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]}},"additionalProperties":{}},{"type":"null"}]},"grouping_mode":{"description":"The app's switch: \"names\" reads the file names with a saved convention, \"by_hand\" groups the files by hand (formats of one creative linked by name, every other file its own ad). Default: names only when a convention reads every file, else by hand","type":"string","enum":["by_hand","names"]}},"additionalProperties":{}},{"type":"object","properties":{"campaign_id":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"campaign\""},{"type":"null"}]},"copy_adset_from":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad group / ad squad to copy, or \"latest\""},{"type":"null"}]},"copy_ad_from":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad to copy, or \"latest\""},{"type":"null"}]},"existing_adset_ids":{"anyOf":[{"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad group / ad squad"}},{"type":"null"}]}},"additionalProperties":{}}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"The questions, in order","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchQuestions"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/launch-plans":{"post":{"operationId":"createLaunchPlan","tags":["Launches"],"summary":"Prepare a launch from the interview's answers, WITHOUT creating anything","description":"Answers 201 with the full recap (show it to the user) and the plan id, valid 24 hours; or 422 missing_answers with the open questions (nothing saved). Only the app's documented defaults are applied, and listed. Files: drive:<id>, or your own files in Apogee storage (each checked present). Advantage+ enhancements: only those in advantage_plus.opt_in are ON. platform tiktok / snapchat: the same answers where they mean the same, their own settings under tiktok / snapchat, groups made by hand under adgroups / adsquads; their files must be in Apogee storage (a Drive file: POST /imports first).","x-apogee-scope":"launch","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"description":"Default meta. tiktok / snapchat: the same interview and arguments where they mean the same, their own settings under `tiktok` / `snapchat`, groups made by hand under `adgroups` / `adsquads`","type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$","description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id"},"campaign_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"campaign\": an existing campaign"},"structure":{"description":"Question \"test_structure\": 1 Adset 1 Ad, 1 Concept 1 Adset, All in One, Insert in Adset","type":"string","enum":["one_adset_one_ad","one_concept_one_adset","all_in_one","insert_in_adset"]},"all_in_one_name":{"description":"All in One: the ad set name (required, unless adset_variants)","type":"string","maxLength":255},"existing_adset_ids":{"description":"Insert: the existing ad sets (Meta), ad groups (TikTok) or ad squads (Snapchat), of campaign_id only (list_adsets with campaign_id lists them)","maxItems":50,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad set / ad group / ad squad id"}},"existing_adsets":{"description":"Existing ads (source_ad_id) with insert_in_adset: existing ad sets of one or several campaigns of the ad account, each with its campaign (list_adsets gives campaign_id), every ad in each or its own (ads). Instead of existing_adset_ids; campaign_id defaults to the first one's. 30 ad sets and 300 ads written at most","minItems":1,"maxItems":30,"type":"array","items":{"type":"object","properties":{"campaign_id":{"type":"string","pattern":"^\\d{1,40}$","description":"The ad set's campaign"},"adset_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An existing ad set"},"ads":{"description":"The ads that go into this ad set, each by its ad_name or its source_ad_id. Left out: every ad","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":255}}},"required":["campaign_id","adset_id"],"additionalProperties":false}},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"source_ad_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An ad of this account to reuse with its post (likes and comments stay). Instead of files (get_launch_questions → creatives.choices.existing_ads)"},"files":{"description":"New files: the formats of ONE creative, linked by hand or as proposed (one file per format: 9:16, 4:5, 1:1, 16:9; never a video with an image). Leave out with source_ad_id","minItems":1,"maxItems":10,"type":"array","items":{"type":"object","properties":{"ref":{"type":"string","minLength":1,"maxLength":2048,"description":"drive:<id> (list_drive_folder), or the Apogee storage URL returned by get_upload_urls / confirm_uploads / import_status (your own files only)"},"name":{"type":"string","maxLength":255},"mimeType":{"type":"string","maxLength":100},"format":{"description":"9:16, 4:5, 1:1, 16:9 or auto","type":"string","maxLength":10}},"required":["ref"]}},"concept":{"description":"Concept = ad set name in 1 Concept 1 Adset. Files without it: the ad's own (its name), or \"Group 1\" once other ads have one (the app's Group by hand)","type":"string","minLength":1,"maxLength":255},"ad_name":{"description":"Ad name = ad set name in 1 Adset 1 Ad. Required with files; existing ads: default = the source ad's name + \" - Copy with post ID\"","type":"string","minLength":1,"maxLength":255},"copy":{"description":"This ad's own texts (question \"copy\"). Not with source_ad_id: an existing ad keeps its post","type":"object","properties":{"primary_texts":{"maxItems":5,"type":"array","items":{"type":"string","maxLength":5000}},"headlines":{"maxItems":5,"type":"array","items":{"type":"string","maxLength":255}},"description":{"type":"string","maxLength":255},"website_url":{"type":"string","maxLength":2048},"call_to_action":{"type":"string","maxLength":40}}},"spark_post":{"description":"TikTok Spark Ads: an existing TikTok post run as this ad instead of files (its caption is the ad text, its likes and comments stay), as list_tiktok_posts gives it","type":"object","properties":{"tiktok_item_id":{"type":"string","pattern":"^\\d{1,40}$","description":"The TikTok post (list_tiktok_posts: its spark_post)"},"identity":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"The account that posted it"},"type":{"type":"string","enum":["TT_USER","BC_AUTH_TT","AUTH_CODE"],"description":"TT_USER / BC_AUTH_TT: one of the brand's TikTok accounts; AUTH_CODE: a creator who authorized the post for this ad account"},"bc_id":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"BC_AUTH_TT: its Business Center"},{"type":"null"}]}},"required":["id","type"],"additionalProperties":false}},"required":["tiktok_item_id","identity"],"additionalProperties":false}}},"description":"The confirmed ads (get_launch_questions proposed_ads, corrected by the user), or the existing ads to reuse (each either files or source_ad_id, all the same kind; 50 existing ads max)"},"adset_variants":{"description":"all_in_one: the same ads in 1-5 new ad sets, each with its own bid / budget (e.g. two cost caps), or each with its own ads (ads)","minItems":1,"maxItems":5,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"The new ad set's name"},"bid_amount":{"description":"Cost cap / bid cap, in the account currency","type":"number","exclusiveMinimum":0},"roas_floor":{"description":"Minimum ROAS strategy, e.g. 2.5","type":"number","exclusiveMinimum":0},"daily_budget":{"description":"ABO only, account currency","type":"number","exclusiveMinimum":0},"ads":{"description":"Existing ads (source_ad_id) only: the ads that go into this new ad set, each by its ad_name or its source_ad_id. Left out on every ad set: every ad in each. Given on one: every ad set needs its own, and every ad must be in one at least","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":255}}},"required":["name"]}},"adsets":{"description":"New files: the ads arranged into new ad sets by hand, on top of structure one_adset_one_ad, one_concept_one_adset or all_in_one. Launched as 1 Concept 1 Adset (each ad set = a concept), the ad names unchanged; every ad set takes the plan's ad set settings. Not with insert_in_adset, adset_variants or existing ads","minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"The new ad set's name"},"ads":{"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ads that go into it, by their ad_name (each ad in exactly one ad set)"}},"required":["name","ads"],"additionalProperties":false}},"nomenclature":{"description":"Question \"nomenclature\", when a saved convention reads the names: named in the recap. Files grouped by hand: leave it out","type":"object","properties":{"config_id":{"description":"The saved naming convention used, null when none","anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"name":{"type":"string","maxLength":255},"confirmed":{"type":"boolean","const":true,"description":"true = the user validated the parsed concepts / iterations / formats"}},"required":["confirmed"]},"grouping_confirmed":{"description":"Question \"grouping\": true = the user validated the ads (their names and files), read by a convention or grouped by hand","type":"boolean","const":true},"copy_adset_from":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"starting_point\": the ad set / ad group / ad squad whose settings are copied (\"latest\" = TikTok: the latest ad group of campaign_id)"},"adset_template_id":{"description":"Question \"starting_point\": a saved Apogee ad set template","type":"string","maxLength":64},"adset_settings":{"description":"A new ad set (questions \"audience\", \"tracking\"), or the changes to a copied ad set / template","type":"object","properties":{"goal":{"description":"New ad set only. Default: from the campaign objective","type":"string","enum":["sales","leads_website","leads_instant_form","traffic","engagement","awareness","app_installs"]},"countries":{"description":"ISO codes, e.g. [\"FR\"] (a new ad set needs countries, regions or cities)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"regions":{"description":"Region keys from search_targeting(type: locations)","maxItems":200,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":32}},"required":["key"]}},"cities":{"description":"City keys from search_targeting(type: locations)","maxItems":250,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":32},"radius":{"type":"number","minimum":1,"maximum":80},"distance_unit":{"type":"string","enum":["kilometer","mile"]}},"required":["key"]}},"age_min":{"type":"integer","minimum":13,"maximum":65},"age_max":{"type":"integer","minimum":13,"maximum":65},"genders":{"description":"Default all","type":"string","enum":["all","men","women"]},"locales":{"description":"Language keys from search_targeting(type: locales)","maxItems":50,"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"advantage_audience":{"description":"Default true (broad)","type":"boolean"},"custom_audience_ids":{"description":"list_custom_audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"excluded_audience_ids":{"description":"list_custom_audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"interests":{"description":"search_targeting(type: interests)","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"behaviors":{"description":"search_targeting(type: behaviors)","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"life_events":{"description":"search_targeting(type: demographics): the app's demographics / life events","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"placements":{"description":"\"advantage\" (Advantage+ placements, the default) or the platforms to keep","anyOf":[{"type":"string","const":"advantage"},{"type":"object","properties":{"publisher_platforms":{"minItems":1,"type":"array","items":{"type":"string","enum":["facebook","instagram","messenger","audience_network"]}}},"required":["publisher_platforms"]}]},"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (list_pixels)"},"event":{"description":"Meta enum: PURCHASE, LEAD, CONTENT_VIEW, INITIATED_CHECKOUT, ADD_TO_CART, COMPLETE_REGISTRATION…","type":"string","maxLength":64},"custom_event_str":{"description":"A pixel custom event name (sent as OTHER + this name)","type":"string","maxLength":100},"custom_conversion_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom conversion (sent alone)"},"optimization_goal":{"description":"New ad set: overrides the default optimization (e.g. LINK_CLICKS for traffic). app_installs: APP_INSTALLS (default), OFFSITE_CONVERSIONS + event (an app event) or VALUE","type":"string","maxLength":64},"bid_strategy":{"description":"ABO: the new ad sets' strategy (default Lowest cost, the highest volume). CBO: must be the campaign's (or leave it out)","type":"string","enum":["LOWEST_COST_WITHOUT_CAP","COST_CAP","LOWEST_COST_WITH_BID_CAP","LOWEST_COST_WITH_MIN_ROAS"]},"bid_amount":{"description":"COST_CAP / LOWEST_COST_WITH_BID_CAP: the cost per result goal (cost cap) or bid cap of every new ad set, account currency (adset_variants: one each)","type":"number","exclusiveMinimum":0},"roas_floor":{"description":"LOWEST_COST_WITH_MIN_ROAS: the minimum ROAS of every new ad set, e.g. 2.5 (adset_variants: one each)","type":"number","exclusiveMinimum":0},"attribution":{"description":"Default 7-day click, 1-day view, 1-day engaged view","type":"object","properties":{"click":{"type":"string","enum":["1_day","7_days"]},"view":{"type":"string","enum":["none","1_day","7_days"]},"engaged_view":{"type":"string","enum":["none","1_day","7_days"]}},"required":["click"]},"application_id":{"type":"string","pattern":"^\\d{1,40}$","description":"app_installs: the app to promote (get_launch_questions → tracking.choices.apps; default: the ad account's only app)"},"object_store_url":{"description":"app_installs: its App Store / Play Store link (choices.apps[].store_urls; default: the app's only one). The ads link to it","type":"string","maxLength":2048},"customer_lifecycle":{"description":"Sales campaigns only: the new ad sets' Customer lifecycle strategy. Left out: a copied ad set or template keeps its own, a new ad set gets conversions from all audiences","type":"object","properties":{"goal":{"type":"string","enum":["BROAD","EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS","EXCLUDE_EXISTING_CUSTOMERS"],"description":"BROAD = \"Get conversions from all audiences\" (the default); EXCLUDE_EXISTING_CUSTOMERS = \"New customer acquisition\" (Meta excludes the existing customers); EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS = New customer acquisition, the engaged audiences excluded too"},"existing_customers":{"description":"The custom audiences of the existing customers (list_custom_audiences). Default: the ad account's own definition of its existing customers, when it has one","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"engaged_audiences":{"description":"EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS only (required there): the custom audiences of the engaged audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}}},"required":["goal"],"additionalProperties":false},"dsa":{"description":"New ad sets in the EU: their beneficiary and payer. Left out: a template's own, else the ad account's (get_launch_questions → advertiser.current)","type":"object","properties":{"beneficiary":{"type":"string","minLength":1,"maxLength":255,"description":"Who the ads promote (Ads Manager: Advertiser)"},"payer":{"description":"Who pays for them, when another (default: the beneficiary)","type":"string","minLength":1,"maxLength":255}},"required":["beneficiary"],"additionalProperties":false}},"additionalProperties":false},"copy_ad_from":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"starting_point\": the ad whose settings are copied (\"latest\" = TikTok: the latest ad)"},"ad_template_id":{"description":"Question \"starting_point\": a saved Apogee ad template","type":"string","maxLength":64},"ad_settings":{"description":"A new ad (questions \"identity\", \"destination\"), or the changes to a copied ad / template","type":"object","properties":{"page_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A Facebook page (list_pages)"},"instagram_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$","description":"Default: the page's linked Instagram"},{"type":"null"}]},"partnership":{"description":"A partnership ad with a creator who approved the brand's Instagram account, or whose Facebook Page accepted the brand's Page; null = none (default)","anyOf":[{"type":"object","properties":{"creator_ig_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An Instagram creator (get_launch_questions → identity.choices.partnership_creators, source instagram)"},"creator_username":{"type":"string","maxLength":100},"creator_fb_page_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$","description":"An Instagram creator's Page (default: read from the approved creators; null: none), or alone a Facebook creator (source facebook)"},{"type":"null"}]},"creator_name":{"description":"A Facebook creator's Page name (as listed)","type":"string","maxLength":200},"ad_code":{"description":"Not used: a partnership ad code boosts the creator's own post, Apogee launches your files. Use creator_ig_id","type":"string","maxLength":200},"identity_mode":{"description":"advertiser_primary = your brand first (default); creator_primary = the creator first (on Instagram only when the creator has no Facebook Page)","type":"string","enum":["advertiser_primary","creator_primary"]},"header_display":{"description":"dynamic (default, Meta picks; optimizes on Instagram only), both identities, or the first identity only","type":"string","enum":["dynamic","both","primary_only"]}},"additionalProperties":false},{"type":"null"}]},"website_url":{"description":"Required except for instant forms and app ads (they link to adset_settings.object_store_url)","type":"string","maxLength":2048},"url_parameters":{"description":"UTM parameters, \"\" = none (required for a new ad)","type":"string","maxLength":1000},"call_to_action":{"description":"Required for a new ad, e.g. SHOP_NOW, LEARN_MORE, SIGN_UP. An app ad: INSTALL_MOBILE_APP (default), USE_MOBILE_APP, PLAY_GAME…","type":"string","maxLength":40},"lead_form_id":{"type":"string","pattern":"^\\d{1,40}$","description":"Instant form leads (list_lead_forms)"},"display_link":{"type":"string","maxLength":255}},"additionalProperties":false},"advantage_plus":{"description":"Question \"advantage_plus\" (required)","type":"object","properties":{"opt_in":{"type":"array","items":{"type":"string","enum":["text_optimizations","product_tags","creative_stickers","inline_comment","enhance_cta","reveal_details_over_time","show_destination_blurbs","show_summary","optimize_website_destination","shop","product_browsing","browser_addons","image_brightness_and_contrast","image_templates","image_touchups","video_auto_crop","video_filtering"]},"description":"The enhancements the user turned ON; every other one is sent OFF. [] = all off"},"multi_advertiser_ads":{"description":"Multi-advertiser ads (the ad's Format in Ads Manager): false = out (OPT_OUT). Left out: the copied ad's or template's, else in (Meta's default)","type":"boolean"}},"required":["opt_in"]},"products":{"description":"Question \"products\" (required when the account has a catalog)","type":"object","properties":{"show":{"type":"boolean","description":"\"Show relevant products\" from the catalog"},"catalog_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A catalog (get_launch_questions → products)"},"product_set_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A product set of that catalog"}},"required":["show"]},"daily_budget":{"description":"ABO: daily budget of each new ad set, account currency (required)","type":"number","exclusiveMinimum":0},"launch_status":{"description":"Created Paused (default), Live Now, Scheduled & Paused, Scheduled & Live","type":"string","enum":["CREATED_PAUSED","LIVE_NOW","SCHEDULED_PAUSED","SCHEDULED_LIVE"]},"schedule":{"description":"Scheduled & Paused / Scheduled & Live. Insert in Adset on Meta: each ad's start, Sales and App promotion campaigns only","type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"YYYY-MM-DD"},"time":{"type":"string","pattern":"^\\d{2}:\\d{2}$","description":"HH:MM, in time_zone"},"time_zone":{"description":"The IANA zone of date and time, e.g. Europe/London for a UK campaign. Default the ad account's","type":"string","maxLength":64}},"required":["date","time"]},"ad_overrides":{"description":"Advanced: raw ad template fields (description, display_link, url_parameters, website_url, call_to_action, instagram_account_id, lead_gen_form_id, primary_texts, headlines)","type":"object","properties":{"description":{},"display_link":{},"url_parameters":{},"website_url":{},"call_to_action":{},"instagram_account_id":{},"lead_gen_form_id":{},"primary_texts":{},"headlines":{}},"additionalProperties":false},"adset_overrides":{"description":"Advanced: raw ad set template fields (name, billing_event, optimization_goal, destination_type, daily_min_spend_target, daily_spend_cap, start_time, end_time, bid_strategy, bid_amount, bid_constraints, attribution_spec, attribution_setting, targeting), Meta's units","type":"object","properties":{"name":{},"billing_event":{},"optimization_goal":{},"destination_type":{},"daily_min_spend_target":{},"daily_spend_cap":{},"start_time":{},"end_time":{},"bid_strategy":{},"bid_amount":{},"bid_constraints":{},"attribution_spec":{},"attribution_setting":{},"targeting":{}},"additionalProperties":false},"adgroups":{"description":"TikTok: ad groups made by hand, instead of structure","minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"A new ad group's name","type":"string","minLength":1,"maxLength":255},"existing_adgroup_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An existing ad group to fill instead (all groups existing, or all new)"},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ad_name of each ad in it (every ad in exactly one group)"},"settings":{"description":"This ad group's own settings, over the shared ones","type":"object","properties":{"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (get_launch_questions → tracking.choices.pixels)"},"optimization_event":{"description":"TikTok's optimization_event: SHOPPING (purchase), INITIATE_ORDER, ON_WEB_CART, ON_WEB_DETAIL, ON_WEB_REGISTER, FORM…","type":"string","maxLength":64},"bid_type":{"description":"Default BID_TYPE_NO_BID (maximum delivery); BID_TYPE_CUSTOM = cost cap (bid)","type":"string","enum":["BID_TYPE_NO_BID","BID_TYPE_CUSTOM"]},"bid":{"description":"Cost cap per conversion (BID_TYPE_CUSTOM), account currency","type":"number","exclusiveMinimum":0},"pacing":{"type":"string","enum":["PACING_MODE_SMOOTH","PACING_MODE_FAST"]},"countries":{"description":"ISO codes, read into TikTok location ids (or location_ids)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"location_ids":{"maxItems":500,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A TikTok location id"}},"age_groups":{"description":"[] or absent = every age","maxItems":6,"type":"array","items":{"type":"string","enum":["AGE_13_17","AGE_18_24","AGE_25_34","AGE_35_44","AGE_45_54","AGE_55_100"]}},"gender":{"type":"string","enum":["GENDER_UNLIMITED","GENDER_MALE","GENDER_FEMALE"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"An interest category"}},"action_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A behaviour category"}},"audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"excluded_audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"placements":{"description":"Default TikTok only","minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["PLACEMENT_TIKTOK","PLACEMENT_PANGLE","PLACEMENT_GLOBAL_APP_BUNDLE"]}}},"additionalProperties":false},"daily_budget":{"description":"ABO: this one's budget (default daily_budget)","type":"number","exclusiveMinimum":0}},"required":["ads"],"additionalProperties":false}},"adsquads":{"description":"Snapchat: ad squads made by hand, instead of structure","minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"A new ad squad's name","type":"string","minLength":1,"maxLength":255},"existing_adsquad_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An existing ad squad to fill instead (all groups existing, or all new)"},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ad_name of each ad in it (every ad in exactly one group)"},"settings":{"description":"This ad squad's own settings, over the shared ones","type":"object","properties":{"optimization_goal":{"description":"Default PIXEL_PURCHASE. The PIXEL_ goals need pixel_id (and enough of that event on the pixel lately: get_launch_questions tracking.choices.optimization_goals); SWIPES and LANDING_PAGE_VIEW need none","type":"string","enum":["PIXEL_PURCHASE","PIXEL_ADD_TO_CART","PIXEL_SIGNUP","PIXEL_PAGE_VIEW","SWIPES","LANDING_PAGE_VIEW"]},"pixel_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap pixel (get_launch_questions → tracking.choices.pixels)"},"bid_strategy":{"description":"Default AUTO_BID","type":"string","enum":["AUTO_BID","LOWEST_COST_WITH_MAX_BID","TARGET_COST"]},"bid":{"description":"LOWEST_COST_WITH_MAX_BID / TARGET_COST: the bid, account currency","type":"number","exclusiveMinimum":0},"pacing_type":{"description":"Default STANDARD","type":"string","enum":["STANDARD","ACCELERATED"]},"conversion_window":{"description":"Default Snapchat's SWIPE_28DAY_VIEW_1DAY","type":"string","enum":["SWIPE_28DAY_VIEW_1DAY","SWIPE_7DAY"]},"countries":{"description":"ISO codes (at least one for a new ad squad)","minItems":1,"maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"region_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":32}},"min_age":{"description":"Default 18 for a new ad squad: Snapchat refuses its goal for under-18s in the EU, the EEA, Switzerland and the UK","type":"integer","minimum":13,"maximum":65},"max_age":{"type":"integer","minimum":13,"maximum":65},"genders":{"type":"string","enum":["all","men","women"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":64}},"segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}},"excluded_segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}}},"additionalProperties":false},"daily_budget":{"description":"ABO: this one's budget (default daily_budget)","type":"number","exclusiveMinimum":0}},"required":["ads"],"additionalProperties":false}},"tiktok":{"description":"TikTok's own settings (platform tiktok)","type":"object","properties":{"new_campaign":{"description":"A new Sales campaign (website conversions; Standard, or Upgraded Smart+), created by the launch (instead of campaign_id)","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"budget_type":{"type":"string","enum":["abo","cbo"],"description":"abo = a budget per ad group (daily_budget); cbo = the campaign's budget"},"budget":{"description":"CBO: the campaign budget, account currency","type":"number","exclusiveMinimum":0},"budget_mode":{"description":"Default daily","type":"string","enum":["daily","lifetime"]},"smart_plus":{"description":"true = an Upgraded Smart+ campaign (website Sales), as the app's Create Campaign: up to 30 ad groups of 30 ads, one ad per creative (its texts rotate inside), TikTok's dynamic CTA (ad_settings.cta_language / cta_texts), no Spark post. Default: a Standard campaign","type":"boolean"}},"required":["name","budget_type"],"additionalProperties":false},"adgroup_settings":{"description":"A new ad group's settings, or the changes to a copied one (copy_adset_from)","type":"object","properties":{"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (get_launch_questions → tracking.choices.pixels)"},"optimization_event":{"description":"TikTok's optimization_event: SHOPPING (purchase), INITIATE_ORDER, ON_WEB_CART, ON_WEB_DETAIL, ON_WEB_REGISTER, FORM…","type":"string","maxLength":64},"bid_type":{"description":"Default BID_TYPE_NO_BID (maximum delivery); BID_TYPE_CUSTOM = cost cap (bid)","type":"string","enum":["BID_TYPE_NO_BID","BID_TYPE_CUSTOM"]},"bid":{"description":"Cost cap per conversion (BID_TYPE_CUSTOM), account currency","type":"number","exclusiveMinimum":0},"pacing":{"type":"string","enum":["PACING_MODE_SMOOTH","PACING_MODE_FAST"]},"countries":{"description":"ISO codes, read into TikTok location ids (or location_ids)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"location_ids":{"maxItems":500,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A TikTok location id"}},"age_groups":{"description":"[] or absent = every age","maxItems":6,"type":"array","items":{"type":"string","enum":["AGE_13_17","AGE_18_24","AGE_25_34","AGE_35_44","AGE_45_54","AGE_55_100"]}},"gender":{"type":"string","enum":["GENDER_UNLIMITED","GENDER_MALE","GENDER_FEMALE"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"An interest category"}},"action_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A behaviour category"}},"audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"excluded_audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"placements":{"description":"Default TikTok only","minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["PLACEMENT_TIKTOK","PLACEMENT_PANGLE","PLACEMENT_GLOBAL_APP_BUNDLE"]}}},"additionalProperties":false},"ad_settings":{"description":"The ads' TikTok account (and whether their videos show on its profile), destination and CTA (new, or the changes to a copied ad); Smart+ and carousel settings","type":"object","properties":{"identity":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"The identity id (get_launch_questions → identity.choices.identities)"},"type":{"type":"string","enum":["TT_USER","BC_AUTH_TT"],"description":"One of the brand's TikTok accounts: TT_USER, or BC_AUTH_TT through its Business Center (TikTok refuses a custom identity on these ads)"},"bc_id":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"BC_AUTH_TT: the Business Center"},{"type":"null"}]}},"required":["id","type"],"additionalProperties":false},"show_on_profile":{"description":"The app's \"Also show the video on the TikTok profile\": true = the video is also posted on the TikTok account's profile; default: it only runs as an ad (TikTok's default). Not where TikTok keeps the videos ads-only (get_launch_questions identity.show_on_profile)","type":"boolean"},"website_url":{"description":"Apogee's TikTok tracking replaces its own utm_ parameters (no UTM option on TikTok: the app's final URL)","type":"string","maxLength":2048},"call_to_action":{"description":"Default SHOP_NOW (a Standard ad's; a Smart+ ad runs TikTok's dynamic CTA: cta_language, cta_texts)","type":"string","enum":["SHOP_NOW","BUY_NOW","ORDER_NOW","LEARN_MORE","SIGN_UP","DOWNLOAD_NOW","CONTACT_US","BOOK_NOW"]},"cta_language":{"description":"Smart+: the language of TikTok's dynamic call to action when the ad group lends none (default en)","type":"string","enum":["en","fr","de","es","it","nl","pt","pl","sv"]},"cta_texts":{"description":"Smart+: the calls to action kept among the ones TikTok offers in cta_language (default: TikTok's whole list)","maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":40}},"automations":{"description":"Smart+: TikTok's automations of the ads (as Meta's Advantage+ creative enhancements), each off unless turned on","type":"object","properties":{"auto_add":{"description":"TikTok adds assets of its own","type":"boolean"},"enhancements":{"maxItems":5,"type":"array","items":{"type":"string","enum":["TRANSLATE_AND_DUB","MUSIC_REFRESH","VIDEO_QUALITY","IMAGE_QUALITY","IMAGE_RESIZE"]}}},"additionalProperties":false},"music_id":{"description":"Carousels (image ads): the music, one of list_tiktok_music; default TikTok's pick at the launch","type":"string","pattern":"^\\d{1,40}$"}},"additionalProperties":false},"carousel_mode":{"description":"Images run as carousels (TikTok's image ads), as the app's Configure switch: single (default) = each image ad a carousel of its image; by_concept = a concept's images one carousel ad named after the concept (35 images at most, its first ad's settings and texts)","type":"string","enum":["single","by_concept"]},"adgroup_template_id":{"description":"Quick Bulk Edit: a saved ad group template (list_platform_templates level adgroup), the base of the new ad groups' settings (instead of copy_adset_from); adgroup_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ad_template_id":{"description":"Quick Bulk Edit: a saved ad template (list_platform_templates level ad), the base of the ads' settings (instead of copy_ad_from); ad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"time_zone":{"description":"The IANA zone of schedule, e.g. Europe/London for a UK campaign. Default the advertiser's","type":"string","maxLength":64},"end_date":{"description":"A lifetime campaign budget (CBO, budget_mode lifetime, a new campaign or an existing one): the date it runs to, YYYY-MM-DD in the schedule's time zone, after the launch (a scheduled launch: TikTok spreads the budget until then). Ignored for a daily budget","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"end_time":{"description":"HH:MM of end_date, default the start's time","type":"string","pattern":"^\\d{2}:\\d{2}$"}},"additionalProperties":false},"snapchat":{"description":"Snapchat's own settings (platform snapchat)","type":"object","properties":{"new_campaign":{"description":"A new Sales campaign, created by the launch (instead of campaign_id)","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"budget_type":{"type":"string","enum":["abo","cbo"],"description":"abo = a budget per ad squad (daily_budget, 5 minimum); cbo = the campaign's (20 minimum per day), Snapchat's Smart Budget: its ad squads share their optimisation goal, pixel, bid strategy and conversion window (get_launch_questions tracking.choices); a lower budget is raised to it"},"budget":{"description":"CBO: the campaign budget per day, account currency","type":"number","exclusiveMinimum":0}},"required":["name","budget_type"],"additionalProperties":false},"adsquad_settings":{"description":"A new ad squad's settings, or the changes to a copied one (copy_adset_from)","type":"object","properties":{"optimization_goal":{"description":"Default PIXEL_PURCHASE. The PIXEL_ goals need pixel_id (and enough of that event on the pixel lately: get_launch_questions tracking.choices.optimization_goals); SWIPES and LANDING_PAGE_VIEW need none","type":"string","enum":["PIXEL_PURCHASE","PIXEL_ADD_TO_CART","PIXEL_SIGNUP","PIXEL_PAGE_VIEW","SWIPES","LANDING_PAGE_VIEW"]},"pixel_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap pixel (get_launch_questions → tracking.choices.pixels)"},"bid_strategy":{"description":"Default AUTO_BID","type":"string","enum":["AUTO_BID","LOWEST_COST_WITH_MAX_BID","TARGET_COST"]},"bid":{"description":"LOWEST_COST_WITH_MAX_BID / TARGET_COST: the bid, account currency","type":"number","exclusiveMinimum":0},"pacing_type":{"description":"Default STANDARD","type":"string","enum":["STANDARD","ACCELERATED"]},"conversion_window":{"description":"Default Snapchat's SWIPE_28DAY_VIEW_1DAY","type":"string","enum":["SWIPE_28DAY_VIEW_1DAY","SWIPE_7DAY"]},"countries":{"description":"ISO codes (at least one for a new ad squad)","minItems":1,"maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"region_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":32}},"min_age":{"description":"Default 18 for a new ad squad: Snapchat refuses its goal for under-18s in the EU, the EEA, Switzerland and the UK","type":"integer","minimum":13,"maximum":65},"max_age":{"type":"integer","minimum":13,"maximum":65},"genders":{"type":"string","enum":["all","men","women"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":64}},"segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}},"excluded_segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}}},"additionalProperties":false},"ad_settings":{"description":"The ads' profile, destination and CTA (new, or the changes to a copied ad)","type":"object","properties":{"profile_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A public profile (get_launch_questions → identity.choices.profiles)"},"website_url":{"description":"https only","type":"string","maxLength":2048},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":200},"medium":{"type":"string","maxLength":200},"campaign":{"type":"string","maxLength":200},"id":{"type":"string","maxLength":200},"content":{"type":"string","maxLength":200}},"additionalProperties":false,"description":"UTM parameters appended to the URL (the app's UTM toggle): given = on, the app's defaults for the fields left out"},"call_to_action":{"description":"Default SHOP_NOW","type":"string","enum":["SHOP_NOW","ORDER_NOW","SIGN_UP","GET_NOW","BOOK_NOW","VIEW","MORE","READ","WATCH","DOWNLOAD","APPLY_NOW","BUY_TICKETS","PLAY_GAME","LISTEN"]},"brand_name":{"type":"string","maxLength":32}},"additionalProperties":false},"adsquad_template_id":{"description":"Quick Bulk Edit: a saved ad squad template (list_platform_templates level adgroup), the base of the new ad squads' settings (instead of copy_adset_from); adsquad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ad_template_id":{"description":"Quick Bulk Edit: a saved ad template (list_platform_templates level ad), the base of the ads' settings (instead of copy_ad_from); ad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"time_zone":{"description":"The IANA zone of schedule, e.g. Europe/London for a UK campaign. Default the ad account's","type":"string","maxLength":64}},"additionalProperties":false}},"required":["ad_account_id","ads"],"additionalProperties":false}}}},"responses":{"201":{"description":"The plan, prepared","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchPlan"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/launch-plans/{id}":{"get":{"operationId":"getLaunchPlan","tags":["Launches"],"summary":"A prepared plan: its recap and whether it was launched","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Launch plan id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The plan","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchPlan"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/launch-plans/{id}/confirm":{"post":{"operationId":"confirmLaunchPlan","tags":["Launches"],"summary":"Launch a prepared plan, after the user said yes to its recap","description":"A plan launches once (409 plan_already_launched), within 24 hours of being prepared (410 plan_expired). Answers 202 as soon as the launch started: follow it with GET /launches/{launch_id}.","x-apogee-scope":"launch","parameters":[{"name":"id","in":"path","required":true,"description":"Launch plan id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","const":true,"description":"true = the user said yes to the recap"}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"202":{"description":"The launch started","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchStarted"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"410":{"$ref":"#/components/responses/Problem410"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/launch-plans/{id}/status":{"get":{"operationId":"getLaunchPlanStatus","tags":["Launches"],"summary":"Where a launch is, by its plan id (useful in the first seconds, before its launch id is known)","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Launch plan id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The launch status","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Launch"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/launches":{"get":{"operationId":"listLaunches","tags":["Launches"],"summary":"The launches (the app's History), newest first: processing, completed, failed or interrupted","x-apogee-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"ad_account_id","in":"query","required":false,"description":"Meta ad account id (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["processing","completed","failed","interrupted"]}}],"responses":{"200":{"description":"A page of launches","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LaunchSummary"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/launches/{id}":{"get":{"operationId":"getLaunch","tags":["Launches"],"summary":"Where a launch is: processing, completed, failed or interrupted (a deploy cut it: check Ads Manager)","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Launch id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The launch status and result","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Launch"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/actions":{"post":{"operationId":"createAction","tags":["Actions"],"summary":"Prepare an action: what will change is answered, nothing changes until it is confirmed","description":"Meta types: pause_ad, pause_adset, activate_ad, activate_adset, update_budget, scale_budget, duplicate_ad, duplicate_adset, duplicate_campaign, create_adset, create_ad, update_adset_targeting, update_campaign_status, create_campaign, create_ad_from_post. TikTok / Snapchat types (with platform and that platform's ad account id): set_platform_status, set_platform_daily_budget. Budgets above the safety cap are refused. duplicate_ad: Keeps the SAME Facebook post (its likes, comments and shares): a new ad on its post id, else on its creative (Meta's /copies made a new post). Instagram starts a new post for each ad, as with a post id in Ads Manager. Only inside the same ad account (a copy into another ad account makes a new post); changing a text or the URL afterwards makes a new post too. The result lists each new ad id and the method used (post_id: shown as an existing post in Ads Manager; shared_creative: the same post shown as a new ad).","x-apogee-scope":"actions (launch for create_campaign)","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"pause_ad"},"input":{"type":"object","properties":{"ad_ids":{"type":"array","items":{"type":"string"},"description":"Array of ad IDs to pause"},"ad_names":{"type":"array","items":{"type":"string"},"description":"Names of the ads for confirmation display"}},"required":["ad_ids","ad_names"],"additionalProperties":{},"description":"Pause one or more ads. Use when user asks to pause, cut, stop, or kill specific ads. Always confirm with the user before executing."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"pause_adset"},"input":{"type":"object","properties":{"adset_ids":{"type":"array","items":{"type":"string"},"description":"Array of ad set IDs to pause"},"adset_names":{"type":"array","items":{"type":"string"},"description":"Names of the ad sets for confirmation display"}},"required":["adset_ids","adset_names"],"additionalProperties":{},"description":"Pause one or more ad sets. Use when user asks to pause, cut, stop, or kill specific ad sets. Preferred over pause_ad for 1-ad-per-adset structures. When user wants to pause/cut a creative, use this tool with the adset_id."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"activate_ad"},"input":{"type":"object","properties":{"ad_ids":{"type":"array","items":{"type":"string"},"description":"Array of ad IDs to activate"},"ad_names":{"type":"array","items":{"type":"string"},"description":"Names of the ads for confirmation display"}},"required":["ad_ids"],"additionalProperties":{},"description":"Reactivate one or more paused ads to ACTIVE status. Use when user asks to reactivate, resume, restart, turn on specific ads."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"activate_adset"},"input":{"type":"object","properties":{"adset_ids":{"type":"array","items":{"type":"string"},"description":"Array of ad set IDs to activate"},"adset_names":{"type":"array","items":{"type":"string"},"description":"Names of the ad sets for confirmation display"}},"required":["adset_ids"],"additionalProperties":{},"description":"Reactivate one or more paused ad sets to ACTIVE status. Use when user asks to reactivate, resume, restart, turn on specific ad sets."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"update_budget"},"input":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"adset_id":{"type":"string"},"adset_name":{"type":"string"},"current_budget":{"type":"number","description":"Current daily budget in account currency"},"new_budget":{"type":"number","description":"New daily budget in account currency"}},"additionalProperties":{}},"description":"Array of budget updates"}},"required":["updates"],"additionalProperties":{},"description":"Update daily budget for one or more ad sets. Use when user asks to scale, increase, decrease, or change budget."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"scale_budget"},"input":{"type":"object","properties":{"adset_ids":{"type":"array","items":{"type":"string"},"description":"Array of ad set IDs to scale"},"adset_names":{"type":"array","items":{"type":"string"},"description":"Names of the ad sets"},"percentage":{"type":"number","description":"Percentage to scale by (e.g. 30 for +30%, -20 for -20%). Max +100, cannot go below 1€/day."}},"required":["adset_ids","percentage"],"additionalProperties":{},"description":"Scale budgets of ad sets by a percentage (e.g. +30% or -20%). Fetches current budgets, calculates new ones, and shows confirmation with before/after. Max +100% per operation, min 1€/day."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"duplicate_ad"},"input":{"type":"object","properties":{"source_ad_id":{"type":"string","description":"ID of the ad to duplicate"},"source_ad_name":{"type":"string","description":"Name of the source ad (for confirmation display)"},"target_adset_ids":{"type":"array","items":{"type":"string"},"description":"Ad set IDs to duplicate into"},"target_adset_names":{"type":"array","items":{"type":"string"},"description":"Names of target ad sets (for confirmation display)"},"rename_suffix":{"type":"string","description":"Optional suffix to append to duplicated ad names (e.g. \" - Copy\")"}},"required":["source_ad_id","source_ad_name","target_adset_ids","target_adset_names"],"additionalProperties":{},"description":"Duplicate a winning ad into one or more target ad sets of the same ad account, on the SAME Facebook post: its likes, comments and shares stay (a new ad on its post id, else on its creative). Instagram starts a new post for each ad, as with a post id in Ads Manager. Use when user asks to duplicate, replicate, scale a winning creative to other campaigns. Keeps the SAME Facebook post (its likes, comments and shares): a new ad on its post id, else on its creative (Meta's /copies made a new post). Instagram starts a new post for each ad, as with a post id in Ads Manager. Only inside the same ad account (a copy into another ad account makes a new post); changing a text or the URL afterwards makes a new post too. The result lists each new ad id and the method used (post_id: shown as an existing post in Ads Manager; shared_creative: the same post shown as a new ad)."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"duplicate_adset"},"input":{"type":"object","properties":{"source_adset_id":{"type":"string","description":"ID of the ad set to duplicate"},"target_campaign_id":{"type":"string","description":"Optional: campaign ID to duplicate into (defaults to same campaign)"},"new_name":{"type":"string","description":"Optional: added after the source's name (\"<source name> - <new_name>\"), e.g. a market or a version"},"new_budget":{"type":"number","description":"Optional: new daily budget in account currency"}},"required":["source_adset_id"],"additionalProperties":{},"description":"Duplicate an ad set WITH its ads into the same campaign or a different one. Each copied ad keeps its post (likes, comments, shares keep adding up). The duplicate is created as PAUSED. Use when user asks to duplicate or copy an ad set."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"duplicate_campaign"},"input":{"type":"object","properties":{"source_campaign_id":{"type":"string","description":"ID of the campaign to duplicate"},"new_name":{"type":"string","description":"Optional: added after the source's name (\"<source name> - <new_name>\"), e.g. a market or a version"},"status_option":{"type":"string","enum":["PAUSED","ACTIVE"],"description":"Status for the new campaign (default PAUSED)"}},"required":["source_campaign_id"],"additionalProperties":{},"description":"Duplicate a full campaign with all its ad sets and ads (archived and deleted ones left out). Each copied ad keeps its post. The duplicate is created as PAUSED. Use when user asks to duplicate or copy a campaign."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"create_adset"},"input":{"type":"object","properties":{"campaign_id":{"type":"string","description":"Campaign ID to create the ad set in"},"name":{"type":"string","description":"Ad set name"},"copy_from_adset_id":{"type":"string","description":"Optional: an ad set of the same account to copy targeting, optimization_goal, billing_event, promoted_object, destination_type, attribution_spec and, into a Sales campaign, its customer lifecycle strategy (ad_set_goal) from (its budget, bid and schedule are not copied)"},"daily_budget":{"type":"number","description":"ABO only: daily budget in cents (e.g. 2000 = 20€). Leave it out in a CBO campaign"},"targeting":{"type":"object","properties":{},"additionalProperties":{},"description":"Targeting spec (geo_locations, age_min, age_max, genders, interests, custom_audiences, etc.). Required unless copy_from_adset_id"},"optimization_goal":{"type":"string","description":"Optimization goal (e.g. OFFSITE_CONVERSIONS, LINK_CLICKS, IMPRESSIONS). Required unless copy_from_adset_id"},"promoted_object":{"type":"object","properties":{},"additionalProperties":{},"description":"Conversion event, e.g. { pixel_id, custom_event_type: \"PURCHASE\" }. Required for OFFSITE_CONVERSIONS / VALUE / LEAD_GENERATION unless copied"},"billing_event":{"type":"string","description":"Billing event (default IMPRESSIONS)"},"bid_strategy":{"type":"string","enum":["LOWEST_COST_WITHOUT_CAP","COST_CAP","LOWEST_COST_WITH_BID_CAP","LOWEST_COST_WITH_MIN_ROAS"],"description":"ABO: this ad set's bid strategy (default LOWEST_COST_WITHOUT_CAP). CBO: the campaign's (leave it out)"},"bid_amount":{"type":"number","description":"Cost cap / bid cap in cents (e.g. 2500 = 25€): required with COST_CAP and LOWEST_COST_WITH_BID_CAP"},"roas_floor":{"type":"number","description":"Minimum ROAS strategy: the ROAS floor, e.g. 2.5 (optimization becomes VALUE)"},"start_time":{"type":"string","description":"Optional: start time in ISO format"}},"required":["campaign_id","name"],"additionalProperties":{},"description":"Create a new ad set in an existing campaign. The ad set is created as PAUSED. Use when user asks to create a new ad set or audience. In a campaign budget (CBO) leave daily_budget out: the campaign's budget and bid strategy apply, each ad set gets its own bid_amount / roas_floor. In ABO, daily_budget is required. copy_from_adset_id copies the audience, optimization, conversion event, destination and attribution of an ad set of the same account (then targeting and optimization_goal can be left out)."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"create_ad"},"input":{"type":"object","properties":{"adset_id":{"type":"string","description":"Ad set ID to create the ad in"},"name":{"type":"string","description":"Ad name"},"object_story_id":{"type":"string","description":"Optional: existing post ID (format pageId_postId) to preserve social proof"},"creative_id":{"type":"string","description":"Optional: existing creative ID to reuse (used if no object_story_id)"},"status":{"type":"string","enum":["PAUSED","ACTIVE"],"description":"Ad status (default PAUSED)"}},"required":["adset_id","name"],"additionalProperties":{},"description":"Create a new ad in an existing ad set. Use an object_story_id (page post ID) to preserve social proof (likes, comments, shares), or a creative_id to reuse an existing creative. The ad is created as PAUSED."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"update_adset_targeting"},"input":{"type":"object","properties":{"adset_id":{"type":"string","description":"Ad set ID to update"},"adset_name":{"type":"string","description":"Ad set name for confirmation display"},"targeting":{"type":"object","properties":{},"additionalProperties":{},"description":"New targeting spec (geo_locations, age_min, age_max, genders, flexible_spec, custom_audiences, etc.)"}},"required":["adset_id","targeting"],"additionalProperties":{},"description":"Update the targeting of an existing ad set. Use when user asks to change audience, targeting, demographics, interests, or locations."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"update_campaign_status"},"input":{"type":"object","properties":{"campaign_id":{"type":"string","description":"Campaign ID"},"campaign_name":{"type":"string","description":"Campaign name for confirmation display"},"status":{"type":"string","enum":["ACTIVE","PAUSED"],"description":"New status"}},"required":["campaign_id","status"],"additionalProperties":{},"description":"Change the status of an entire campaign (ACTIVE or PAUSED). Use when user asks to pause or activate a whole campaign."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"create_campaign"},"input":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"objective":{"type":"string","enum":["OUTCOME_SALES","OUTCOME_LEADS","OUTCOME_TRAFFIC","OUTCOME_ENGAGEMENT","OUTCOME_AWARENESS","OUTCOME_APP_PROMOTION"]},"budget_type":{"type":"string","enum":["abo","cbo"],"description":"abo = budget per ad set; cbo = campaign budget"},"budget":{"description":"CBO only: daily campaign budget, in the account currency","type":"number","exclusiveMinimum":0},"bid_strategy":{"description":"CBO: the bid strategy shared by all ad sets; each new ad set then gets its own bid_amount / roas_floor (prepare_launch adset_variants). ABO: leave it out and use adset_settings.bid_strategy.","type":"string","enum":["LOWEST_COST_WITHOUT_CAP","COST_CAP","LOWEST_COST_WITH_BID_CAP","LOWEST_COST_WITH_MIN_ROAS"]}},"required":["name","objective","budget_type"],"additionalProperties":false,"description":"A new campaign (the app's Create Campaign), always created PAUSED. Scope launch."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^(act_)?\\d{1,32}$","description":"Meta ad account id (act_…)"},"type":{"type":"string","const":"create_ad_from_post"},"input":{"type":"object","properties":{"adset_id":{"type":"string","pattern":"^\\d{1,40}$","description":"The ad set the new ad goes in (list_adsets)"},"name":{"type":"string","minLength":1,"maxLength":255,"description":"The new ad's name"},"object_story_id":{"description":"A Facebook post: <pageId>_<postId> (list_posts)","type":"string","pattern":"^\\d{1,40}_\\d{1,40}$"},"instagram_media_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An Instagram post (list_posts source instagram or ads)"},"instagram_user_id":{"type":"string","pattern":"^\\d{1,40}$","description":"Instagram post: the account that published it"},"page_id":{"type":"string","pattern":"^\\d{1,40}$","description":"Instagram post: the Facebook page linked to that account"},"call_to_action":{"description":"Instagram post only: e.g. SHOP_NOW, LEARN_MORE","type":"string","maxLength":40},"website_url":{"description":"Instagram post only, with call_to_action","type":"string","maxLength":2048},"url_parameters":{"description":"UTM parameters added to the post's link","type":"string","maxLength":1000},"advantage_plus":{"type":"object","properties":{"opt_in":{"type":"array","items":{"type":"string","enum":["text_optimizations","product_tags","creative_stickers","inline_comment","enhance_cta","reveal_details_over_time","show_destination_blurbs","show_summary","optimize_website_destination","shop","product_browsing","browser_addons","image_brightness_and_contrast","image_templates","image_touchups","video_auto_crop","video_filtering"]},"description":"Enhancements turned ON; every other one is sent OFF. [] = all off"}},"required":["opt_in"],"description":"Required: the Advantage+ creative enhancements, all explicit"},"status":{"description":"Default PAUSED","type":"string","enum":["PAUSED","ACTIVE"]}},"required":["adset_id","name","advantage_plus"],"additionalProperties":false,"description":"A new ad on an EXISTING post (Facebook or Instagram): its likes, comments and shares are kept. Advantage+ choices required, every other enhancement OFF."}},"required":["ad_account_id","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{0,63}$","description":"The ad account, from list_ad_accounts with the same platform: a TikTok advertiser id (digits), a Snapchat ad account id (a UUID)"},"platform":{"type":"string","enum":["tiktok","snapchat"],"description":"tiktok or snapchat (Meta has its own reads and actions)"},"type":{"type":"string","const":"set_platform_status"},"input":{"type":"object","properties":{"level":{"type":"string","enum":["campaign","adset","ad"],"description":"campaign, adset (a TikTok ad group / a Snapchat ad squad) or ad"},"ids":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{0,63}$","description":"An id of that level (get_platform_performance)"},"description":"1 to 50 campaigns, ad sets or ads of that level"},"status":{"type":"string","enum":["paused","active"],"description":"paused (stops delivering) or active (delivers again)"}},"required":["level","ids","status"],"additionalProperties":false,"description":"TikTok / Snapchat: pause or activate campaigns, ad sets (TikTok ad groups, Snapchat ad squads) or ads of the ad account (platform and its own ad account id at the top). TikTok GMV Max and legacy Smart+ campaigns, and the ads TikTok generates inside Smart+ ad groups, are refused."}},"required":["ad_account_id","platform","type","input"],"additionalProperties":false},{"type":"object","properties":{"ad_account_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{0,63}$","description":"The ad account, from list_ad_accounts with the same platform: a TikTok advertiser id (digits), a Snapchat ad account id (a UUID)"},"platform":{"type":"string","enum":["tiktok","snapchat"],"description":"tiktok or snapchat (Meta has its own reads and actions)"},"type":{"type":"string","const":"set_platform_daily_budget"},"input":{"type":"object","properties":{"level":{"type":"string","enum":["campaign","adset"],"description":"campaign (its campaign budget) or adset (a TikTok ad group / a Snapchat ad squad)"},"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{0,63}$","description":"The campaign or ad set (get_platform_performance shows its daily_budget)"},"daily_budget":{"type":"number","exclusiveMinimum":0,"description":"The new daily budget, in the ad account's currency (not cents or micro)"}},"required":["level","id","daily_budget"],"additionalProperties":false,"description":"TikTok / Snapchat: a campaign's or an ad set's new daily budget, in the ad account's currency. Refused above the safety cap (converted to the account's currency), on a lifetime budget, on an ad set whose campaign holds the budget, and on TikTok Smart+ budgets."}},"required":["ad_account_id","platform","type","input"],"additionalProperties":false}]}}}},"responses":{"201":{"description":"The action, prepared","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Action"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/actions/{id}":{"get":{"operationId":"getAction","tags":["Actions"],"summary":"A prepared action: what it will do, and whether it ran","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Action id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The action","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Action"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/actions/{id}/confirm":{"post":{"operationId":"confirmAction","tags":["Actions"],"summary":"Run a prepared action, after the user approved what it will do","description":"An action runs once (409 action_already_ran), within 24 hours (410 action_expired). The answer lists what was created (details: new ids; for a duplicated ad, the method that kept its post).","x-apogee-scope":"the action's own: actions (launch for create_campaign)","parameters":[{"name":"id","in":"path","required":true,"description":"Action id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","const":true,"description":"true = the user approved this action"}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"The action ran","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResult"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"410":{"$ref":"#/components/responses/Problem410"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/bridge-transfers":{"post":{"operationId":"createBridgeTransfer","tags":["Bridge"],"summary":"Prepare a Bridge transfer WITHOUT transferring anything: the recap and the transfer id","description":"Cross-platform: source ads (or a Meta ad set / campaign = its ads, 50 ads max) into a destination campaign, in an existing ad set / TikTok ad group / Snapchat ad squad (destination.adset_id) or a new one copied from a template (destination.new_adset). Meta → Meta (both platforms meta, two ad accounts): ads, ad sets or campaigns. ready false = what to give (recap.missing → extra_fields; recap.fields → mapping), then prepare it again. Show the recap, confirm after the yes.","x-apogee-scope":"launch","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$","description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id"},"ad_ids":{"description":"The ads to transfer (cross-platform: 50 max per run)","minItems":1,"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A source ad (list_ads)"}},"adset_ids":{"description":"Meta: ad sets (cross-platform: their ads; Meta → Meta: the ad sets themselves, 20 max)","minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Meta ad set"}},"campaign_ids":{"description":"Meta: campaigns (cross-platform: their ads; Meta → Meta: the campaigns themselves, 5 max)","minItems":1,"maxItems":5,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Meta campaign"}}},"required":["platform","ad_account_id"],"additionalProperties":false,"description":"Where the ads come from: one of ad_ids, adset_ids, campaign_ids"},"destination":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$","description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id"},"campaign_id":{"description":"Required, except for a Meta → Meta copy of campaigns","type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"},"adset_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An existing destination ad set / TikTok ad group / Snapchat ad squad (list_adsets)"},"new_adset":{"description":"Cross-platform: a new ad set copied from a template, instead of adset_id","type":"object","properties":{"template_adset_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad set / ad group / ad squad of the destination campaign whose settings the new one copies"},"name":{"type":"string","minLength":1,"maxLength":255},"daily_budget":{"description":"Account currency; not for a TikTok CBO campaign","type":"number","exclusiveMinimum":0}},"required":["template_adset_id","name"],"additionalProperties":false}},"required":["platform","ad_account_id"],"additionalProperties":false},"launch_status":{"description":"Cross-platform. Default CREATED_PAUSED; SCHEDULED_* only with new_adset (+ schedule)","type":"string","enum":["CREATED_PAUSED","LIVE_NOW","SCHEDULED_PAUSED","SCHEDULED_LIVE"]},"schedule":{"description":"A new ad set's schedule, in the destination account's time zone","type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"},"end_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"end_time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"}},"required":["date","time"],"additionalProperties":false},"extra_fields":{"description":"What the plan asked for (recap.missing): the destination's identity / profile / page, URL, CTA, headline","type":"object","properties":{"identity_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"TikTok: the identity the ads run under"},"identity_type":{"description":"TikTok: one of the brand's TikTok accounts, TT_USER or BC_AUTH_TT through its Business Center (TikTok refuses a custom identity on these ads)","type":"string","enum":["TT_USER","BC_AUTH_TT"]},"identity_bc_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"TikTok BC_AUTH_TT: the Business Center"},"profile_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Snapchat: the public profile"},"page_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Meta: the Facebook page"},"website_url":{"type":"string","maxLength":2048},"call_to_action":{"type":"string","maxLength":40},"headline":{"description":"Snapchat: 34 characters","type":"string","maxLength":255}},"additionalProperties":false},"meta_texts":{"description":"Destination Meta: each source ad's texts (by source ad id), instead of the ones the plan suggested (recap.meta_texts)","type":"object","propertyNames":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"},"additionalProperties":{"type":"object","properties":{"primary_text":{"type":"string","maxLength":2200},"headline":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":255}},"additionalProperties":false}},"options":{"description":"Meta → Meta copy only","type":"object","properties":{"keep_social_proof":{"description":"Default true: reuse the source post (likes, comments) when Meta allows it","type":"boolean"},"status":{"description":"After the copy: PAUSED (default), ACTIVE, or INHERIT (on only what is on in the source)","type":"string","enum":["PAUSED","ACTIVE","INHERIT"]},"name_suffix":{"type":"string","maxLength":100}},"additionalProperties":false},"mapping":{"description":"Meta → Meta copy: values for the plan's fields (recap.fields: pixel, page, audience, budget…), by key","type":"object","propertyNames":{"type":"string","maxLength":200},"additionalProperties":{"type":"string","maxLength":500}}},"required":["source","destination"],"additionalProperties":false}}}},"responses":{"201":{"description":"The transfer, prepared","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BridgeTransfer"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/bridge-transfers/{id}/confirm":{"post":{"operationId":"confirmBridgeTransfer","tags":["Bridge"],"summary":"Run a prepared Bridge transfer, after the user said yes to its recap","description":"The plan is checked again first (changed: 422, nothing transferred). Answers 202 with the outcome when the run ended within ~25 s (finished true), else status running: follow it with GET /bridge-transfers/{id}. A transfer runs once (409), within 24 hours (410).","x-apogee-scope":"launch","parameters":[{"name":"id","in":"path","required":true,"description":"Bridge transfer id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","const":true,"description":"true = the user said yes to the recap"}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"202":{"description":"The transfer started (or already ended: finished)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BridgeTransferStatus"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409"},"410":{"$ref":"#/components/responses/Problem410"},"412":{"$ref":"#/components/responses/Problem412"},"422":{"$ref":"#/components/responses/Problem422"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/bridge-transfers/{id}":{"get":{"operationId":"getBridgeTransfer","tags":["Bridge"],"summary":"Where a Bridge transfer is: prepared, running, completed, partial, failed, not_run or unknown","x-apogee-scope":"read","parameters":[{"name":"id","in":"path","required":true,"description":"Bridge transfer id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w-]+$"}}],"responses":{"200":{"description":"The transfer's status","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BridgeTransferStatus"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/bridged-ads":{"get":{"operationId":"listBridgedAds","tags":["Bridge"],"summary":"The ads already bridged from a source ad account (the app's Bridged tab), newest first","description":"Your own transfers, and another Apogee user's from the same source account when their destination account is yours too.","x-apogee-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"source_platform","in":"query","required":false,"description":"Default meta","schema":{"type":"string","enum":["meta","tiktok","snapchat"]}},{"name":"source_ad_account_id","in":"query","required":true,"description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id","schema":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$"}}],"responses":{"200":{"description":"A page of bridged ads","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BridgedAd"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"}}}},"/bridged-ads/stats":{"get":{"operationId":"getBridgeStats","tags":["Bridge"],"summary":"The Bridge's Stats tab: each creative bridged from a Meta ad account, its source ad next to its TikTok and Snapchat copies","description":"Newest bridge first, over since → until (7-day click attribution on every platform). Per platform: status (ok, no_target = never bridged there, not_connected = that destination account is not one of yours, error), the ads, inputs (raw sums: spend, revenue, impressions, reach, link clicks, landing page views, adds to cart, purchases, 3 s and 15 s plays) and kpis (the app's columns: ROAS, CPM, CTR, CPC, cost per purchase, hook and hold rates…), each in its own ad account's currency: platforms are never added together.","x-apogee-scope":"read","parameters":[{"name":"source_ad_account_id","in":"query","required":true,"description":"The Meta ad account the ads were bridged from (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"name":"since","in":"query","required":true,"description":"First day, YYYY-MM-DD","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"until","in":"query","required":true,"description":"Last day, YYYY-MM-DD","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"The bridged creatives and their numbers","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BridgeStats"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}},"/bridged-ads/daily-stats":{"get":{"operationId":"getBridgeDailyStats","tags":["Bridge"],"summary":"The Bridge's Daily tab: per platform and per day, the numbers of every creative bridged from a Meta ad account","description":"Day by day over since → until (366 days at most): spend, revenue, ROAS, impressions, link clicks and purchases summed over the Meta source ads and, separately, over their TikTok and Snapchat copies, with each platform's totals, status and currency. Platforms are never summed together.","x-apogee-scope":"read","parameters":[{"name":"source_ad_account_id","in":"query","required":true,"description":"The Meta ad account the ads were bridged from (act_…)","schema":{"type":"string","pattern":"^(act_)?\\d{1,32}$"}},{"name":"since","in":"query","required":true,"description":"First day, YYYY-MM-DD","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"until","in":"query","required":true,"description":"Last day, YYYY-MM-DD","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"Each platform's days and totals","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Apogee-Version":{"$ref":"#/components/headers/Apogee-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BridgeDailyStats"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"$ref":"#/components/responses/Problem404"},"412":{"$ref":"#/components/responses/Problem412"},"429":{"$ref":"#/components/responses/Problem429"},"500":{"$ref":"#/components/responses/Problem500"},"502":{"$ref":"#/components/responses/Problem502"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"apk_…","description":"An API key from app.apogee.ad → Settings → API"}},"parameters":{"Limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Page size"},"Cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor of the previous page"},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":255},"description":"A unique key per request (e.g. a UUID), reused when retrying it"},"IdempotencyKeyOptional":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255},"description":"Accepted, never replayed (signed URLs are not stored)"}},"headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"This request's id (give it to support)"},"Apogee-Version":{"schema":{"type":"string"},"description":"The contract's date (2026-10-06)"},"RateLimit":{"schema":{"type":"string"},"description":"Remaining requests and reset (draft-ietf-httpapi-ratelimit-headers-08)"},"RateLimit-Policy":{"schema":{"type":"string"},"description":"The limit of this kind of request"},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait"},"Idempotent-Replayed":{"schema":{"type":"string","enum":["true"]},"description":"This answer is the stored answer of an earlier request with the same Idempotency-Key"}},"schemas":{"Problem":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"code":{"type":"string","enum":["invalid_api_key","insufficient_scope","forbidden","meta_permission_denied","account_not_connected","platform_permission_denied","upgrade_required","payment_failed","plan_required","credits_exhausted","member_cap_reached","cost_ceiling_reached","free_daily_limit_reached","not_found","method_not_allowed","validation_failed","idempotency_key_required","request_refused","not_supported","plan_already_launched","action_already_ran","same_error_again","idempotency_in_progress","too_many_keys","plan_expired","action_expired","meta_not_connected","platform_not_connected","drive_not_connected","payload_too_large","missing_answers","idempotency_key_reused","budget_above_cap","launch_refused","rate_limited","quota_exceeded","daily_read_cap","meta_rate_limited","platform_rate_limited","internal_error","meta_error","platform_error","upstream_error","launch_failed","drive_error","feature_not_ready","service_disabled","ai_paused","meta_timeout"]},"request_id":{"type":["string","null"]},"errors":{"type":"array","items":{"type":"object","properties":{"param":{"type":["string","null"]},"code":{"type":"string"},"message":{"type":"string"}}}},"missing":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"question":{"type":["string","null"]},"needs":{"type":"array","items":{"type":"string"}},"answer_with":{"type":["string","null"]}}}},"feature":{"type":"string","enum":["tiktok","snapchat","other_platforms","bridge","duplicate_post_id","analytics","mcp","rest_api","copywriting_agent","creative_studio","automations","done_for_you"],"description":"upgrade_required: the feature the plan does not include"},"required_plan":{"type":"string","enum":["pro","growth","scale"],"description":"upgrade_required: the plan that includes the feature"},"current_plan":{"type":"string","description":"upgrade_required: the account's plan"},"required_scope":{"type":"string","enum":["read","launch","actions"]},"retry_after":{"type":"integer"},"meta":{"type":"object","properties":{"code":{"type":"integer"}}},"buy_url":{"type":"string","format":"uri","description":"credits_exhausted: the Apogee app's page to buy credits"}},"required":["type","title","status","detail","code"]},"Me":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id"]},"key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"scopes":{"type":"array","items":{"type":"string","enum":["read","launch","actions"]}},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["id","scopes"]},"api_version":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}}},"required":["user","key","api_version"]},"AdAccount":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"currency":{"type":["string","null"]},"timezone":{"type":["string","null"]},"timezone_offset_hours_utc":{"type":["number","null"]},"business":{"type":["string","null"]}},"required":["id"]},"FacebookPage":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"instagram":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"username":{"type":["string","null"]}}},{"type":"null"}]}},"required":["id"]},"Named":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["id"]},"PixelEvents":{"type":"object","properties":{"standard":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string"},"name":{"type":["string","null"]},"count":{"type":["number","null"]}}}},"never_fired":{"type":"array","items":{"type":"string"}},"custom_events":{"type":"array","items":{"type":"object","properties":{"custom_event_str":{"type":"string"},"count":{"type":["number","null"]}}}},"custom_conversions":{"type":"array","items":{"type":"object","properties":{"custom_conversion_id":{"type":"string"},"name":{"type":["string","null"]}}}}}},"Catalog":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"product_count":{"type":"integer"}},"required":["id"]},"Audience":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"subtype":{"type":["string","null"]},"delivery_status":{"type":["string","null"]}},"required":["id"]},"Template":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"kind":{"type":"string","enum":["adset","ad"]},"objective":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","kind"]},"InstagramAccount":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":["string","null"]},"name":{"type":["string","null"]},"linked":{"type":"boolean"},"recommended":{"type":"boolean"}},"required":["id"]},"LeadForm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]}},"required":["id"]},"Creator":{"type":"object","properties":{"source":{"type":"string","enum":["instagram","facebook"]},"creator_ig_id":{"type":["string","null"]},"creator_username":{"type":["string","null"]},"creator_fb_page_id":{"type":["string","null"]},"creator_name":{"type":["string","null"]}},"required":["source"]},"Post":{"type":"object","properties":{"object_story_id":{"type":["string","null"],"description":"A Facebook post: <pageId>_<postId>"},"instagram_media_id":{"type":["string","null"]},"instagram_user_id":{"type":["string","null"]},"page_id":{"type":["string","null"]},"instagram_permalink":{"type":["string","null"]},"permalink":{"type":["string","null"]},"message":{"type":["string","null"]},"caption":{"type":["string","null"]},"created_time":{"type":["string","null"]},"thumbnail_url":{"type":["string","null"]},"media_type":{"type":["string","null"]},"likes":{"type":["number","null"]},"comments":{"type":["number","null"]},"ads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]}}},"description":"/ad-accounts/{acc}/posts: the ads using this post"}}},"TargetingItem":{"type":"object","additionalProperties":true,"description":"Meta's targeting item: id or key, name, type, audience size…"},"Campaign":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"objective":{"type":["string","null"]},"status":{"type":["string","null"]},"cbo":{"type":"boolean"},"daily_budget":{"type":["number","null"]},"lifetime_budget":{"type":["number","null"]}},"required":["id"]},"AdSet":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"daily_budget":{"type":["number","null"]},"optimization_goal":{"type":["string","null"]},"countries":{"type":["array","null"],"items":{"type":"string"}}},"required":["id"]},"Ad":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]}},"required":["id"]},"LatestInCampaign":{"type":"object","properties":{"campaign_id":{"type":"string"},"adset":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"created_time":{"type":["string","null"]}},"required":["id"]},{"type":"null"}]},"ad":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"adset_id":{"type":["string","null"]},"created_time":{"type":["string","null"]}},"required":["id"]},{"type":"null"}]},"use":{"type":"object","properties":{"copy_adset_from":{"type":"string"},"copy_ad_from":{"type":"string"}}},"note":{"type":"string"}},"required":["campaign_id","adset","ad"]},"InsightRow":{"type":"object","description":"One row: its level and dimensions (id, name, date, platform, position, age, gender, device…) and its metrics, in the account currency. TikTok / Snapchat rows (platform tiktok or snapchat) also carry since, until, currency, and per level campaign_id, adset_id, daily_budget, budget_mode, family, smart_plus (TikTok), lifetime_budget (Snapchat).","properties":{"level":{"type":"string","enum":["account","campaign","adset","ad","daily","placement","age_gender","device"]},"date_preset":{"type":["string","null"]},"since":{"type":["string","null"]},"until":{"type":["string","null"]},"currency":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"adset_id":{"type":["string","null"]},"daily_budget":{"type":["number","null"]},"id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"date":{"type":["string","null"]},"platform":{"type":["string","null"]},"position":{"type":["string","null"]},"age":{"type":["string","null"]},"gender":{"type":["string","null"]},"device":{"type":["string","null"]},"metrics":{"type":"object","properties":{"spend":{"type":["number","null"]},"impressions":{"type":["number","null"]},"clicks":{"type":["number","null"]},"ctr":{"type":["number","null"]},"cpc":{"type":["number","null"]},"cpm":{"type":["number","null"]},"reach":{"type":["number","null"]},"frequency":{"type":["number","null"]},"purchases":{"type":["number","null"]},"revenue":{"type":["number","null"]},"roas":{"type":["number","null"]},"cpa":{"type":["number","null"]},"add_to_cart":{"type":["number","null"]},"cost_per_atc":{"type":["number","null"]}}}},"additionalProperties":true,"required":["level","metrics"]},"Import":{"type":"object","properties":{"id":{"type":"string"},"source":{"type":"string","enum":["frameio","google_drive","dropbox"]},"share_name":{"type":["string","null"]},"done":{"type":"boolean"},"created_at":{"type":["string","null"]},"note":{"type":"string","description":"Why an import has no file (done at once)"},"jobs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":"string","enum":["PENDING","PROCESSING","COMPLETED","FAILED","MISSING"]},"progress":{"type":["number","null"]},"size_bytes":{"type":["number","null"]},"ref":{"type":["string","null"]},"error":{"type":["string","null"]}}}},"truncated":{"type":"boolean"},"skipped_too_large":{"type":"array","items":{}}},"required":["id","source","jobs"]},"DriveFile":{"type":"object","properties":{"ref":{"type":"string","description":"drive:<id>"},"name":{"type":"string"},"folder":{"type":["string","null"]},"kind":{"type":"string","enum":["video","image"]},"mimeType":{"type":["string","null"]},"width":{"type":["number","null"]},"height":{"type":["number","null"]},"format":{"type":"string"},"sizeMB":{"type":["number","null"]},"durationS":{"type":["number","null"]}},"required":["ref","name"]},"UploadSlots":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"upload_url":{"type":"string","format":"uri"},"method":{"type":"string","enum":["PUT"]},"headers":{"type":"object","additionalProperties":{"type":"string"}},"path":{"type":"string"},"ref":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"error":{"type":"string"}}}}},"required":["files"]},"UploadConfirmations":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"ref":{"type":"string"},"size_bytes":{"type":["number","null"]},"error":{"type":"string"}}}}},"required":["files"]},"LaunchQuestions":{"type":"object","properties":{"questions":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string"},"topic":{"type":"string"},"status":{"type":"string","enum":["to_ask","answered","not_needed","later","last"]},"ask":{"type":"string"},"choices":{},"recommended":{},"answer_with":{"type":"string"}}}},"read_errors":{"type":"array","items":{"type":"string"}}},"required":["questions"]},"LaunchPlan":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["prepared","launched","expired"]},"recap":{"type":"object","additionalProperties":true},"defaults_applied":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}},"created_at":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"launched_at":{"type":["string","null"]},"launch_id":{"type":["string","null"]}},"required":["id","status","recap"]},"LaunchStarted":{"type":"object","properties":{"plan_id":{"type":"string"},"launch_id":{"type":["string","null"]},"status":{"type":"string","enum":["started"]}},"required":["plan_id","status"]},"BridgeTransfer":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["prepared"]},"ready":{"type":"boolean"},"recap":{"type":"object","additionalProperties":true},"ask":{"type":"string","description":"When not ready: what to give, then prepare it again"},"expires_at":{"type":"string","format":"date-time"}},"required":["id","status","ready","recap"]},"BridgeTransferStatus":{"type":"object","properties":{"id":{"type":"string"},"finished":{"type":"boolean"},"status":{"type":"string","enum":["prepared","running","completed","partial","failed","not_run","unknown","expired"]},"ads_created":{"type":["number","null"]},"adsets":{},"campaigns":{"type":["number","null"]},"failures":{"type":"array","items":{"type":"string"}},"error":{"type":["string","null"]},"may_have_written":{"type":"boolean"},"started_at":{"type":["string","null"]},"at":{"type":["string","null"]},"ready":{"type":"boolean"},"expires_at":{"type":["string","null"]}},"required":["id","status"]},"BridgedAd":{"type":"object","properties":{"source_ad_id":{"type":"string"},"name":{"type":["string","null"]},"last_at":{"type":["string","null"]},"count":{"type":["number","null"]},"targets":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":["string","null"]},"ad_id":{"type":["string","null"]},"adset_id":{"type":["string","null"]},"smart_plus":{"type":"boolean"},"at":{"type":["string","null"]}}}}},"required":["source_ad_id"]},"BridgePlatformStats":{"type":"object","properties":{"status":{"type":"string","enum":["ok","no_target","not_connected","error"]},"ads":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"ad_account_id":{"type":["string","null"]},"adset_id":{"type":["string","null"]},"smart_plus":{"type":"boolean"},"at":{"type":["string","null"]}}}},"inputs":{"anyOf":[{"type":"object","properties":{"spend":{"type":["number","null"]},"revenue":{"type":["number","null"]},"impressions":{"type":["number","null"]},"reach":{"type":["number","null"]},"link_clicks":{"type":["number","null"]},"landing_page_views":{"type":["number","null"]},"add_to_cart":{"type":["number","null"]},"purchases":{"type":["number","null"]},"hook_views":{"type":["number","null"]},"hold_views":{"type":["number","null"]}}},{"type":"null"}],"description":"Raw sums over the platform's ads, in its ad account currency (null = the platform can't report it)"},"kpis":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"The app's columns from the inputs: spend, revenue, roas, atc_rate (+ atc_rate_basis), cpm, cpmr, reach, impressions, cpc, cpatc, cpp, link_clicks, add_to_cart, purchases, hook_rate, hold_rate, ctr"},"hint":{"type":["string","null"]},"error":{"type":["string","null"]}},"required":["status"]},"BridgeStats":{"type":"object","properties":{"range":{"type":"object","properties":{"since":{"type":"string"},"until":{"type":"string"}}},"source_ad_account_id":{"type":"string"},"creatives":{"type":"array","items":{"type":"object","properties":{"source_ad_id":{"type":"string"},"name":{"type":["string","null"]},"last_bridged_at":{"type":["string","null"]},"count":{"type":["number","null"]},"platforms":{"type":"object","properties":{"meta":{"$ref":"#/components/schemas/BridgePlatformStats"},"tiktok":{"$ref":"#/components/schemas/BridgePlatformStats"},"snapchat":{"$ref":"#/components/schemas/BridgePlatformStats"}}}},"required":["source_ad_id","platforms"]}}},"required":["range","creatives"]},"BridgePlatformDaily":{"type":"object","properties":{"status":{"type":"string","enum":["ok","no_target","not_connected","error"]},"currency":{"type":["string","null"]},"totals":{"anyOf":[{"type":"object","properties":{"spend":{"type":["number","null"]},"revenue":{"type":["number","null"]},"impressions":{"type":["number","null"]},"link_clicks":{"type":["number","null"]},"purchases":{"type":["number","null"]},"roas":{"type":["number","null"]}}},{"type":"null"}]},"days":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"spend":{"type":["number","null"]},"revenue":{"type":["number","null"]},"impressions":{"type":["number","null"]},"link_clicks":{"type":["number","null"]},"purchases":{"type":["number","null"]},"roas":{"type":["number","null"]}}}},{"type":"null"}],"description":"Every day of the range (zeros when nothing delivered); null when status is not ok"},"hint":{"type":["string","null"]},"error":{"type":["string","null"]}},"required":["status"]},"BridgeDailyStats":{"type":"object","properties":{"range":{"type":"object","properties":{"since":{"type":"string"},"until":{"type":"string"}}},"source_ad_account_id":{"type":"string"},"platforms":{"type":"object","properties":{"meta":{"$ref":"#/components/schemas/BridgePlatformDaily"},"tiktok":{"$ref":"#/components/schemas/BridgePlatformDaily"},"snapchat":{"$ref":"#/components/schemas/BridgePlatformDaily"}},"required":["meta","tiktok","snapchat"]}},"required":["range","platforms"]},"TargetingOption":{"type":"object","properties":{"id":{"type":"string","description":"The id or code to put in the launch plan field `use`"},"name":{"type":["string","null"]},"use":{"type":"string","description":"The launch plan field it goes in, e.g. tiktok.adgroup_settings.interest_category_ids"},"level":{"type":["number","null"]},"description":{"type":["string","null"]},"scene":{"type":["string","null"]}},"required":["id","use"]},"TikTokPost":{"type":"object","properties":{"item_id":{"type":["string","null"]},"caption":{"type":["string","null"]},"visibility":{"type":["string","null"]},"account":{"type":"object","properties":{"id":{"type":["string","null"]},"type":{"type":["string","null"]},"name":{"type":["string","null"]}}},"duration_sec":{"type":["number","null"]},"preview_url":{"type":["string","null"]},"authorization":{"type":"object","additionalProperties":true,"description":"A creator's post: its authorization (status, end, days left)"},"usable":{"type":"boolean","description":"false: TikTok would refuse it now (refusals)"},"refusals":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}},"spark_post":{"type":"object","additionalProperties":true,"description":"What goes in a launch plan's ads[].spark_post"}},"required":["item_id","spark_post"]},"TikTokPosts":{"type":"object","properties":{"source":{"type":"string","enum":["account","authorized"]},"available":{"type":"boolean"},"account":{"type":"object","properties":{"id":{"type":["string","null"]},"type":{"type":["string","null"]},"name":{"type":["string","null"]}}},"posts":{"type":"array","items":{"$ref":"#/components/schemas/TikTokPost"}},"next_cursor":{"type":["string","null"],"description":"source account: the next page"},"page":{"type":["number","null"]},"total_pages":{"type":["number","null"]}},"required":["source","posts"]},"TikTokMusics":{"type":"object","properties":{"available":{"type":"boolean"},"query":{"type":["string","null"]},"page":{"type":["number","null"]},"musics":{"type":"array","items":{"type":"object","properties":{"music_id":{"type":["string","null"]},"title":{"type":["string","null"]},"author":{"type":["string","null"]},"duration_sec":{"type":["number","null"]},"preview_url":{"type":["string","null"]}},"required":["music_id"]}},"use":{"type":["string","null"]}},"required":["musics"]},"PlatformTemplates":{"type":"object","properties":{"platform":{"type":"string","enum":["tiktok","snapchat"]},"level":{"type":"string","enum":["adgroup","ad"]},"available":{"type":"boolean","description":"false: templates are not set up on this server"},"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"params":{"type":"object","additionalProperties":true,"description":"The drawer's params as the app saved them"}},"required":["id","name"]}}},"required":["templates"]},"Launch":{"type":"object","properties":{"id":{"type":["string","null"]},"plan_id":{"type":["string","null"]},"finished":{"type":"boolean"},"status":{"type":"string","enum":["not launched","starting","processing","completed","failed","interrupted"]},"files":{"type":"object","properties":{"total":{"type":["number","null"]},"completed":{"type":["number","null"]},"failed":{"type":["number","null"]}}},"result":{"anyOf":[{"type":"object","properties":{"success":{"type":"boolean"},"summary":{"type":"object","additionalProperties":true},"adsets":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]}}}},"ads_ok":{"type":"array","items":{"type":"string"}},"errors":{}}},{"type":"null"}]},"interrupted_at":{"type":["string","null"]},"note":{"type":["string","null"]},"error":{"type":["string","null"]}},"required":["finished","status"]},"LaunchSummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"ad_account_id":{"type":["string","null"]},"status":{"type":"string","enum":["processing","completed","failed","interrupted"]},"files":{"type":"object","properties":{"total":{"type":["number","null"]},"completed":{"type":["number","null"]},"failed":{"type":["number","null"]}}},"created_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"interrupted_at":{"type":["string","null"]}},"required":["id","status"]},"Action":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":["string","null"]},"platform":{"type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":["string","null"]},"status":{"type":"string","enum":["prepared","done","expired"]},"will_do":{"type":["string","null"]},"created_at":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"executed_at":{"type":["string","null"]}},"required":["id","status"]},"ActionResult":{"type":"object","properties":{"id":{"type":"string"},"done":{"type":"boolean"},"type":{"type":["string","null"]},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["id","done","message"]},"LaunchPlanInput":{"type":"object","properties":{"platform":{"description":"Default meta. tiktok / snapchat: the same interview and arguments where they mean the same, their own settings under `tiktok` / `snapchat`, groups made by hand under `adgroups` / `adsquads`","type":"string","enum":["meta","tiktok","snapchat"]},"ad_account_id":{"type":"string","pattern":"^(act_\\d{1,32}|[A-Za-z0-9][A-Za-z0-9-]{0,63})$","description":"The ad account (list_ad_accounts): Meta act_…, a TikTok advertiser id, a Snapchat ad account id"},"campaign_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"campaign\": an existing campaign"},"structure":{"description":"Question \"test_structure\": 1 Adset 1 Ad, 1 Concept 1 Adset, All in One, Insert in Adset","type":"string","enum":["one_adset_one_ad","one_concept_one_adset","all_in_one","insert_in_adset"]},"all_in_one_name":{"description":"All in One: the ad set name (required, unless adset_variants)","type":"string","maxLength":255},"existing_adset_ids":{"description":"Insert: the existing ad sets (Meta), ad groups (TikTok) or ad squads (Snapchat), of campaign_id only (list_adsets with campaign_id lists them)","maxItems":50,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An ad set / ad group / ad squad id"}},"existing_adsets":{"description":"Existing ads (source_ad_id) with insert_in_adset: existing ad sets of one or several campaigns of the ad account, each with its campaign (list_adsets gives campaign_id), every ad in each or its own (ads). Instead of existing_adset_ids; campaign_id defaults to the first one's. 30 ad sets and 300 ads written at most","minItems":1,"maxItems":30,"type":"array","items":{"type":"object","properties":{"campaign_id":{"type":"string","pattern":"^\\d{1,40}$","description":"The ad set's campaign"},"adset_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An existing ad set"},"ads":{"description":"The ads that go into this ad set, each by its ad_name or its source_ad_id. Left out: every ad","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":255}}},"required":["campaign_id","adset_id"],"additionalProperties":false}},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"source_ad_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An ad of this account to reuse with its post (likes and comments stay). Instead of files (get_launch_questions → creatives.choices.existing_ads)"},"files":{"description":"New files: the formats of ONE creative, linked by hand or as proposed (one file per format: 9:16, 4:5, 1:1, 16:9; never a video with an image). Leave out with source_ad_id","minItems":1,"maxItems":10,"type":"array","items":{"type":"object","properties":{"ref":{"type":"string","minLength":1,"maxLength":2048,"description":"drive:<id> (list_drive_folder), or the Apogee storage URL returned by get_upload_urls / confirm_uploads / import_status (your own files only)"},"name":{"type":"string","maxLength":255},"mimeType":{"type":"string","maxLength":100},"format":{"description":"9:16, 4:5, 1:1, 16:9 or auto","type":"string","maxLength":10}},"required":["ref"]}},"concept":{"description":"Concept = ad set name in 1 Concept 1 Adset. Files without it: the ad's own (its name), or \"Group 1\" once other ads have one (the app's Group by hand)","type":"string","minLength":1,"maxLength":255},"ad_name":{"description":"Ad name = ad set name in 1 Adset 1 Ad. Required with files; existing ads: default = the source ad's name + \" - Copy with post ID\"","type":"string","minLength":1,"maxLength":255},"copy":{"description":"This ad's own texts (question \"copy\"). Not with source_ad_id: an existing ad keeps its post","type":"object","properties":{"primary_texts":{"maxItems":5,"type":"array","items":{"type":"string","maxLength":5000}},"headlines":{"maxItems":5,"type":"array","items":{"type":"string","maxLength":255}},"description":{"type":"string","maxLength":255},"website_url":{"type":"string","maxLength":2048},"call_to_action":{"type":"string","maxLength":40}}},"spark_post":{"description":"TikTok Spark Ads: an existing TikTok post run as this ad instead of files (its caption is the ad text, its likes and comments stay), as list_tiktok_posts gives it","type":"object","properties":{"tiktok_item_id":{"type":"string","pattern":"^\\d{1,40}$","description":"The TikTok post (list_tiktok_posts: its spark_post)"},"identity":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"The account that posted it"},"type":{"type":"string","enum":["TT_USER","BC_AUTH_TT","AUTH_CODE"],"description":"TT_USER / BC_AUTH_TT: one of the brand's TikTok accounts; AUTH_CODE: a creator who authorized the post for this ad account"},"bc_id":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"BC_AUTH_TT: its Business Center"},{"type":"null"}]}},"required":["id","type"],"additionalProperties":false}},"required":["tiktok_item_id","identity"],"additionalProperties":false}}},"description":"The confirmed ads (get_launch_questions proposed_ads, corrected by the user), or the existing ads to reuse (each either files or source_ad_id, all the same kind; 50 existing ads max)"},"adset_variants":{"description":"all_in_one: the same ads in 1-5 new ad sets, each with its own bid / budget (e.g. two cost caps), or each with its own ads (ads)","minItems":1,"maxItems":5,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"The new ad set's name"},"bid_amount":{"description":"Cost cap / bid cap, in the account currency","type":"number","exclusiveMinimum":0},"roas_floor":{"description":"Minimum ROAS strategy, e.g. 2.5","type":"number","exclusiveMinimum":0},"daily_budget":{"description":"ABO only, account currency","type":"number","exclusiveMinimum":0},"ads":{"description":"Existing ads (source_ad_id) only: the ads that go into this new ad set, each by its ad_name or its source_ad_id. Left out on every ad set: every ad in each. Given on one: every ad set needs its own, and every ad must be in one at least","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":255}}},"required":["name"]}},"adsets":{"description":"New files: the ads arranged into new ad sets by hand, on top of structure one_adset_one_ad, one_concept_one_adset or all_in_one. Launched as 1 Concept 1 Adset (each ad set = a concept), the ad names unchanged; every ad set takes the plan's ad set settings. Not with insert_in_adset, adset_variants or existing ads","minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"The new ad set's name"},"ads":{"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ads that go into it, by their ad_name (each ad in exactly one ad set)"}},"required":["name","ads"],"additionalProperties":false}},"nomenclature":{"description":"Question \"nomenclature\", when a saved convention reads the names: named in the recap. Files grouped by hand: leave it out","type":"object","properties":{"config_id":{"description":"The saved naming convention used, null when none","anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"name":{"type":"string","maxLength":255},"confirmed":{"type":"boolean","const":true,"description":"true = the user validated the parsed concepts / iterations / formats"}},"required":["confirmed"]},"grouping_confirmed":{"description":"Question \"grouping\": true = the user validated the ads (their names and files), read by a convention or grouped by hand","type":"boolean","const":true},"copy_adset_from":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"starting_point\": the ad set / ad group / ad squad whose settings are copied (\"latest\" = TikTok: the latest ad group of campaign_id)"},"adset_template_id":{"description":"Question \"starting_point\": a saved Apogee ad set template","type":"string","maxLength":64},"adset_settings":{"description":"A new ad set (questions \"audience\", \"tracking\"), or the changes to a copied ad set / template","type":"object","properties":{"goal":{"description":"New ad set only. Default: from the campaign objective","type":"string","enum":["sales","leads_website","leads_instant_form","traffic","engagement","awareness","app_installs"]},"countries":{"description":"ISO codes, e.g. [\"FR\"] (a new ad set needs countries, regions or cities)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"regions":{"description":"Region keys from search_targeting(type: locations)","maxItems":200,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":32}},"required":["key"]}},"cities":{"description":"City keys from search_targeting(type: locations)","maxItems":250,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":32},"radius":{"type":"number","minimum":1,"maximum":80},"distance_unit":{"type":"string","enum":["kilometer","mile"]}},"required":["key"]}},"age_min":{"type":"integer","minimum":13,"maximum":65},"age_max":{"type":"integer","minimum":13,"maximum":65},"genders":{"description":"Default all","type":"string","enum":["all","men","women"]},"locales":{"description":"Language keys from search_targeting(type: locales)","maxItems":50,"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"advantage_audience":{"description":"Default true (broad)","type":"boolean"},"custom_audience_ids":{"description":"list_custom_audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"excluded_audience_ids":{"description":"list_custom_audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"interests":{"description":"search_targeting(type: interests)","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"behaviors":{"description":"search_targeting(type: behaviors)","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"life_events":{"description":"search_targeting(type: demographics): the app's demographics / life events","maxItems":100,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","maxLength":255}},"required":["id"]}},"placements":{"description":"\"advantage\" (Advantage+ placements, the default) or the platforms to keep","anyOf":[{"type":"string","const":"advantage"},{"type":"object","properties":{"publisher_platforms":{"minItems":1,"type":"array","items":{"type":"string","enum":["facebook","instagram","messenger","audience_network"]}}},"required":["publisher_platforms"]}]},"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (list_pixels)"},"event":{"description":"Meta enum: PURCHASE, LEAD, CONTENT_VIEW, INITIATED_CHECKOUT, ADD_TO_CART, COMPLETE_REGISTRATION…","type":"string","maxLength":64},"custom_event_str":{"description":"A pixel custom event name (sent as OTHER + this name)","type":"string","maxLength":100},"custom_conversion_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom conversion (sent alone)"},"optimization_goal":{"description":"New ad set: overrides the default optimization (e.g. LINK_CLICKS for traffic). app_installs: APP_INSTALLS (default), OFFSITE_CONVERSIONS + event (an app event) or VALUE","type":"string","maxLength":64},"bid_strategy":{"description":"ABO: the new ad sets' strategy (default Lowest cost, the highest volume). CBO: must be the campaign's (or leave it out)","type":"string","enum":["LOWEST_COST_WITHOUT_CAP","COST_CAP","LOWEST_COST_WITH_BID_CAP","LOWEST_COST_WITH_MIN_ROAS"]},"bid_amount":{"description":"COST_CAP / LOWEST_COST_WITH_BID_CAP: the cost per result goal (cost cap) or bid cap of every new ad set, account currency (adset_variants: one each)","type":"number","exclusiveMinimum":0},"roas_floor":{"description":"LOWEST_COST_WITH_MIN_ROAS: the minimum ROAS of every new ad set, e.g. 2.5 (adset_variants: one each)","type":"number","exclusiveMinimum":0},"attribution":{"description":"Default 7-day click, 1-day view, 1-day engaged view","type":"object","properties":{"click":{"type":"string","enum":["1_day","7_days"]},"view":{"type":"string","enum":["none","1_day","7_days"]},"engaged_view":{"type":"string","enum":["none","1_day","7_days"]}},"required":["click"]},"application_id":{"type":"string","pattern":"^\\d{1,40}$","description":"app_installs: the app to promote (get_launch_questions → tracking.choices.apps; default: the ad account's only app)"},"object_store_url":{"description":"app_installs: its App Store / Play Store link (choices.apps[].store_urls; default: the app's only one). The ads link to it","type":"string","maxLength":2048},"customer_lifecycle":{"description":"Sales campaigns only: the new ad sets' Customer lifecycle strategy. Left out: a copied ad set or template keeps its own, a new ad set gets conversions from all audiences","type":"object","properties":{"goal":{"type":"string","enum":["BROAD","EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS","EXCLUDE_EXISTING_CUSTOMERS"],"description":"BROAD = \"Get conversions from all audiences\" (the default); EXCLUDE_EXISTING_CUSTOMERS = \"New customer acquisition\" (Meta excludes the existing customers); EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS = New customer acquisition, the engaged audiences excluded too"},"existing_customers":{"description":"The custom audiences of the existing customers (list_custom_audiences). Default: the ad account's own definition of its existing customers, when it has one","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}},"engaged_audiences":{"description":"EXCLUDE_EXISTING_AND_ENGAGED_CUSTOMERS only (required there): the custom audiences of the engaged audiences","maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience id"}}},"required":["goal"],"additionalProperties":false},"dsa":{"description":"New ad sets in the EU: their beneficiary and payer. Left out: a template's own, else the ad account's (get_launch_questions → advertiser.current)","type":"object","properties":{"beneficiary":{"type":"string","minLength":1,"maxLength":255,"description":"Who the ads promote (Ads Manager: Advertiser)"},"payer":{"description":"Who pays for them, when another (default: the beneficiary)","type":"string","minLength":1,"maxLength":255}},"required":["beneficiary"],"additionalProperties":false}},"additionalProperties":false},"copy_ad_from":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"Question \"starting_point\": the ad whose settings are copied (\"latest\" = TikTok: the latest ad)"},"ad_template_id":{"description":"Question \"starting_point\": a saved Apogee ad template","type":"string","maxLength":64},"ad_settings":{"description":"A new ad (questions \"identity\", \"destination\"), or the changes to a copied ad / template","type":"object","properties":{"page_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A Facebook page (list_pages)"},"instagram_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$","description":"Default: the page's linked Instagram"},{"type":"null"}]},"partnership":{"description":"A partnership ad with a creator who approved the brand's Instagram account, or whose Facebook Page accepted the brand's Page; null = none (default)","anyOf":[{"type":"object","properties":{"creator_ig_id":{"type":"string","pattern":"^\\d{1,40}$","description":"An Instagram creator (get_launch_questions → identity.choices.partnership_creators, source instagram)"},"creator_username":{"type":"string","maxLength":100},"creator_fb_page_id":{"anyOf":[{"type":"string","pattern":"^\\d{1,40}$","description":"An Instagram creator's Page (default: read from the approved creators; null: none), or alone a Facebook creator (source facebook)"},{"type":"null"}]},"creator_name":{"description":"A Facebook creator's Page name (as listed)","type":"string","maxLength":200},"ad_code":{"description":"Not used: a partnership ad code boosts the creator's own post, Apogee launches your files. Use creator_ig_id","type":"string","maxLength":200},"identity_mode":{"description":"advertiser_primary = your brand first (default); creator_primary = the creator first (on Instagram only when the creator has no Facebook Page)","type":"string","enum":["advertiser_primary","creator_primary"]},"header_display":{"description":"dynamic (default, Meta picks; optimizes on Instagram only), both identities, or the first identity only","type":"string","enum":["dynamic","both","primary_only"]}},"additionalProperties":false},{"type":"null"}]},"website_url":{"description":"Required except for instant forms and app ads (they link to adset_settings.object_store_url)","type":"string","maxLength":2048},"url_parameters":{"description":"UTM parameters, \"\" = none (required for a new ad)","type":"string","maxLength":1000},"call_to_action":{"description":"Required for a new ad, e.g. SHOP_NOW, LEARN_MORE, SIGN_UP. An app ad: INSTALL_MOBILE_APP (default), USE_MOBILE_APP, PLAY_GAME…","type":"string","maxLength":40},"lead_form_id":{"type":"string","pattern":"^\\d{1,40}$","description":"Instant form leads (list_lead_forms)"},"display_link":{"type":"string","maxLength":255}},"additionalProperties":false},"advantage_plus":{"description":"Question \"advantage_plus\" (required)","type":"object","properties":{"opt_in":{"type":"array","items":{"type":"string","enum":["text_optimizations","product_tags","creative_stickers","inline_comment","enhance_cta","reveal_details_over_time","show_destination_blurbs","show_summary","optimize_website_destination","shop","product_browsing","browser_addons","image_brightness_and_contrast","image_templates","image_touchups","video_auto_crop","video_filtering"]},"description":"The enhancements the user turned ON; every other one is sent OFF. [] = all off"},"multi_advertiser_ads":{"description":"Multi-advertiser ads (the ad's Format in Ads Manager): false = out (OPT_OUT). Left out: the copied ad's or template's, else in (Meta's default)","type":"boolean"}},"required":["opt_in"]},"products":{"description":"Question \"products\" (required when the account has a catalog)","type":"object","properties":{"show":{"type":"boolean","description":"\"Show relevant products\" from the catalog"},"catalog_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A catalog (get_launch_questions → products)"},"product_set_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A product set of that catalog"}},"required":["show"]},"daily_budget":{"description":"ABO: daily budget of each new ad set, account currency (required)","type":"number","exclusiveMinimum":0},"launch_status":{"description":"Created Paused (default), Live Now, Scheduled & Paused, Scheduled & Live","type":"string","enum":["CREATED_PAUSED","LIVE_NOW","SCHEDULED_PAUSED","SCHEDULED_LIVE"]},"schedule":{"description":"Scheduled & Paused / Scheduled & Live. Insert in Adset on Meta: each ad's start, Sales and App promotion campaigns only","type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"YYYY-MM-DD"},"time":{"type":"string","pattern":"^\\d{2}:\\d{2}$","description":"HH:MM, in time_zone"},"time_zone":{"description":"The IANA zone of date and time, e.g. Europe/London for a UK campaign. Default the ad account's","type":"string","maxLength":64}},"required":["date","time"]},"ad_overrides":{"description":"Advanced: raw ad template fields (description, display_link, url_parameters, website_url, call_to_action, instagram_account_id, lead_gen_form_id, primary_texts, headlines)","type":"object","properties":{"description":{},"display_link":{},"url_parameters":{},"website_url":{},"call_to_action":{},"instagram_account_id":{},"lead_gen_form_id":{},"primary_texts":{},"headlines":{}},"additionalProperties":false},"adset_overrides":{"description":"Advanced: raw ad set template fields (name, billing_event, optimization_goal, destination_type, daily_min_spend_target, daily_spend_cap, start_time, end_time, bid_strategy, bid_amount, bid_constraints, attribution_spec, attribution_setting, targeting), Meta's units","type":"object","properties":{"name":{},"billing_event":{},"optimization_goal":{},"destination_type":{},"daily_min_spend_target":{},"daily_spend_cap":{},"start_time":{},"end_time":{},"bid_strategy":{},"bid_amount":{},"bid_constraints":{},"attribution_spec":{},"attribution_setting":{},"targeting":{}},"additionalProperties":false},"adgroups":{"description":"TikTok: ad groups made by hand, instead of structure","minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"A new ad group's name","type":"string","minLength":1,"maxLength":255},"existing_adgroup_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An existing ad group to fill instead (all groups existing, or all new)"},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ad_name of each ad in it (every ad in exactly one group)"},"settings":{"description":"This ad group's own settings, over the shared ones","type":"object","properties":{"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (get_launch_questions → tracking.choices.pixels)"},"optimization_event":{"description":"TikTok's optimization_event: SHOPPING (purchase), INITIATE_ORDER, ON_WEB_CART, ON_WEB_DETAIL, ON_WEB_REGISTER, FORM…","type":"string","maxLength":64},"bid_type":{"description":"Default BID_TYPE_NO_BID (maximum delivery); BID_TYPE_CUSTOM = cost cap (bid)","type":"string","enum":["BID_TYPE_NO_BID","BID_TYPE_CUSTOM"]},"bid":{"description":"Cost cap per conversion (BID_TYPE_CUSTOM), account currency","type":"number","exclusiveMinimum":0},"pacing":{"type":"string","enum":["PACING_MODE_SMOOTH","PACING_MODE_FAST"]},"countries":{"description":"ISO codes, read into TikTok location ids (or location_ids)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"location_ids":{"maxItems":500,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A TikTok location id"}},"age_groups":{"description":"[] or absent = every age","maxItems":6,"type":"array","items":{"type":"string","enum":["AGE_13_17","AGE_18_24","AGE_25_34","AGE_35_44","AGE_45_54","AGE_55_100"]}},"gender":{"type":"string","enum":["GENDER_UNLIMITED","GENDER_MALE","GENDER_FEMALE"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"An interest category"}},"action_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A behaviour category"}},"audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"excluded_audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"placements":{"description":"Default TikTok only","minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["PLACEMENT_TIKTOK","PLACEMENT_PANGLE","PLACEMENT_GLOBAL_APP_BUNDLE"]}}},"additionalProperties":false},"daily_budget":{"description":"ABO: this one's budget (default daily_budget)","type":"number","exclusiveMinimum":0}},"required":["ads"],"additionalProperties":false}},"adsquads":{"description":"Snapchat: ad squads made by hand, instead of structure","minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"A new ad squad's name","type":"string","minLength":1,"maxLength":255},"existing_adsquad_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"An existing ad squad to fill instead (all groups existing, or all new)"},"ads":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":255},"description":"The ad_name of each ad in it (every ad in exactly one group)"},"settings":{"description":"This ad squad's own settings, over the shared ones","type":"object","properties":{"optimization_goal":{"description":"Default PIXEL_PURCHASE. The PIXEL_ goals need pixel_id (and enough of that event on the pixel lately: get_launch_questions tracking.choices.optimization_goals); SWIPES and LANDING_PAGE_VIEW need none","type":"string","enum":["PIXEL_PURCHASE","PIXEL_ADD_TO_CART","PIXEL_SIGNUP","PIXEL_PAGE_VIEW","SWIPES","LANDING_PAGE_VIEW"]},"pixel_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap pixel (get_launch_questions → tracking.choices.pixels)"},"bid_strategy":{"description":"Default AUTO_BID","type":"string","enum":["AUTO_BID","LOWEST_COST_WITH_MAX_BID","TARGET_COST"]},"bid":{"description":"LOWEST_COST_WITH_MAX_BID / TARGET_COST: the bid, account currency","type":"number","exclusiveMinimum":0},"pacing_type":{"description":"Default STANDARD","type":"string","enum":["STANDARD","ACCELERATED"]},"conversion_window":{"description":"Default Snapchat's SWIPE_28DAY_VIEW_1DAY","type":"string","enum":["SWIPE_28DAY_VIEW_1DAY","SWIPE_7DAY"]},"countries":{"description":"ISO codes (at least one for a new ad squad)","minItems":1,"maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"region_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":32}},"min_age":{"description":"Default 18 for a new ad squad: Snapchat refuses its goal for under-18s in the EU, the EEA, Switzerland and the UK","type":"integer","minimum":13,"maximum":65},"max_age":{"type":"integer","minimum":13,"maximum":65},"genders":{"type":"string","enum":["all","men","women"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":64}},"segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}},"excluded_segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}}},"additionalProperties":false},"daily_budget":{"description":"ABO: this one's budget (default daily_budget)","type":"number","exclusiveMinimum":0}},"required":["ads"],"additionalProperties":false}},"tiktok":{"description":"TikTok's own settings (platform tiktok)","type":"object","properties":{"new_campaign":{"description":"A new Sales campaign (website conversions; Standard, or Upgraded Smart+), created by the launch (instead of campaign_id)","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"budget_type":{"type":"string","enum":["abo","cbo"],"description":"abo = a budget per ad group (daily_budget); cbo = the campaign's budget"},"budget":{"description":"CBO: the campaign budget, account currency","type":"number","exclusiveMinimum":0},"budget_mode":{"description":"Default daily","type":"string","enum":["daily","lifetime"]},"smart_plus":{"description":"true = an Upgraded Smart+ campaign (website Sales), as the app's Create Campaign: up to 30 ad groups of 30 ads, one ad per creative (its texts rotate inside), TikTok's dynamic CTA (ad_settings.cta_language / cta_texts), no Spark post. Default: a Standard campaign","type":"boolean"}},"required":["name","budget_type"],"additionalProperties":false},"adgroup_settings":{"description":"A new ad group's settings, or the changes to a copied one (copy_adset_from)","type":"object","properties":{"pixel_id":{"type":"string","pattern":"^\\d{1,40}$","description":"A pixel (get_launch_questions → tracking.choices.pixels)"},"optimization_event":{"description":"TikTok's optimization_event: SHOPPING (purchase), INITIATE_ORDER, ON_WEB_CART, ON_WEB_DETAIL, ON_WEB_REGISTER, FORM…","type":"string","maxLength":64},"bid_type":{"description":"Default BID_TYPE_NO_BID (maximum delivery); BID_TYPE_CUSTOM = cost cap (bid)","type":"string","enum":["BID_TYPE_NO_BID","BID_TYPE_CUSTOM"]},"bid":{"description":"Cost cap per conversion (BID_TYPE_CUSTOM), account currency","type":"number","exclusiveMinimum":0},"pacing":{"type":"string","enum":["PACING_MODE_SMOOTH","PACING_MODE_FAST"]},"countries":{"description":"ISO codes, read into TikTok location ids (or location_ids)","maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"location_ids":{"maxItems":500,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A TikTok location id"}},"age_groups":{"description":"[] or absent = every age","maxItems":6,"type":"array","items":{"type":"string","enum":["AGE_13_17","AGE_18_24","AGE_25_34","AGE_35_44","AGE_45_54","AGE_55_100"]}},"gender":{"type":"string","enum":["GENDER_UNLIMITED","GENDER_MALE","GENDER_FEMALE"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"An interest category"}},"action_category_ids":{"maxItems":200,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A behaviour category"}},"audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"excluded_audience_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{1,40}$","description":"A custom audience"}},"placements":{"description":"Default TikTok only","minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["PLACEMENT_TIKTOK","PLACEMENT_PANGLE","PLACEMENT_GLOBAL_APP_BUNDLE"]}}},"additionalProperties":false},"ad_settings":{"description":"The ads' TikTok account (and whether their videos show on its profile), destination and CTA (new, or the changes to a copied ad); Smart+ and carousel settings","type":"object","properties":{"identity":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"The identity id (get_launch_questions → identity.choices.identities)"},"type":{"type":"string","enum":["TT_USER","BC_AUTH_TT"],"description":"One of the brand's TikTok accounts: TT_USER, or BC_AUTH_TT through its Business Center (TikTok refuses a custom identity on these ads)"},"bc_id":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"BC_AUTH_TT: the Business Center"},{"type":"null"}]}},"required":["id","type"],"additionalProperties":false},"show_on_profile":{"description":"The app's \"Also show the video on the TikTok profile\": true = the video is also posted on the TikTok account's profile; default: it only runs as an ad (TikTok's default). Not where TikTok keeps the videos ads-only (get_launch_questions identity.show_on_profile)","type":"boolean"},"website_url":{"description":"Apogee's TikTok tracking replaces its own utm_ parameters (no UTM option on TikTok: the app's final URL)","type":"string","maxLength":2048},"call_to_action":{"description":"Default SHOP_NOW (a Standard ad's; a Smart+ ad runs TikTok's dynamic CTA: cta_language, cta_texts)","type":"string","enum":["SHOP_NOW","BUY_NOW","ORDER_NOW","LEARN_MORE","SIGN_UP","DOWNLOAD_NOW","CONTACT_US","BOOK_NOW"]},"cta_language":{"description":"Smart+: the language of TikTok's dynamic call to action when the ad group lends none (default en)","type":"string","enum":["en","fr","de","es","it","nl","pt","pl","sv"]},"cta_texts":{"description":"Smart+: the calls to action kept among the ones TikTok offers in cta_language (default: TikTok's whole list)","maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":40}},"automations":{"description":"Smart+: TikTok's automations of the ads (as Meta's Advantage+ creative enhancements), each off unless turned on","type":"object","properties":{"auto_add":{"description":"TikTok adds assets of its own","type":"boolean"},"enhancements":{"maxItems":5,"type":"array","items":{"type":"string","enum":["TRANSLATE_AND_DUB","MUSIC_REFRESH","VIDEO_QUALITY","IMAGE_QUALITY","IMAGE_RESIZE"]}}},"additionalProperties":false},"music_id":{"description":"Carousels (image ads): the music, one of list_tiktok_music; default TikTok's pick at the launch","type":"string","pattern":"^\\d{1,40}$"}},"additionalProperties":false},"carousel_mode":{"description":"Images run as carousels (TikTok's image ads), as the app's Configure switch: single (default) = each image ad a carousel of its image; by_concept = a concept's images one carousel ad named after the concept (35 images at most, its first ad's settings and texts)","type":"string","enum":["single","by_concept"]},"adgroup_template_id":{"description":"Quick Bulk Edit: a saved ad group template (list_platform_templates level adgroup), the base of the new ad groups' settings (instead of copy_adset_from); adgroup_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ad_template_id":{"description":"Quick Bulk Edit: a saved ad template (list_platform_templates level ad), the base of the ads' settings (instead of copy_ad_from); ad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"time_zone":{"description":"The IANA zone of schedule, e.g. Europe/London for a UK campaign. Default the advertiser's","type":"string","maxLength":64},"end_date":{"description":"A lifetime campaign budget (CBO, budget_mode lifetime, a new campaign or an existing one): the date it runs to, YYYY-MM-DD in the schedule's time zone, after the launch (a scheduled launch: TikTok spreads the budget until then). Ignored for a daily budget","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"end_time":{"description":"HH:MM of end_date, default the start's time","type":"string","pattern":"^\\d{2}:\\d{2}$"}},"additionalProperties":false},"snapchat":{"description":"Snapchat's own settings (platform snapchat)","type":"object","properties":{"new_campaign":{"description":"A new Sales campaign, created by the launch (instead of campaign_id)","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"budget_type":{"type":"string","enum":["abo","cbo"],"description":"abo = a budget per ad squad (daily_budget, 5 minimum); cbo = the campaign's (20 minimum per day), Snapchat's Smart Budget: its ad squads share their optimisation goal, pixel, bid strategy and conversion window (get_launch_questions tracking.choices); a lower budget is raised to it"},"budget":{"description":"CBO: the campaign budget per day, account currency","type":"number","exclusiveMinimum":0}},"required":["name","budget_type"],"additionalProperties":false},"adsquad_settings":{"description":"A new ad squad's settings, or the changes to a copied one (copy_adset_from)","type":"object","properties":{"optimization_goal":{"description":"Default PIXEL_PURCHASE. The PIXEL_ goals need pixel_id (and enough of that event on the pixel lately: get_launch_questions tracking.choices.optimization_goals); SWIPES and LANDING_PAGE_VIEW need none","type":"string","enum":["PIXEL_PURCHASE","PIXEL_ADD_TO_CART","PIXEL_SIGNUP","PIXEL_PAGE_VIEW","SWIPES","LANDING_PAGE_VIEW"]},"pixel_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap pixel (get_launch_questions → tracking.choices.pixels)"},"bid_strategy":{"description":"Default AUTO_BID","type":"string","enum":["AUTO_BID","LOWEST_COST_WITH_MAX_BID","TARGET_COST"]},"bid":{"description":"LOWEST_COST_WITH_MAX_BID / TARGET_COST: the bid, account currency","type":"number","exclusiveMinimum":0},"pacing_type":{"description":"Default STANDARD","type":"string","enum":["STANDARD","ACCELERATED"]},"conversion_window":{"description":"Default Snapchat's SWIPE_28DAY_VIEW_1DAY","type":"string","enum":["SWIPE_28DAY_VIEW_1DAY","SWIPE_7DAY"]},"countries":{"description":"ISO codes (at least one for a new ad squad)","minItems":1,"maxItems":250,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"region_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":32}},"min_age":{"description":"Default 18 for a new ad squad: Snapchat refuses its goal for under-18s in the EU, the EEA, Switzerland and the UK","type":"integer","minimum":13,"maximum":65},"max_age":{"type":"integer","minimum":13,"maximum":65},"genders":{"type":"string","enum":["all","men","women"]},"languages":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":16}},"interest_ids":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":64}},"segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}},"excluded_segment_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A Snap audience segment"}}},"additionalProperties":false},"ad_settings":{"description":"The ads' profile, destination and CTA (new, or the changes to a copied ad)","type":"object","properties":{"profile_id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$","description":"A public profile (get_launch_questions → identity.choices.profiles)"},"website_url":{"description":"https only","type":"string","maxLength":2048},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":200},"medium":{"type":"string","maxLength":200},"campaign":{"type":"string","maxLength":200},"id":{"type":"string","maxLength":200},"content":{"type":"string","maxLength":200}},"additionalProperties":false,"description":"UTM parameters appended to the URL (the app's UTM toggle): given = on, the app's defaults for the fields left out"},"call_to_action":{"description":"Default SHOP_NOW","type":"string","enum":["SHOP_NOW","ORDER_NOW","SIGN_UP","GET_NOW","BOOK_NOW","VIEW","MORE","READ","WATCH","DOWNLOAD","APPLY_NOW","BUY_TICKETS","PLAY_GAME","LISTEN"]},"brand_name":{"type":"string","maxLength":32}},"additionalProperties":false},"adsquad_template_id":{"description":"Quick Bulk Edit: a saved ad squad template (list_platform_templates level adgroup), the base of the new ad squads' settings (instead of copy_adset_from); adsquad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ad_template_id":{"description":"Quick Bulk Edit: a saved ad template (list_platform_templates level ad), the base of the ads' settings (instead of copy_ad_from); ad_settings over it","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"time_zone":{"description":"The IANA zone of schedule, e.g. Europe/London for a UK campaign. Default the ad account's","type":"string","maxLength":64}},"additionalProperties":false}},"required":["ad_account_id","ads"],"additionalProperties":false,"description":"POST /launch-plans body (the interview's answers)"}},"responses":{"Problem400":{"description":"The request is not valid (validation_failed, idempotency_key_required, request_refused)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem401":{"description":"Missing, invalid, revoked or expired API key (invalid_api_key)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem402":{"description":"The Apogee plan does not include this feature (plan_required)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem403":{"description":"The key lacks the scope (insufficient_scope), the account's plan does not include the feature (upgrade_required: feature, required_plan), Meta, TikTok or Snapchat refused the access, or the TikTok / Snapchat ad account is not one the user connected (account_not_connected)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem404":{"description":"Not found (not_found)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem409":{"description":"Already done or in progress (plan_already_launched, action_already_ran, idempotency_in_progress)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem410":{"description":"Prepared more than 24 hours ago (plan_expired, action_expired)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem412":{"description":"The Facebook (or Google Drive) connection is missing or expired: log in to the app again (meta_not_connected); a TikTok / Snapchat connection was revoked or expired (platform_not_connected)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem422":{"description":"Open questions or a refused request (missing_answers, idempotency_key_reused, budget_above_cap, launch_refused)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem429":{"description":"Too many requests (rate_limited), or Meta, TikTok or Snapchat throttles the account (meta_rate_limited, platform_rate_limited): see Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem500":{"description":"Apogee failed (internal_error): it was recorded","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem502":{"description":"Meta, TikTok, Snapchat or another service failed (meta_error, platform_error, upstream_error, launch_failed)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Problem503":{"description":"Not available on this environment yet (feature_not_ready)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}