{"openapi":"3.1.0","info":{"title":"ROAS.to API","version":"1.0.0","description":"The ROAS.to API: report on, manage, and launch Facebook campaigns; run landing-page A/B tests; send conversions; and receive webhooks.\n\n**Authentication** — `Authorization: Bearer roas_…` (or `x-api-key: roas_…`). Create keys in Settings → API Keys. Each key carries scopes (what it may touch) and acts with its creator's role and ad-account access — a key can never do more than the person who created it.\n\n**Writes** — every write accepts an `Idempotency-Key` header (a retry returns the original response with `Idempotent-Replay: true`), `created_by` (recorded in the audit log), and most accept `dry_run: true` (preview without changing anything). Facebook writes return Meta's readback under `verified`. Writes matched by a workspace approval rule return **202** with `pending_action_id`; poll `GET /v1/approvals/{id}`.\n\n**Money** — request bodies use MAJOR units of the ad account currency (dollars, not cents). Response fields ending in `_minor` (including Meta readbacks under `verified`) are integer minor units.\n\n**Dates** — timestamps are returned in the workspace timezone (`X-Timezone` header). Ranges: `date_range` (e.g. last_7d) or `start_date` + `end_date` (YYYY-MM-DD, inclusive).\n\n**Rate limits** — 300 reads and 60 writes per minute per key. Every response carries `X-RateLimit-Limit/Remaining/Reset`; a 429 carries `Retry-After`.\n\n**Errors** — `{ \"error\": { \"code\", \"message\", … } }` with stable codes: unauthorized, forbidden, not_found, invalid_request (+ `problems[]`), conflict, unprocessable, rate_limit_exceeded, upstream_error, internal_error, service_unavailable. Every response has an `X-Request-Id`."},"servers":[{"url":"https://api.roas.to"}],"tags":[{"name":"Account"},{"name":"Facebook reporting"},{"name":"Facebook analytics"},{"name":"Facebook launch"},{"name":"Facebook assets"},{"name":"Facebook management"},{"name":"Media"},{"name":"Automation rules"},{"name":"Clone rules"},{"name":"Auto-boost rules"},{"name":"Conversions"},{"name":"Approvals"},{"name":"Webhooks"},{"name":"Page tests"},{"name":"Link tests"}],"paths":{"/v1":{"get":{"operationId":"apiIndex","summary":"API index","description":"Version, docs links, rate limits, and every endpoint with its required scope.","tags":["Account"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":[],"x-minimum-role":"viewer","responses":{"200":{"description":"Index.","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":["string","null"]},"version":{"type":["string","null"]},"documentation":{"type":["string","null"]},"openapi":{"type":["string","null"]},"rate_limits":{"type":"object","properties":{"reads_per_minute":{"type":["number","null"]},"writes_per_minute":{"type":["number","null"]}}},"endpoints":{"type":"array","items":{"type":"object","properties":{"method":{"type":["string","null"]},"path":{"type":["string","null"]},"scope":{"type":"array","items":{}},"summary":{"type":["string","null"]}}}}}},"example":{"name":"ROAS.to API","version":"v1","documentation":"https://www.roas.to/docs/api","openapi":"https://api.roas.to/v1/openapi.json","rate_limits":{"reads_per_minute":300,"writes_per_minute":60},"endpoints":[{"method":"GET","path":"/v1/me","scope":[],"summary":"Who am I"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/me":{"get":{"operationId":"getMe","summary":"Who am I","description":"The workspace, key, scopes, and role this key acts with, plus the ad accounts it can see (null = every account). Use it to check a key's access before calling anything else.","tags":["Account"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":[],"x-minimum-role":"viewer","responses":{"200":{"description":"Key identity.","content":{"application/json":{"schema":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]},"timezone":{"type":["string","null"]}}},"key":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]},"prefix":{"type":["string","null"]}}},"acting_as":{"type":"object","properties":{"role":{"type":["string","null"]},"user_id":{"type":["string","null"]}}},"scopes":{"type":"array","items":{"type":["string","null"]}},"account_scope":{"type":["null","string","number","object"]},"rate_limits":{"type":"object","properties":{"reads_per_minute":{"type":["number","null"]},"writes_per_minute":{"type":["number","null"]}}}}},"example":{"workspace":{"id":"0d4c1a52-7b2e-4c3d-9e8f-1a2b3c4d5e6f","name":"Acme Media","timezone":"America/New_York"},"key":{"id":"7e1f2a3b-4c5d-4e6f-8a9b-0c1d2e3f4a5b","name":"Agent","prefix":"roas_1a2b3"},"acting_as":{"role":"admin","user_id":"user_2abc"},"scopes":["read:campaigns","write:status"],"account_scope":null,"rate_limits":{"reads_per_minute":300,"writes_per_minute":60}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/accounts":{"get":{"operationId":"listAdAccounts","summary":"List ad accounts","description":"Connected ad accounts with currency, timezone, Meta account status, platform fee, and last sync times. `account_status` is Meta’s enum name (ACTIVE, DISABLED, UNSETTLED, …), refreshed every few hours. `fee_pct` is the platform surcharge you set for the account (0 when none).","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","responses":{"200":{"description":"Accounts.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":["number","null"]},"accounts":{"type":"array","items":{"type":"object","properties":{"fb_account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"account_status":{"type":["string","null"]},"account_status_code":{"type":["number","null"]},"disable_reason":{"type":["number","null"]},"currency":{"type":["string","null"]},"timezone_name":{"type":["string","null"]},"business_id":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"fee_pct":{"type":["number","null"]},"last_campaigns_sync":{"type":["string","null"]},"last_insights_sync":{"type":["string","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"count":2,"accounts":[{"fb_account_id":"act_123456789","name":"My Ad Account","account_status":"ACTIVE","account_status_code":1,"disable_reason":0,"currency":"USD","timezone_name":"America/New_York","business_id":"987654321","is_active":true,"fee_pct":2,"last_campaigns_sync":"2026-04-05T09:30:00.000-04:00","last_insights_sync":"2026-04-05T09:15:00.000-04:00","created_at":"2026-01-12T14:02:11.000-05:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/accounts/{account_id}":{"patch":{"operationId":"updateAdAccount","summary":"Update an ad account’s settings","description":"Set the platform surcharge for an ad account. `fee_pct` is a percent on top of Meta spend (2 = spend + 2%). It feeds `spend_with_fees` and `profit_after_fees` on campaign rows; nothing is sent to Meta.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:budgets"],"x-minimum-role":"admin","parameters":[{"name":"account_id","in":"path","required":true,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fee_pct":{"type":"number","minimum":0,"maximum":100,"description":"Surcharge percent, e.g. 2 for 2%."}},"required":["fee_pct"]}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":["string","null"]},"fee_pct":{"type":["number","null"]}}},"example":{"account_id":"act_123456789","fee_pct":2}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/campaigns":{"get":{"operationId":"listCampaigns","summary":"List campaigns with performance","description":"Campaigns with aggregated Facebook metrics and tracked conversions for the date range.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"status","in":"query","required":false,"description":"Filter by status (ACTIVE, PAUSED, …). ACTIVE means currently serving.","schema":{"type":"string","maxLength":40}},{"name":"min_spend","in":"query","required":false,"description":"Only campaigns that spent at least this much (account currency) in the date range.","schema":{"type":"number","minimum":0}},{"name":"has_spend","in":"query","required":false,"description":"true: only campaigns with any spend in the date range.","schema":{"type":"string","enum":["true","false"]}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Campaigns.","content":{"application/json":{"schema":{"type":"object","properties":{"date_range":{"type":"object","properties":{"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]}}},"count":{"type":["number","null"]},"campaigns":{"type":"array","items":{"type":"object","properties":{"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"objective":{"type":["string","null"]},"status":{"type":["string","null"]},"daily_budget_minor":{"type":["number","null"]},"lifetime_budget_minor":{"type":["null","string","number","object"]},"spend_cap_minor":{"type":["null","string","number","object"]},"total_ad_sets":{"type":["number","null"]},"active_ad_sets":{"type":["number","null"]},"fb_impressions":{"type":["number","null"]},"fb_clicks":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"fb_ctr":{"type":["number","null"]},"fb_cpc":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]},"true_cpa":{"type":["number","null"]},"bid_strategy":{"type":["string","null"]},"bid_amount_minor":{"type":["null","string","number","object"]},"adset_bid_strategies":{"type":"array","items":{"type":["string","null"]}},"adset_bid_amount_minor_min":{"type":["null","string","number","object"]},"adset_bid_amount_minor_max":{"type":["null","string","number","object"]},"fee_pct":{"type":["number","null"]},"spend_with_fees":{"type":["number","null"]},"profit_after_fees":{"type":["number","null"]},"revenue_source":{"type":["string","null"]},"revenue_synced_at":{"type":["string","null"]}}}}}},"example":{"date_range":{"start_date":"2026-03-29","end_date":"2026-04-05"},"count":12,"campaigns":[{"fb_campaign_id":"120212345678","name":"TOF - Broad Interests - US","objective":"OUTCOME_SALES","status":"ACTIVE","daily_budget_minor":50000,"lifetime_budget_minor":null,"spend_cap_minor":null,"total_ad_sets":3,"active_ad_sets":2,"fb_impressions":48210,"fb_clicks":1893,"fb_spend":1247.55,"fb_ctr":3.9261,"fb_cpc":0.659,"our_conversions":31,"our_revenue":4185,"true_revenue":4185,"true_roas":3.3546,"true_cpa":40.24,"bid_strategy":"LOWEST_COST_WITHOUT_CAP","bid_amount_minor":null,"adset_bid_strategies":["LOWEST_COST_WITHOUT_CAP"],"adset_bid_amount_minor_min":null,"adset_bid_amount_minor_max":null,"fee_pct":2,"spend_with_fees":1272.5,"profit_after_fees":2912.5,"revenue_source":"tracker","revenue_synced_at":"2026-04-05T09:41:07.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/campaigns/{campaign_id}":{"get":{"operationId":"getCampaign","summary":"Get a campaign","description":"One campaign with its ad sets and ads (creative + per-ad metrics).\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"campaign_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Campaign.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"object","properties":{"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]}}},"performance":{"type":"object","properties":{"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}},"ad_sets":{"type":"object","properties":{"count":{"type":["number","null"]},"items":{"type":"array","items":{"type":"object","properties":{"fb_ad_set_id":{"type":["string","null"]},"name":{"type":["string","null"]},"targeting":{"type":"object","properties":{"age_min":{"type":["number","null"]},"age_max":{"type":["number","null"]},"genders":{"type":"array","items":{"type":["number","null"]}}}},"ads":{"type":"array","items":{"type":"object","properties":{"fb_ad_id":{"type":["string","null"]},"name":{"type":["string","null"]},"creative":{"type":"object","properties":{"headline":{"type":["string","null"]},"body_text":{"type":["string","null"]},"image_url":{"type":["string","null"]},"link_url":{"type":["string","null"]}}},"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}}}}}}}}}},"example":{"campaign":{"fb_campaign_id":"120212345678","name":"...","status":"ACTIVE"},"performance":{"fb_spend":1247.55,"our_conversions":31,"our_revenue":4185,"true_roas":3.3546},"ad_sets":{"count":3,"items":[{"fb_ad_set_id":"120298765432","name":"25-44 Broad","targeting":{"age_min":25,"age_max":44,"genders":[0]},"ads":[{"fb_ad_id":"120211112222","name":"V1 - Headline A + Image 2","creative":{"headline":"Stop Wasting Ad Spend","body_text":"See your true ROAS in real-time...","image_url":"https://...","link_url":"https://..."},"fb_spend":312.1,"our_conversions":8,"true_roas":4.12}]}]}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateCampaign","summary":"Edit a campaign","description":"Change any of `name`, `status`, `daily_budget` (CBO campaigns) in one call. Each field needs its own scope: name → write:create, status → write:status, daily_budget → write:budgets. Fields are applied independently and reported per field.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create","write:status","write:budgets"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"name":"campaign_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":400},"status":{"type":"string","enum":["ACTIVE","PAUSED"]},"daily_budget":{"type":"number","exclusiveMinimum":0,"maximum":1000000},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Every requested change applied (or the top-level `status` is `partial` / `failed` with per-field detail).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"status":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}},"name":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}}}},"verified":{"type":"object","properties":{"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"name":{"type":["string","null"]}}}}},"example":{"status":"completed","id":"120210000000000001","changes":{"status":{"status":"completed","value":"PAUSED"},"name":{"status":"completed","value":"TOF — Broad — US"}},"verified":{"status":"PAUSED","effective_status":"PAUSED","name":"TOF — Broad — US"}}}}},"202":{"description":"At least one change was queued for approval; see `changes`.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"daily_budget":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]}}}}}}},"example":{"status":"pending_approval","id":"120210000000000001","changes":{"daily_budget":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11"}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/adsets":{"get":{"operationId":"listAdSets","summary":"List ad sets with performance","description":"Ad sets with targeting, budget, bid strategy, and metrics.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"status","in":"query","required":false,"description":"Filter by status (ACTIVE, PAUSED, …). ACTIVE means currently serving.","schema":{"type":"string","maxLength":40}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Ad sets.","content":{"application/json":{"schema":{"type":"object","properties":{"date_range":{"type":"object","properties":{"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]}}},"count":{"type":["number","null"]},"ad_sets":{"type":"array","items":{"type":"object","properties":{"fb_ad_set_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"daily_budget_minor":{"type":["number","null"]},"lifetime_budget_minor":{"type":["null","string","number","object"]},"bid_strategy":{"type":["string","null"]},"optimization_goal":{"type":["string","null"]},"targeting":{"type":"object","properties":{"age_min":{"type":["number","null"]},"age_max":{"type":["number","null"]}}},"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}}}}},"example":{"date_range":{"start_date":"2026-03-29","end_date":"2026-04-05"},"count":8,"ad_sets":[{"fb_ad_set_id":"120298765432","fb_campaign_id":"120212345678","name":"25-44 Broad","status":"ACTIVE","effective_status":"ACTIVE","daily_budget_minor":15000,"lifetime_budget_minor":null,"bid_strategy":"LOWEST_COST_WITHOUT_CAP","optimization_goal":"OFFSITE_CONVERSIONS","targeting":{"age_min":25,"age_max":44},"fb_spend":742.3,"our_conversions":18,"true_roas":3.81}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/adsets/{adset_id}":{"get":{"operationId":"getAdSet","summary":"Get an ad set","description":"One ad set with all of its ads, creative, and per-ad metrics.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"adset_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Ad set.","content":{"application/json":{"schema":{"type":"object","properties":{"date_range":{"type":"object","properties":{"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]}}},"ad_set":{"type":"object","properties":{"fb_ad_set_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"daily_budget_minor":{"type":["number","null"]},"lifetime_budget_minor":{"type":["null","string","number","object"]},"bid_strategy":{"type":["string","null"]},"optimization_goal":{"type":["string","null"]},"targeting":{"type":"object","properties":{"age_min":{"type":["number","null"]},"age_max":{"type":["number","null"]}}},"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}},"ads":{"type":"array","items":{"type":"object","properties":{"fb_ad_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"creative":{"type":"object","properties":{"headline":{"type":["string","null"]},"body_text":{"type":["string","null"]},"call_to_action":{"type":["string","null"]},"image_url":{"type":["string","null"]},"link_url":{"type":["string","null"]}}},"fb_impressions":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"fb_ctr":{"type":["number","null"]},"fb_cpc":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]},"true_cpa":{"type":["number","null"]}}}}}},"example":{"date_range":{"start_date":"2026-03-29","end_date":"2026-04-05"},"ad_set":{"fb_ad_set_id":"120298765432","fb_campaign_id":"120212345678","name":"25-44 Broad","status":"ACTIVE","effective_status":"ACTIVE","daily_budget_minor":15000,"lifetime_budget_minor":null,"bid_strategy":"LOWEST_COST_WITHOUT_CAP","optimization_goal":"OFFSITE_CONVERSIONS","targeting":{"age_min":25,"age_max":44},"fb_spend":742.3,"our_conversions":18,"true_roas":3.81},"ads":[{"fb_ad_id":"120211112222","fb_campaign_id":"120212345678","name":"V1 - Headline A + Image 2","status":"ACTIVE","effective_status":"ACTIVE","creative":{"headline":"Stop Wasting Ad Spend","body_text":"See your true ROAS...","call_to_action":"LEARN_MORE","image_url":"https://...","link_url":"https://youroffer.com/lp1"},"fb_impressions":12400,"fb_spend":312.1,"fb_ctr":4.12,"fb_cpc":0.61,"our_conversions":8,"our_revenue":1286,"true_roas":4.1206,"true_cpa":39.01}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateAdSet","summary":"Edit an ad set","description":"Change any of `name`, `status`, `daily_budget` (ABO), `bid_amount`, `start_time`, `end_time`. Scopes per field: name/schedule → write:create, status → write:status, daily_budget → write:budgets, bid_amount → write:bids. Pass `end_time: null` to remove an end date.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create","write:status","write:budgets","write:bids"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"name":"adset_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":400},"status":{"type":"string","enum":["ACTIVE","PAUSED"]},"daily_budget":{"type":"number","exclusiveMinimum":0,"maximum":1000000},"bid_amount":{"type":"number","exclusiveMinimum":0,"maximum":100000},"start_time":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"end_time":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Every requested change applied (or the top-level `status` is `partial` / `failed` with per-field detail).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"status":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}},"name":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}}}},"verified":{"type":"object","properties":{"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"name":{"type":["string","null"]}}}}},"example":{"status":"completed","id":"120210000000000001","changes":{"status":{"status":"completed","value":"PAUSED"},"name":{"status":"completed","value":"TOF — Broad — US"}},"verified":{"status":"PAUSED","effective_status":"PAUSED","name":"TOF — Broad — US"}}}}},"202":{"description":"At least one change was queued for approval; see `changes`.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"daily_budget":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]}}}}}}},"example":{"status":"pending_approval","id":"120210000000000001","changes":{"daily_budget":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11"}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/ads":{"get":{"operationId":"listAds","summary":"List ads with creative + performance","description":"Ads with full creative (headline, body, media, CTA, landing URL) and metrics.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"adset_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"status","in":"query","required":false,"description":"Filter by status (ACTIVE, PAUSED, …). ACTIVE means currently serving.","schema":{"type":"string","maxLength":40}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Ads.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":["number","null"]},"ads":{"type":"array","items":{"type":"object","properties":{"fb_ad_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"creative":{"type":"object","properties":{"headline":{"type":["string","null"]},"body_text":{"type":["string","null"]},"call_to_action":{"type":["string","null"]},"image_url":{"type":["string","null"]},"link_url":{"type":["string","null"]}}},"fb_impressions":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"fb_ctr":{"type":["number","null"]},"fb_cpc":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]},"true_cpa":{"type":["number","null"]}}}}}},"example":{"count":24,"ads":[{"fb_ad_id":"120211112222","fb_campaign_id":"120212345678","name":"V1 - Headline A + Image 2","status":"ACTIVE","effective_status":"ACTIVE","creative":{"headline":"Stop Wasting Ad Spend","body_text":"See your true ROAS...","call_to_action":"LEARN_MORE","image_url":"https://...","link_url":"https://youroffer.com/lp1"},"fb_impressions":12400,"fb_spend":312.1,"fb_ctr":4.12,"fb_cpc":0.61,"our_conversions":8,"our_revenue":1286,"true_roas":4.1206,"true_cpa":39.01}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/ads/{ad_id}":{"get":{"operationId":"getAd","summary":"Get an ad","description":"One ad with creative, launch info, and a day-by-day breakdown.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"ad_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Ad.","content":{"application/json":{"schema":{"type":"object","properties":{"ad":{"type":"object","properties":{"fb_ad_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]}}},"creative":{"type":"object","properties":{"headline":{"type":["string","null"]},"body_text":{"type":["string","null"]},"image_url":{"type":["string","null"]},"link_url":{"type":["string","null"]}}},"batch":{"type":"object","properties":{"headlines":{"type":"array","items":{"type":["string","null"]}},"this_ad_headline":{"type":["string","null"]}}},"totals":{"type":"object","properties":{"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":["string","null"]},"fb_impressions":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]}}}}}},"example":{"ad":{"fb_ad_id":"120211112222","name":"V1 - Headline A","status":"ACTIVE"},"creative":{"headline":"Stop Wasting Ad Spend","body_text":"See your true ROAS...","image_url":"https://...","link_url":"https://..."},"batch":{"headlines":["Stop Wasting Ad Spend","Know Your True ROAS"],"this_ad_headline":"Stop Wasting Ad Spend"},"totals":{"fb_spend":312.1,"our_conversions":8,"true_roas":4.12},"daily":[{"date":"2026-04-04","fb_impressions":3100,"fb_spend":78.2,"our_conversions":2,"our_revenue":340,"true_roas":4.3478}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateAd","summary":"Edit an ad","description":"Change an ad's `name` (write:create) and/or `status` (write:status). Ad creative is immutable at Meta. To change copy or media, duplicate the campaign with new creative.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create","write:status"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"name":"ad_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":400},"status":{"type":"string","enum":["ACTIVE","PAUSED"]},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Every requested change applied (or the top-level `status` is `partial` / `failed` with per-field detail).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"status":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}},"name":{"type":"object","properties":{"status":{"type":["string","null"]},"value":{"type":["string","null"]}}}}},"verified":{"type":"object","properties":{"status":{"type":["string","null"]},"effective_status":{"type":["string","null"]},"name":{"type":["string","null"]}}}}},"example":{"status":"completed","id":"120210000000000001","changes":{"status":{"status":"completed","value":"PAUSED"},"name":{"status":"completed","value":"TOF — Broad — US"}},"verified":{"status":"PAUSED","effective_status":"PAUSED","name":"TOF — Broad — US"}}}}},"202":{"description":"At least one change was queued for approval; see `changes`.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"changes":{"type":"object","properties":{"daily_budget":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]}}}}}}},"example":{"status":"pending_approval","id":"120210000000000001","changes":{"daily_budget":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11"}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/conversions":{"get":{"operationId":"listFacebookConversions","summary":"List ad-attributed conversions","description":"Tracked conversions attributed to a Facebook ad, with revenue and the campaign / ad set / ad that drove them. For every conversion (including unattributed) use GET /v1/conversions.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:conversions"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"ad_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Conversions.","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"total_conversions":{"type":["number","null"]},"total_revenue":{"type":["number","null"]},"inferred_conversions":{"type":["number","null"]},"inferred_revenue":{"type":["number","null"]},"deterministic_conversions":{"type":["number","null"]},"deterministic_revenue":{"type":["number","null"]}}},"count":{"type":["number","null"]},"conversions":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"timestamp":{"type":["string","null"]},"revenue":{"type":["number","null"]},"transaction_id":{"type":["string","null"]},"page_id":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"product_id":{"type":["null","string","number","object"]},"fb_ad_id":{"type":["string","null"]},"fb_ad_set_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"attribution_method":{"type":["string","null"]}}}}}},"example":{"summary":{"total_conversions":31,"total_revenue":4185,"inferred_conversions":3,"inferred_revenue":405,"deterministic_conversions":28,"deterministic_revenue":3780},"count":31,"conversions":[{"id":"conv_abc123","timestamp":"2026-04-04T14:22:08.000-04:00","revenue":127.5,"transaction_id":"EF-987654","page_id":"page_123","variant_id":"variant_a","product_id":null,"fb_ad_id":"120211112222","fb_ad_set_id":"120298765432","fb_campaign_id":"120212345678","attribution_method":"sub_direct"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/daily":{"get":{"operationId":"getDailyPerformance","summary":"Daily performance totals","description":"Day-by-day spend, Facebook metrics, and tracked revenue for P&L and time series.\n\nMetrics: `fb_*` fields are what Meta reports; `our_*` are conversions your tracking recorded; `true_*` (true_roas, true_cpa, true_revenue) use your workspace conversion source. Money is in the ad account currency; `*_usd` twins are USD-normalized. `*_minor` fields are integer minor units (cents).\n\nRevenue provenance: `revenue_source` is `tracker` (your tracking/postbacks, e.g. Everflow, matched to the campaign by sub1 = campaign id) or `fb_pixel` (Meta-reported purchases); `revenue_synced_at` is when that source last delivered data. Fees: `spend_with_fees` = spend × (1 + account `fee_pct`/100); `profit_after_fees` = true_revenue − spend_with_fees. Bids: `bid_strategy` / `bid_amount_minor` are the campaign’s (CBO) or its ad sets’ when they all agree; `adset_bid_strategies` lists every distinct ad set strategy and `adset_bid_amount_minor_min`/`_max` the ad set bid range.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Daily rows + totals.","content":{"application/json":{"schema":{"type":"object","properties":{"totals":{"type":"object","properties":{"fb_impressions":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]},"profit_loss":{"type":["number","null"]}}},"days":{"type":["number","null"]},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":["string","null"]},"fb_impressions":{"type":["number","null"]},"fb_clicks":{"type":["number","null"]},"fb_spend":{"type":["number","null"]},"fb_ctr":{"type":["number","null"]},"fb_cpc":{"type":["number","null"]},"active_ads":{"type":["number","null"]},"our_conversions":{"type":["number","null"]},"our_revenue":{"type":["number","null"]},"true_roas":{"type":["number","null"]},"profit_loss":{"type":["number","null"]}}}}}},"example":{"totals":{"fb_impressions":142800,"fb_spend":3842.1,"our_conversions":89,"our_revenue":12450,"true_roas":3.2402,"profit_loss":8607.9},"days":7,"daily":[{"date":"2026-04-04","fb_impressions":21200,"fb_clicks":832,"fb_spend":548.9,"fb_ctr":3.9245,"fb_cpc":0.6597,"active_ads":24,"our_conversions":14,"our_revenue":1890,"true_roas":3.4433,"profit_loss":1341.1}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/placements":{"get":{"operationId":"getPlacementBreakdown","summary":"Placement breakdown","description":"Spend, impressions, clicks, and reach by publisher × position (e.g. facebook_feed, instagram_reels) for the date range, across the workspace or one account / campaign.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Placements, largest spend first.","content":{"application/json":{"schema":{"type":"object","properties":{"date_range":{"type":"object","properties":{"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]}}},"placements":{"type":"array","items":{"type":"object","properties":{"placement":{"type":["string","null"]},"publisher_platform":{"type":["string","null"]},"platform_position":{"type":["string","null"]},"spend":{"type":["number","null"]},"impressions":{"type":["number","null"]},"clicks":{"type":["number","null"]},"reach":{"type":["number","null"]},"ctr":{"type":["number","null"]},"cpm":{"type":["number","null"]},"share_of_spend":{"type":["number","null"]}}}},"currencies":{"type":"array","items":{"type":["string","null"]}}}},"example":{"date_range":{"start_date":"2026-10-12","end_date":"2026-10-19"},"placements":[{"placement":"facebook_feed","publisher_platform":"facebook","platform_position":"feed","spend":812.4,"impressions":40211,"clicks":1602,"reach":28844,"ctr":3.98,"cpm":20.2,"share_of_spend":0.61}],"currencies":["USD"]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/batches":{"get":{"operationId":"listCompletedBatches","summary":"List completed launches (creative detail)","description":"Completed launches with every creative variation and targeting used. For all launches including failed ones (with reasons), use GET /v1/facebook/launches.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Launches.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":["number","null"]},"batches":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"ads_created":{"type":["number","null"]},"headlines":{"type":"array","items":{"type":["string","null"]}},"body_texts":{"type":"array","items":{"type":["string","null"]}},"image_ids":{"type":"array","items":{"type":["string","null"]}},"bid_strategy":{"type":["string","null"]},"daily_budget_minor":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"count":5,"batches":[{"id":"batch_xyz","fb_campaign_id":"120212345678","ads_created":12,"headlines":["Stop Wasting Ad Spend","Know Your True ROAS"],"body_texts":["See real-time data...","Track every dollar..."],"image_ids":["img_1","img_2","img_3"],"bid_strategy":"LOWEST_COST_WITHOUT_CAP","daily_budget_minor":5000,"created_at":"2026-04-01T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/automation":{"get":{"operationId":"getAutomationOverview","summary":"Automation rules + recent actions","description":"Every automation rule with its configuration, plus the most recent actions taken. For full history with filters use GET /v1/automation/history.","tags":["Facebook reporting"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"Rules + actions.","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"object","properties":{"count":{"type":["number","null"]},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"rule_type":{"type":["string","null"]},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"action_type":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"execution_count":{"type":["number","null"]}}}}}},"recent_actions":{"type":"object","properties":{"count":{"type":["number","null"]},"items":{"type":"array","items":{"type":"object","properties":{"rule_id":{"type":["string","null"]},"fb_ad_id":{"type":["string","null"]},"fb_adset_id":{"type":["null","string","number","object"]},"fb_campaign_id":{"type":["string","null"]},"action_taken":{"type":["string","null"]},"raw_action_taken":{"type":["string","null"]},"is_alert_only":{"type":["boolean","null"]},"reason":{"type":["string","null"]},"money_saved":{"type":["number","null"]},"executed_at":{"type":["string","null"]}}}}}}}},"example":{"rules":{"count":4,"items":[{"name":"Kill low ROAS ads","rule_type":"ad","conditions":[{"metric":"roas","operator":"less_than","value":1.5}],"action_type":"pause_ad","is_active":true,"execution_count":47}]},"recent_actions":{"count":12,"items":[{"rule_id":"rule_abc","fb_ad_id":"120211112222","fb_adset_id":null,"fb_campaign_id":"120212345678","action_taken":"pause_ad","raw_action_taken":"pause_ad","is_alert_only":false,"reason":"ROAS 0.82 < 1.5 threshold","money_saved":42.1,"executed_at":"2026-04-04T15:30:00.000-04:00"}]}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/launches":{"get":{"operationId":"listLaunches","summary":"List launches (including failed)","description":"Every launch attempt (from the app, the API, MCP, clone rules, and automation), newest first, with status `creating`, `completed`, or `failed` and the plain-English failure reason.","tags":["Facebook launch"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["creating","completed","failed"]}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Launches.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"launches":{"type":"array","items":{"type":"object","properties":{"launch_id":{"type":["string","null"]},"status":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"campaign_id":{"type":["null","string","number","object"]},"campaign_name":{"type":["string","null"]},"launched_via":{"type":["string","null"]},"source_label":{"type":["string","null"]},"ads_created":{"type":["number","null"]},"failure_reason":{"type":["string","null"]},"created_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"launches":[{"launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d","status":"failed","fb_account_id":"act_123456789","campaign_id":null,"campaign_name":"TOF — Broad — US","launched_via":"api","source_label":"API","ads_created":0,"failure_reason":"Page can't run ads. Connect the Page to this ad account's business, then retry.","created_at":"2026-10-19T09:00:00.000-04:00","failed_at":"2026-10-19T09:00:12.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/launches/{launch_id}":{"get":{"operationId":"getLaunch","summary":"Get a launch","description":"One launch with its full outcome: created campaign / ad set / ad ids, per-ad failures, and Meta’s error detail (code, subcode, raw message) when it failed.","tags":["Facebook launch"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"launch_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Launch.","content":{"application/json":{"schema":{"type":"object","properties":{"launch_id":{"type":["string","null"]},"status":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"campaign_id":{"type":["null","string","number","object"]},"campaign_name":{"type":["string","null"]},"launched_via":{"type":["string","null"]},"source_label":{"type":["string","null"]},"ads_created":{"type":["number","null"]},"failure_reason":{"type":["string","null"]},"created_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]},"adset_id":{"type":["null","string","number","object"]},"ad_ids":{"type":"array","items":{}},"failure_detail":{"type":"object","properties":{"kind":{"type":["string","null"]},"code":{"type":["number","null"]},"subcode":{"type":["number","null"]},"raw_message":{"type":["string","null"]},"failed_ads":{"type":"array","items":{}}}}}},"example":{"launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d","status":"failed","fb_account_id":"act_123456789","campaign_id":null,"campaign_name":"TOF — Broad — US","launched_via":"api","source_label":"API","ads_created":0,"failure_reason":"Page can't run ads. Connect the Page to this ad account's business, then retry.","created_at":"2026-10-19T09:00:00.000-04:00","failed_at":"2026-10-19T09:00:12.000-04:00","adset_id":null,"ad_ids":[],"failure_detail":{"kind":"permission","code":200,"subcode":1487194,"raw_message":"…","failed_ads":[]}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/hourly":{"get":{"operationId":"getHourlyPerformance","summary":"Hourly performance","description":"Spend, clicks, conversions, revenue, ROAS, and profit by hour of day (0–23, workspace timezone), for dayparting decisions. `date` picks one exact day; otherwise `date_range` (today, yesterday, last_3d, last_7d, this_week, last_week) or start_date + end_date.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"date","in":"query","required":false,"description":"One exact day (YYYY-MM-DD).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"campaign_search","in":"query","required":false,"description":"Campaign name contains.","schema":{"type":"string","maxLength":200}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Hours + summary.","content":{"application/json":{"schema":{"type":"object","properties":{"data_source":{"type":["string","null"]},"currencies":{"type":"array","items":{"type":["string","null"]}},"hours":{"type":"array","items":{"type":"object","properties":{"hour":{"type":["number","null"]},"hour_label":{"type":["string","null"]},"spend":{"type":["number","null"]},"clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue":{"type":["number","null"]},"roas":{"type":["number","null"]},"cvr":{"type":["number","null"]},"profit":{"type":["number","null"]}}}},"summary":{"type":"object","properties":{"total_spend":{"type":["number","null"]},"total_revenue":{"type":["number","null"]},"total_profit":{"type":["number","null"]},"total_conversions":{"type":["number","null"]},"total_clicks":{"type":["number","null"]},"overall_roas":{"type":["number","null"]},"peak_hour":{"type":["number","null"]},"worst_hour":{"type":["number","null"]}}}}},"example":{"data_source":"facebook_ad_insights_hourly","currencies":["USD"],"hours":[{"hour":9,"hour_label":"9 AM","spend":41.2,"clicks":133,"conversions":4,"revenue":196,"roas":4.76,"cvr":3.01,"profit":154.8}],"summary":{"total_spend":812.4,"total_revenue":2944,"total_profit":2131.6,"total_conversions":61,"total_clicks":2311,"overall_roas":3.62,"peak_hour":21,"worst_hour":4}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/profitability":{"get":{"operationId":"getProfitability","summary":"Profitability","description":"Spend vs tracked revenue → profit and ROAS, grouped by campaign, day, or hour. `start_hour` / `end_hour` restrict to a time window (workspace timezone).","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"group_by","in":"query","required":false,"schema":{"default":"campaign","type":"string","enum":["campaign","day","hour"]}},{"name":"campaign_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"start_hour","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":23}},{"name":"end_hour","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":23}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"Breakdown rows (keyed by campaign, day, or hour per group_by) + summary.","content":{"application/json":{"schema":{"type":"object","properties":{"data_source":{"type":["string","null"]},"currencies":{"type":"array","items":{"type":["string","null"]}},"breakdown":{"type":"array","items":{"type":"object","properties":{"campaign_id":{"type":["string","null"]},"campaign_name":{"type":["string","null"]},"spend":{"type":["number","null"]},"revenue":{"type":["number","null"]},"profit":{"type":["number","null"]},"roas":{"type":["number","null"]},"conversions":{"type":["number","null"]},"clicks":{"type":["number","null"]}}}},"summary":{"type":"object","properties":{"total_spend":{"type":["number","null"]},"total_revenue":{"type":["number","null"]},"total_profit":{"type":["number","null"]},"roas":{"type":["number","null"]},"best_period":{"type":["null","string","number","object"]},"worst_period":{"type":["null","string","number","object"]}}},"meta":{"type":"object","properties":{"date_range":{"type":["string","null"]},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]},"group_by":{"type":["string","null"]}}}}},"example":{"data_source":"independent_tracking","currencies":["USD"],"breakdown":[{"campaign_id":"120210000000000001","campaign_name":"TOF — Broad — US","spend":812.4,"revenue":2944,"profit":2131.6,"roas":3.62,"conversions":61,"clicks":2311}],"summary":{"total_spend":812.4,"total_revenue":2944,"total_profit":2131.6,"roas":3.62,"best_period":null,"worst_period":null},"meta":{"date_range":"last_7d","start_date":"2026-10-12","end_date":"2026-10-19","group_by":"campaign"}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/funnel":{"get":{"operationId":"getFunnel","summary":"Funnel per campaign","description":"Per campaign: ad clicks → landing-page views → offer clicks → sales, with the step rates and spend, to see whether a campaign leaks at the ad, the lander, or the offer. Landing views and clicks are bot-filtered.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"status","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["active","all"]}},{"name":"date_range","in":"query","required":false,"schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_14d","last_30d","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–500, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Funnel rows.","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"campaign_id":{"type":["string","null"]},"campaign_name":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"currency":{"type":["string","null"]},"spend":{"type":["number","null"]},"link_clicks":{"type":["number","null"]},"landing_views":{"type":["number","null"]},"landing_clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue":{"type":["number","null"]},"view_rate":{"type":["number","null"]},"click_through_rate":{"type":["number","null"]},"conversion_rate":{"type":["number","null"]}}}}}},"example":{"campaigns":[{"campaign_id":"120210000000000001","campaign_name":"TOF — Broad — US","fb_account_id":"act_123456789","currency":"USD","spend":812.4,"link_clicks":2311,"landing_views":1980,"landing_clicks":655,"conversions":61,"revenue":2944,"view_rate":0.857,"click_through_rate":0.331,"conversion_rate":0.093}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/account-health":{"get":{"operationId":"getAccountHealth","summary":"Ad account health","description":"Per ad account: Meta account status + disable reason, funding source, sync health, automation health, rate-limit usage, and connected pixels / pages.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"include_assets","in":"query","required":false,"schema":{"default":"true","type":"string","enum":["true","false"]}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Accounts + summary.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"account_status":{"type":["string","null"]},"funding_source_present":{"type":["boolean","null"]},"currency":{"type":["string","null"]},"sync_tier":{"type":["string","null"]}}}},"summary":{"type":"object","properties":{"total":{"type":["number","null"]},"active":{"type":["number","null"]},"disabled":{"type":["number","null"]}}}}},"example":{"accounts":[{"account_id":"act_123456789","name":"Main","account_status":"ACTIVE","funding_source_present":true,"currency":"USD","sync_tier":"hot"}],"summary":{"total":1,"active":1,"disabled":0}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/data-freshness":{"get":{"operationId":"getDataFreshness","summary":"Data freshness","description":"How fresh each account’s data is: last insights / structure sync, minutes behind, sync failures, and 24h spend probe. Check this before acting on \"today\" numbers.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:analytics"],"x-minimum-role":"viewer","parameters":[{"name":"account_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Freshness per account.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"account_id":{"type":["string","null"]},"sync_tier":{"type":["string","null"]},"age_minutes":{"type":"object","properties":{"insights":{"type":["number","null"]},"campaigns":{"type":["number","null"]}}},"sync_failures":{"type":"object","properties":{"consecutive":{"type":["number","null"]}}}}}}}},"example":{"accounts":[{"account_id":"act_123456789","sync_tier":"hot","age_minutes":{"insights":2,"campaigns":21},"sync_failures":{"consecutive":0}}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/budget-alerts":{"get":{"operationId":"listBudgetAlerts","summary":"Budget recommendations","description":"The budget optimizer’s alerts: scale opportunities, reallocations, degradations, and new winners, with the suggested budget change and opportunity cost.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"severity","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["info","warning","critical","all"]}},{"name":"alert_type","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["scale_opportunity","reallocation","degradation","new_winner","all"]}},{"name":"include_dismissed","in":"query","required":false,"schema":{"default":"false","type":"string","enum":["true","false"]}},{"name":"campaign_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Alerts.","content":{"application/json":{"schema":{"type":"object","properties":{"alerts":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"alert_type":{"type":["string","null"]},"severity":{"type":["string","null"]},"title":{"type":["string","null"]},"recommendation":{"type":["string","null"]},"metrics":{"type":"object","properties":{"current_roi":{"type":["number","null"]},"suggested_new_budget":{"type":["number","null"]},"currency":{"type":["string","null"]}}}}}},"summary":{"type":"object","properties":{"total":{"type":["number","null"]},"critical":{"type":["number","null"]},"warning":{"type":["number","null"]}}}}},"example":{"alerts":[{"id":"9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f","alert_type":"scale_opportunity","severity":"warning","title":"TOF — Broad — US is under-funded","recommendation":"Raise budget 30%","metrics":{"current_roi":2.6,"suggested_new_budget":130,"currency":"USD"}}],"summary":{"total":1,"critical":0,"warning":1}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/boosts":{"get":{"operationId":"listBoosts","summary":"Boosted-post campaigns","description":"Boosted-post campaigns with spend and Meta-reported results (boosts inherit post URLs, so they use Meta attribution rather than tracker sub-ids).","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["ACTIVE","PAUSED","DELETED","ARCHIVED","all"]}},{"name":"sort_by","in":"query","required":false,"schema":{"default":"spend","type":"string","enum":["spend","revenue","roas","clicks","impressions"]}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Boost campaigns + totals.","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"status":{"type":["string","null"]},"spend":{"type":["number","null"]},"revenue":{"type":["number","null"]},"roas":{"type":["number","null"]},"currency":{"type":["string","null"]}}}},"summary":{"type":"object","properties":{"total_spend":{"type":["number","null"]},"total_revenue":{"type":["number","null"]},"avg_roas":{"type":["number","null"]}}}}},"example":{"campaigns":[{"name":"Boost: Fall launch post","status":"ACTIVE","spend":120.5,"revenue":410,"roas":3.4,"currency":"USD"}],"summary":{"total_spend":120.5,"total_revenue":410,"avg_roas":3.4}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/creatives":{"get":{"operationId":"listCreativePerformance","summary":"Creative performance","description":"Which creative wins: performance grouped by creative, headline, image, body text, or ad: spend, CTR, conversions, revenue, ROAS.","tags":["Facebook analytics"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"group_by","in":"query","required":false,"schema":{"default":"creative","type":"string","enum":["creative","headline","image","body_text","ad"]}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"campaign_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Grouped creative performance + best / worst performer.","content":{"application/json":{"schema":{"type":"object","properties":{"creatives":{"type":"array","items":{"type":"object","properties":{"group":{"type":["string","null"]},"spend":{"type":["number","null"]},"clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue":{"type":["number","null"]},"roas":{"type":["number","null"]},"ad_count":{"type":["number","null"]}}}},"summary":{"type":"object","properties":{"best_performer":{"type":["string","null"]},"worst_performer":{"type":["null","string","number","object"]}}},"meta":{"type":"object","properties":{"date_range":{"type":["string","null"]},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]},"group_by":{"type":["string","null"]}}}}},"example":{"creatives":[{"group":"Doctors hate this one trick","spend":210.4,"clicks":811,"conversions":22,"revenue":1034,"roas":4.91,"ad_count":3}],"summary":{"best_performer":"Doctors hate this one trick","worst_performer":null},"meta":{"date_range":"last_7d","start_date":"2026-10-12","end_date":"2026-10-19","group_by":"headline"}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/creatives/search":{"get":{"operationId":"searchCreatives","summary":"Search creatives","description":"Find ads by text in their headline, body, or name.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Matching ads.","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":["string","null"]},"total":{"type":["number","null"]},"shown":{"type":["number","null"]},"truncated":{"type":["boolean","null"]},"creatives":{"type":"array","items":{"type":"object","properties":{"fb_creative_id":{"type":["string","null"]},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]}}}}}},"example":{"query":"one trick","total":1,"shown":1,"truncated":false,"creatives":[{"fb_creative_id":"120210000000000004","title":"Doctors hate this one trick","body":"…","fb_account_id":"act_123456789"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/ads/{ad_id}/preview":{"get":{"operationId":"getAdPreview","summary":"Ad preview","description":"Meta’s rendered preview of an ad (an iframe snippet) for a placement format, e.g. MOBILE_FEED_STANDARD (default), INSTAGRAM_STANDARD, INSTAGRAM_REELS.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"ad_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"ad_format","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":60}}],"responses":{"200":{"description":"Preview.","content":{"application/json":{"schema":{"type":"object","properties":{"ad_id":{"type":["string","null"]},"ad_format":{"type":["string","null"]},"preview_iframe":{"type":["string","null"]}}},"example":{"ad_id":"120210000000000003","ad_format":"MOBILE_FEED_STANDARD","preview_iframe":"<iframe src=\"https://www.facebook.com/ads/api/preview_iframe.php?…\"></iframe>"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/audiences":{"get":{"operationId":"listAudiences","summary":"List audiences","description":"Custom, lookalike, and saved audiences. Use the ids in `included_audience_ids` / `excluded_audience_ids` when launching.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"type","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["custom","saved","all"]}},{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"include_inactive","in":"query","required":false,"schema":{"default":"false","type":"string","enum":["true","false"]}},{"name":"limit","in":"query","required":false,"description":"Rows (1–200, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Audiences.","content":{"application/json":{"schema":{"type":"object","properties":{"audiences":{"type":"array","items":{"type":"object","properties":{"fb_audience_id":{"type":["string","null"]},"name":{"type":["string","null"]},"type":{"type":["string","null"]},"subtype":{"type":["string","null"]},"approximate_count_lower_bound":{"type":["number","null"]},"fb_account_id":{"type":["string","null"]}}}}}},"example":{"audiences":[{"fb_audience_id":"23851234567890123","name":"Purchasers 180d","type":"custom","subtype":"WEBSITE","approximate_count_lower_bound":12000,"fb_account_id":"act_123456789"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/pixels":{"get":{"operationId":"listPixels","summary":"List pixels","description":"Meta pixels per ad account. Pass the id as `fb_pixel_id` when launching.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"include_inactive","in":"query","required":false,"schema":{"default":"false","type":"string","enum":["true","false"]}},{"name":"limit","in":"query","required":false,"description":"Rows (1–200, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Pixels.","content":{"application/json":{"schema":{"type":"object","properties":{"pixels":{"type":"array","items":{"type":"object","properties":{"fb_pixel_id":{"type":["string","null"]},"name":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"is_active":{"type":["boolean","null"]}}}}}},"example":{"pixels":[{"fb_pixel_id":"1234567890123456","name":"Main pixel","fb_account_id":"act_123456789","is_active":true}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/pages":{"get":{"operationId":"listPages","summary":"List Facebook Pages","description":"Facebook Pages ads can run under. Pass `account_id` to also get `launch_block_reason` for launching from that ad account (null = OK; `no_system_user_access` / `no_user_token_access` = Meta will refuse; fix the Page’s access in Business Settings). Pass the id as `fb_page_id` when launching.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Pages.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"pages":{"type":"array","items":{"type":"object","properties":{"fb_page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"fb_account_id":{"type":["null","string","number","object"]},"category":{"type":["string","null"]},"is_default":{"type":["boolean","null"]},"active_ad_count":{"type":["number","null"]},"ad_limit":{"type":["number","null"]},"launch_block_reason":{"type":["null","string","number","object"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"pages":[{"fb_page_id":"104455667788990","name":"Acme","fb_account_id":null,"category":"Brand","is_default":true,"active_ad_count":41,"ad_limit":250,"launch_block_reason":null}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/targeting/interests":{"get":{"operationId":"searchInterests","summary":"Search targeting interests","description":"Look up Meta interest ids by keyword (live from Meta) for `interest_ids` when launching.","tags":["Facebook assets"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"account_id","in":"query","required":true,"description":"Ad account whose access is used for the lookup.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 25).","schema":{"default":25,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Interests.","content":{"application/json":{"schema":{"type":"object","properties":{"interests":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]},"audience_size_lower_bound":{"type":["number","null"]},"audience_size_upper_bound":{"type":["number","null"]},"path":{"type":"array","items":{"type":["string","null"]}}}}}}},"example":{"interests":[{"id":"6003107902433","name":"Keto diet","audience_size_lower_bound":21000000,"audience_size_upper_bound":24700000,"path":["Interests","Fitness and wellness"]}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/status":{"post":{"operationId":"setEntityStatus","summary":"Pause or activate campaigns, ad sets, or ads","description":"Sets `status` to ACTIVE or PAUSED on up to 50 entities in one ad account. Each id is re-read from Meta after the write and returned under `verified`.\n\nSubject to workspace approval rules (202 + `pending_action_id`). Boosted-post campaigns are excluded.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:status"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["campaign","adset","ad"],"description":"Entity level the ids refer to: 'campaign', 'adset', or 'ad'."},"ids":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d{5,25}$","description":"Numeric Facebook id (campaign / ad set / ad)."},"description":"Up to 50 Facebook ids of the given type."},"status":{"type":"string","enum":["ACTIVE","PAUSED"],"description":"Target status."},"fb_account_id":{"description":"Ad account that owns the ids. Optional: inferred from the ids when omitted.","type":"string","pattern":"^act_\\d{1,25}$"},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["type","ids","status"]}}}},"responses":{"200":{"description":"Applied. Per-id results + Meta readback.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"total":{"type":["number","null"]},"succeeded":{"type":["number","null"]},"failed":{"type":["number","null"]},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"ok":{"type":["boolean","null"]}}}}}},"example":{"status":"completed","total":2,"succeeded":2,"failed":0,"results":[{"id":"120210000000000001","ok":true},{"id":"120210000000000002","ok":true}]}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/budgets":{"post":{"operationId":"updateBudgets","summary":"Set daily budgets","description":"Sets the daily budget on up to 50 campaigns (CBO) or ad sets (ABO) in one ad account. Amounts are in the ad account's currency, MAJOR units (dollars, not cents).\n\nRejected per id when the budget lives at the other level (`wrong_budget_type`). Member budget caps apply; increases can be queued by approval rules.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:budgets"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["campaign","adset"],"description":"'campaign' (CBO) or 'adset' (ABO)."},"updates":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^\\d{5,25}$","description":"Numeric Facebook id (campaign / ad set / ad)."},"daily_budget":{"type":"number","exclusiveMinimum":0,"maximum":1000000,"description":"New daily budget, MAJOR account currency."}},"required":["id","daily_budget"]}},"fb_account_id":{"description":"Ad account that owns the ids. Optional: inferred from the ids when omitted.","type":"string","pattern":"^act_\\d{1,25}$"},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["type","updates"]}}}},"responses":{"200":{"description":"Applied. Per-id results + Meta readback.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"total":{"type":["number","null"]},"succeeded":{"type":["number","null"]},"failed":{"type":["number","null"]},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"ok":{"type":["boolean","null"]}}}}}},"example":{"status":"completed","total":2,"succeeded":2,"failed":0,"results":[{"id":"120210000000000001","ok":true},{"id":"120210000000000002","ok":true}]}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/bids":{"post":{"operationId":"updateBids","summary":"Set bid / cost caps on ad sets","description":"Sets `bid_amount` on up to 50 ad sets in one ad account. Only ad sets whose bid strategy uses a cap (bid cap / cost cap) accept it; others return `wrong_strategy`. Amount is MAJOR account currency.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:bids"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"adset_ids":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d{5,25}$","description":"Numeric Facebook id (campaign / ad set / ad)."},"description":"Up to 50 ad set ids (all in one ad account)."},"bid_amount":{"type":"number","exclusiveMinimum":0,"maximum":100000,"description":"Bid amount, MAJOR account currency."},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["adset_ids","bid_amount"]}}}},"responses":{"200":{"description":"Applied. Per-id results + Meta readback.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"total":{"type":["number","null"]},"succeeded":{"type":["number","null"]},"failed":{"type":["number","null"]},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"ok":{"type":["boolean","null"]}}}}}},"example":{"status":"completed","total":2,"succeeded":2,"failed":0,"results":[{"id":"120210000000000001","ok":true},{"id":"120210000000000002","ok":true}]}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/delete":{"post":{"operationId":"deleteEntities","summary":"Delete or archive campaigns, ad sets, or ads","description":"Deletes (default) or archives up to 50 entities. Deleting a campaign removes its ad sets and ads. Requires `confirm: true`. Entities already gone at Meta count as success.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:delete"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["campaign","adset","ad"],"description":"Entity level the ids refer to: 'campaign', 'adset', or 'ad'."},"ids":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d{5,25}$","description":"Numeric Facebook id (campaign / ad set / ad)."},"description":"Up to 50 Facebook ids of the given type."},"mode":{"default":"delete","description":"'delete' removes permanently; 'archive' keeps it in Meta's archive.","type":"string","enum":["delete","archive"]},"fb_account_id":{"description":"Ad account that owns the ids. Optional: inferred from the ids when omitted.","type":"string","pattern":"^act_\\d{1,25}$"},"confirm":{"type":"boolean","const":true,"description":"Must be true. Guards against accidental destructive calls."},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["type","ids","confirm"]}}}},"responses":{"200":{"description":"Applied. Per-id results + Meta readback.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"total":{"type":["number","null"]},"succeeded":{"type":["number","null"]},"failed":{"type":["number","null"]},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"ok":{"type":["boolean","null"]}}}}}},"example":{"status":"completed","total":2,"succeeded":2,"failed":0,"results":[{"id":"120210000000000001","ok":true},{"id":"120210000000000002","ok":true}]}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/campaigns/{campaign_id}/duplicate":{"post":{"operationId":"duplicateCampaign","summary":"Duplicate a campaign (with optional overrides)","description":"Creates a copy of a campaign launched through ROAS, with every setting, targeting, creative, and tracking carried over. Any field you pass replaces just that part (new copy, new media, new budget, new geo, …). Meta creative is immutable, so this is how you swap creative on a winner. The copy gets fresh sub1/sub2/sub3 tracking for its own campaign / ad set / ad ids automatically (see launch), and the source campaign’s automation rules are attached unless `copy_rules: false`.\n\nInterest / custom-audience targeting always inherits from the original. Runs synchronously (typically 10–40s) and returns the new campaign.","tags":["Facebook management"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:clone"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"name":"campaign_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"daily_budget":{"description":"New daily budget (MAJOR currency). Omit to copy the original.","type":"number","exclusiveMinimum":0,"maximum":100000},"page_id":{"description":"Run under a different Facebook Page.","type":"string","pattern":"^\\d+$"},"start_immediately":{"description":"Launch ACTIVE (default: created PAUSED).","type":"boolean"},"copy_rules":{"description":"Attach every active automation rule the source campaign is assigned to (default true; false skips). Rules set to \"all campaigns\" already cover the copy. The response reports `rules_copied`.","type":"boolean"},"headlines":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1}},"body_texts":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1}},"descriptions":{"maxItems":5,"type":"array","items":{"type":"string","minLength":1}},"image_ids":{"description":"Replace the media with these media-library ids (see GET /v1/media).","minItems":1,"maxItems":10,"type":"array","items":{"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)$"}},"video_thumbnail_ids":{"maxItems":10,"type":"array","items":{"anyOf":[{"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)$"},{"type":"null"}]}},"custom_cta":{"type":"string","minLength":1},"countries":{"minItems":1,"type":"array","items":{"type":"string","minLength":2}},"age_min":{"type":"integer","minimum":13,"maximum":65},"age_max":{"type":"integer","minimum":13,"maximum":65},"genders":{"minItems":1,"type":"array","items":{"type":"string","enum":["1","2","all"]}},"devices":{"minItems":1,"type":"array","items":{"type":"string","enum":["mobile","desktop"]}},"exclude_tablet":{"type":"boolean"},"placements":{"type":"array","items":{"type":"string","minLength":1}},"campaign_objective":{"type":"string","minLength":1},"optimization_goal":{"type":"string","minLength":1},"bid_strategy":{"type":"string","minLength":1},"advantage_audience":{"type":"boolean"},"advantage_placements":{"type":"boolean"},"advantage_creative":{"type":"boolean"},"ai_disclosure":{"type":"boolean"},"value_rule_set":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"rules":{"minItems":1,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"adjust_sign":{"type":"string","minLength":1},"adjust_value":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"criterias":{"minItems":1,"type":"array","items":{"type":"object","properties":{"criteria_type":{"type":"string","minLength":1},"operator":{"default":"CONTAINS","type":"string"},"criteria_values":{"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"criteria_value_types":{"type":"array","items":{"type":"string"}}},"required":["criteria_type","criteria_values","criteria_value_types"]}}},"required":["name","adjust_sign","adjust_value","criterias"]}}},"required":["name","rules"]},"value_rule_recipe_id":{"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)$"},"end_date":{"description":"Ad set end date (YYYY-MM-DD).","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"201":{"description":"New campaign created.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"source_campaign_id":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"launch_id":{"type":["string","null"]},"ads_created":{"type":["number","null"]},"rules_copied":{"type":["number","null"]}}},"example":{"status":"completed","source_campaign_id":"120210000000000001","campaign_id":"120210000000000099","launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d","ads_created":6,"rules_copied":2}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/facebook/launch":{"post":{"operationId":"launchCampaign","summary":"Launch a campaign from scratch","description":"Builds a campaign → ad set(s) → ads in one call, with the same engine as the Create Ads page. Every headline × body × media combination becomes an ad (or one ad per media item with `ad_mode: 'per_creative'`). Tracking is stamped on every ad automatically — there is no `url_tags` to pass: every ad's link carries `sub1` = campaign id, `sub2` = ad set id, `sub3` = the ad (its Meta ad id, or a ROAS `ad_…` id ROAS resolves back to it), and the tracking redirect appends `sub1`–`sub5` to your offer URL, so Everflow (or any tracker reading sub1–sub3) receives them with no setup. Don't add your own `{{campaign.id}}`-style params to `destination_url` — duplicate sub params make attribution ambiguous.\n\n- Media: upload first with `POST /v1/media/images` / `POST /v1/media/videos`, then pass the returned ids in `image_ids`.\n- Destination: `destination_url` or `page_test_id`.\n- Created PAUSED unless `start_immediately` (or `start_time`) is set.\n- Use `dry_run: true` to validate and preview the build without touching Meta.\n- Pass an `Idempotency-Key` header: a retry returns the original launch instead of creating a second campaign.\n\nRuns synchronously (typically 15–60s). Partial success returns 201 with `ads_failed > 0` and the per-ad reasons. A failed launch returns 422 with the reason and the `launch_id` to inspect via `GET /v1/facebook/launches/{launch_id}`.","tags":["Facebook launch"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create"],"x-minimum-role":"editor","x-approval-gated":true,"x-supports-dry-run":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fb_account_id":{"type":"string","minLength":1,"description":"Ad account id (e.g. act_123…). REST: GET /v1/facebook/accounts · MCP: list_ad_assets."},"campaign_name":{"type":"string","minLength":1,"maxLength":200,"description":"Name for the new campaign."},"fb_page_id":{"type":"string","minLength":1,"description":"Facebook Page id to run the ads under."},"fb_pixel_id":{"type":"string","minLength":1,"description":"Facebook Pixel id for conversion tracking."},"daily_budget_major":{"type":"number","exclusiveMinimum":0,"maximum":100000,"description":"Daily budget in MAJOR account currency (e.g. dollars)."},"headlines":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1},"description":"1–5 ad headlines."},"body_texts":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1},"description":"1–5 primary/body texts."},"image_ids":{"minItems":1,"maxItems":10,"type":"array","items":{"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)$"},"description":"Media-library ids (UUIDs) for images OR videos. REST: GET /v1/media, POST /v1/media/images|videos · MCP: list_media, upload_media_from_url, upload_video_from_url."},"descriptions":{"description":"Optional link descriptions.","maxItems":5,"type":"array","items":{"type":"string","minLength":1}},"video_thumbnail_ids":{"description":"Optional custom thumbnail image ids, parallel to image_ids (for video creatives).","maxItems":10,"type":"array","items":{"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)$"}},"custom_cta":{"description":"Call-to-action (e.g. SHOP_NOW, LEARN_MORE).","type":"string","minLength":1},"countries":{"minItems":1,"type":"array","items":{"type":"string","minLength":2},"description":"ISO country codes (e.g. ['US','CA']) or ['WORLDWIDE']."},"age_min":{"default":18,"type":"integer","minimum":13,"maximum":65},"age_max":{"default":65,"type":"integer","minimum":13,"maximum":65},"genders":{"default":["all"],"minItems":1,"type":"array","items":{"type":"string","enum":["1","2","all"]}},"devices":{"default":["mobile","desktop"],"minItems":1,"type":"array","items":{"type":"string","enum":["mobile","desktop"]}},"exclude_tablet":{"description":"Opt out of tablets (deliver to phones only). Meta has no separate tablet placement, so this excludes tablet devices from the mobile bucket. Desktop is unaffected.","type":"boolean"},"placements":{"description":"Placement tokens; omit to use the standard default set.","type":"array","items":{"type":"string","minLength":1}},"campaign_objective":{"description":"Defaults to the standard objective.","type":"string","minLength":1},"conversion_event":{"description":"Pixel conversion event to optimize for (defaults to PURCHASE). Meta rejects events that are invalid for the chosen campaign objective (this is enforced by Meta at create time, not pre-validated here) — e.g. LEAD for lead-gen, ADD_TO_CART / INITIATED_CHECKOUT / COMPLETE_REGISTRATION for sales funnels.","type":"string","enum":["PURCHASE","ADD_TO_CART","INITIATED_CHECKOUT","LEAD","COMPLETE_REGISTRATION","CONTENT_VIEW","ADD_PAYMENT_INFO","ADD_TO_WISHLIST","SUBSCRIBE","START_TRIAL","CONTACT","DONATE","SCHEDULE","SUBMIT_APPLICATION","FIND_LOCATION","SEARCH"]},"optimization_goal":{"type":"string","minLength":1},"bid_strategy":{"type":"string","minLength":1},"advantage_audience":{"type":"boolean"},"advantage_placements":{"type":"boolean"},"advantage_creative":{"type":"boolean"},"ai_disclosure":{"description":"Manual \"media created or edited with AI\" self-disclosure stamped on every creative (legal compliance, e.g. NY State). Set true when the ad media is AI-generated or AI-edited.","type":"boolean"},"value_rule_set":{"description":"Optional Value Rules — bid multipliers by audience / placement / conversion-location criteria within the ad set ({name, rules[]}). Eligible only with LOWEST_COST_WITHOUT_CAP or COST_CAP bid strategy. Best-effort: ignored (campaign still launches) if the account can't use value rules.","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"rules":{"minItems":1,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"adjust_sign":{"type":"string","minLength":1},"adjust_value":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"criterias":{"minItems":1,"type":"array","items":{"type":"object","properties":{"criteria_type":{"type":"string","minLength":1},"operator":{"default":"CONTAINS","type":"string"},"criteria_values":{"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"criteria_value_types":{"type":"array","items":{"type":"string"}}},"required":["criteria_type","criteria_values","criteria_value_types"]}}},"required":["name","adjust_sign","adjust_value","criterias"]}}},"required":["name","rules"]},"value_rule_recipe_id":{"description":"Optional id of a saved value-rule recipe this set came from (UI/reuse pointer).","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)$"},"destination_url":{"description":"Where the ads send people (your landing page or offer URL). Required unless page_test_id is set. Sub-id tracking parameters are appended automatically.","type":"string","maxLength":2000,"format":"uri"},"page_test_id":{"description":"Send traffic through a ROAS page test instead of a raw URL (the test page_id). Required unless destination_url is set.","type":"string","minLength":1,"maxLength":50},"offer_name":{"description":"Optional label for the destination offer (shown in reporting).","type":"string","minLength":1,"maxLength":200},"ad_mode":{"description":"'combinatorial' (default) builds every headline × body × media combination; 'per_creative' builds one ad per media item sharing the same copy variants.","type":"string","enum":["combinatorial","per_creative"]},"ads_per_ad_set":{"description":"Split the ads across multiple ad sets with at most this many ads each.","type":"integer","minimum":1,"maximum":50},"bid_amount_major":{"description":"Bid cap / cost cap amount in MAJOR account currency. Required when bid_strategy is a cap strategy (LOWEST_COST_WITH_BID_CAP or COST_CAP). With LOWEST_COST_WITH_MIN_ROAS it is the ROAS floor as a multiple (2 = 2.0x), not money.","type":"number","exclusiveMinimum":0,"maximum":100000},"start_time":{"description":"Schedule the launch: ISO-8601 datetime the ad set starts delivering. Implies the campaign is created ACTIVE but waits for this time.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"end_date":{"description":"Ad set end date (YYYY-MM-DD, end of day in the ad account timezone).","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"interest_ids":{"description":"Meta interest ids to target. Find them with GET /v1/facebook/targeting/interests.","maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d+$"}},"interest_names":{"description":"Display names for interest_ids (same order). Optional, used for reporting.","maxItems":50,"type":"array","items":{"type":"string","minLength":1}},"included_audience_ids":{"description":"Custom/lookalike audience ids to target. See GET /v1/facebook/audiences.","maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d+$"}},"excluded_audience_ids":{"description":"Custom audience ids to exclude.","maxItems":50,"type":"array","items":{"type":"string","pattern":"^\\d+$"}},"languages":{"description":"Meta locale ids to target (e.g. 6 = English US, 24 = English UK).","maxItems":50,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"special_ad_categories":{"description":"Declare a special ad category (credit, employment, housing, …) when required.","type":"array","items":{"type":"string","enum":["HOUSING","EMPLOYMENT","ISSUES_ELECTIONS_POLITICS","FINANCIAL_PRODUCTS_SERVICES","ONLINE_GAMBLING_AND_GAMING"]}},"special_ad_category_countries":{"description":"Countries the special ad category applies in (ISO codes).","type":"array","items":{"type":"string","minLength":2,"maxLength":2}},"custom_conversion_id":{"description":"Optimize for a Meta custom conversion instead of conversion_event.","type":"string","pattern":"^\\d+$"},"automation_rule_ids":{"description":"Automation rules to attach to the new campaign at launch.","maxItems":20,"type":"array","items":{"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)$"}},"start_immediately":{"default":false,"description":"If true, the campaign launches ACTIVE; otherwise PAUSED.","type":"boolean"},"dry_run":{"description":"Validate and preview the exact change without applying it. Nothing is sent to Meta.","type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["fb_account_id","campaign_name","fb_page_id","fb_pixel_id","daily_budget_major","headlines","body_texts","image_ids","countries"]}}}},"responses":{"201":{"description":"Launched (possibly with some failed ads).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"launch_id":{"type":["string","null"]},"adset_ids":{"type":"array","items":{"type":["string","null"]}},"ad_ids":{"type":"array","items":{"type":["string","null"]}},"ads_created":{"type":["number","null"]},"ads_failed":{"type":["number","null"]},"failed_ads":{"type":"array","items":{}},"warnings":{"type":"array","items":{}}}},"example":{"status":"completed","campaign_id":"120210000000000099","launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d","adset_ids":["120210000000000100"],"ad_ids":["120210000000000101","120210000000000102"],"ads_created":2,"ads_failed":0,"failed_ads":[],"warnings":[]}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"description":"Meta (or a launch preflight) rejected the launch. Nothing was left running.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":["string","null"]},"message":{"type":["string","null"]},"launch_id":{"type":["string","null"]}}}}},"example":{"error":{"code":"unprocessable","message":"Page can't run ads. The Page isn't connected to this ad account's business. Connect it in Business Settings, then retry.","launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d"}}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/media":{"get":{"operationId":"listMedia","summary":"List media","description":"Images and videos in the media library, newest first. Pass the `id` values as `image_ids` when launching or duplicating.","tags":["Media"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"media_type","in":"query","required":false,"schema":{"type":"string","enum":["image","video"]}},{"name":"q","in":"query","required":false,"description":"Search filename and tags.","schema":{"type":"string","maxLength":200}},{"name":"tag","in":"query","required":false,"description":"Only media with this tag.","schema":{"type":"string","maxLength":64}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Media.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"media_type":{"type":["string","null"]},"filename":{"type":["string","null"]},"url":{"type":["string","null"]},"type":{"type":["string","null"]},"tags":{"type":"array","items":{"type":["string","null"]}},"width":{"type":["number","null"]},"height":{"type":["number","null"]},"stream_uid":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"media":[{"id":"6a1f0b2c-3d4e-4f5a-8b6c-7d8e9f0a1b2c","media_type":"image","filename":"hero-v2.jpg","url":"https://imagedelivery.net/abc/6a1f…/public","type":"ad_creative","tags":["keto","ugc"],"width":1080,"height":1350,"stream_uid":null,"created_at":"2026-10-18T14:02:11.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/media/{media_id}":{"get":{"operationId":"getMedia","summary":"Get a media item","description":"One media item. For videos, `status` is checked live: `ready` once transcoding finished, `processing` while it runs, `error` if the source could not be transcoded.","tags":["Media"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:campaigns"],"x-minimum-role":"viewer","parameters":[{"name":"media_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Media item.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"media_type":{"type":["string","null"]},"filename":{"type":["string","null"]},"url":{"type":["string","null"]},"type":{"type":["string","null"]},"tags":{"type":"array","items":{"type":["string","null"]}},"width":{"type":["number","null"]},"height":{"type":["number","null"]},"stream_uid":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]},"status":{"type":["string","null"]}}},"example":{"id":"6a1f0b2c-3d4e-4f5a-8b6c-7d8e9f0a1b2c","media_type":"image","filename":"hero-v2.jpg","url":"https://imagedelivery.net/abc/6a1f…/public","type":"ad_creative","tags":["keto","ugc"],"width":1080,"height":1350,"stream_uid":null,"created_at":"2026-10-18T14:02:11.000-04:00","status":"ready"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/media/images":{"post":{"operationId":"importImage","summary":"Import an image from a URL","description":"Fetches a public https image and stores it in the media library. Returns the `id` to use in `image_ids`. JPG / PNG / GIF / WebP.","tags":["Media"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create"],"x-minimum-role":"editor","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public https URL of the image."},"name":{"description":"Display name in the library.","type":"string","minLength":1,"maxLength":255},"type":{"default":"ad_creative","type":"string","enum":["ad_creative","product","header","icon","background"]},"tags":{"maxItems":8,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["url"]}}}},"responses":{"201":{"description":"Imported.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"url":{"type":["string","null"]},"media_type":{"type":["string","null"]}}},"example":{"status":"completed","id":"6a1f0b2c-3d4e-4f5a-8b6c-7d8e9f0a1b2c","url":"https://imagedelivery.net/abc/6a1f…/public","media_type":"image"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/media/videos":{"post":{"operationId":"importVideo","summary":"Import a video from a URL","description":"Copies a public https video (mp4 / mov) into the media library. Videos transcode asynchronously: when `status` is `processing`, poll `GET /v1/media/{id}` until it's `ready` (usually under a minute) before launching with it.","tags":["Media"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:create"],"x-minimum-role":"editor","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public https URL of the video."},"name":{"type":"string","minLength":1,"maxLength":255},"tags":{"maxItems":8,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["url"]}}}},"responses":{"201":{"description":"Imported (possibly still transcoding).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"id":{"type":["string","null"]},"media_type":{"type":["string","null"]},"stream_uid":{"type":["string","null"]}}},"example":{"status":"processing","id":"9b8c7d6e-5f4a-4b3c-8d2e-1f0a9b8c7d6e","media_type":"video","stream_uid":"31c9291ab41fac05471db4e73aa11717"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules":{"get":{"operationId":"listAutomationRules","summary":"List automation rules","description":"Automation rules (pause / activate / scale budget / bid cap / duplicate / budget schedule / alert) with their full configuration. With `account_id`, returns rules that apply to that account (including workspace-wide rules).","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"active","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Rules.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["null","string","number","object"]},"fb_account_ids":{"type":"array","items":{"type":["string","null"]}},"name":{"type":["string","null"]},"description":{"type":["null","string","number","object"]},"action_type":{"type":["string","null"]},"action_params":{"type":"object","properties":{}},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"schedule":{"type":["string","null"]},"cooldown_minutes":{"type":["number","null"]},"max_actions_per_day":{"type":["null","string","number","object"]},"execute_mode":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"last_executed":{"type":["string","null"]},"execution_count":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"rules":[{"id":"0f1e2d3c-4b5a-4968-8776-655443322110","fb_account_id":null,"fb_account_ids":["act_123456789"],"name":"Pause losers after $50","description":null,"action_type":"pause_campaign","action_params":{},"conditions":[{"metric":"spend","operator":"greater_than","value":50},{"metric":"tracker_conversions","operator":"equals","value":0}],"data_interval":"today","apply_to":"campaign","campaign_ids":["120210000000000001"],"schedule":"every_15m","cooldown_minutes":60,"max_actions_per_day":null,"execute_mode":"execute_and_alert","is_active":true,"last_executed":"2026-10-19T08:45:00.000-04:00","execution_count":14,"created_at":"2026-09-02T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createAutomationRule","summary":"Create an automation rule","description":"Creates a rule. Set `apply_to`: `'all'` for every campaign (narrow with `fb_account_ids`), or `'campaign'` / `'adset'` / `'ad'` with `campaign_ids` / `adset_ids` for specific entities. Conditions: up to 20 `{metric, operator, value, useTrackerData?}` with operators `greater_than`, `less_than`, `equals`, `greater_than_or_equal`, `less_than_or_equal`.\n\nScale rules take `action_params: {budget_change_pct, budget_change_type: 'increase' | 'decrease', max_budget_cap, min_budget_floor, cap_currency}`; increases require `max_budget_cap`. Unlike request bodies elsewhere, money inside `action_params` (caps, floors, bid caps) is integer MINOR units (cents) with its `cap_currency`, the same stored shape this API returns. Rules that move money (scale budget, bid caps, duplicate, budget schedules) can be queued by approval rules (202). Requires the admin role.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","x-approval-gated":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fb_account_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"fb_account_ids":{"anyOf":[{"type":"array","items":{"type":"string","minLength":1}},{"type":"null"}]},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"rule_group":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"data_interval":{"type":"string","enum":["today","yesterday","today_yesterday","this_week","last_week","this_month","last_30_days","last_7_days","last_1d","last_3d","last_7d","last_14d","last_30d","last_60d","last_90d","mtd","all_time"]},"exclude_days":{"anyOf":[{"anyOf":[{"type":"integer","minimum":0,"maximum":6},{"type":"array","items":{"type":"integer","minimum":0,"maximum":6}}]},{"type":"null"}]},"conditions":{"anyOf":[{"maxItems":20,"type":"array","items":{"type":"object","properties":{"metric":{"anyOf":[{"type":"string","enum":["roas","revenue","spend","conversions","ctr","cpc","cpa","impressions","clicks"]},{"type":"string","enum":["tracker_roas","tracker_conversions","tracker_revenue","tracker_cpa"]}]},"operator":{"type":"string","enum":["less_than","greater_than","equals","less_than_or_equal","greater_than_or_equal"]},"value":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"useTrackerData":{"type":"boolean"}},"required":["metric","operator","value"],"additionalProperties":false}},{"type":"null"}]},"rule_type":{"type":"string","maxLength":50},"action_type":{"type":"string","enum":["pause_campaign","activate_campaign","pause_adset","activate_adset","pause_ad","activate_ad","send_alert","scale_budget","scale_campaign_budget","duplicate_campaign","set_budget_schedule","adjust_bid_cap","set_bid_cap"]},"action_params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"apply_to":{"type":"string","enum":["all","campaign","adset","ad"]},"campaign_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"adset_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"schedule":{"type":"string","enum":["every_5m","every_15m","every_30m","hourly","every_2h","every_4h","every_6h","daily","daily_12pm_utc"]},"cooldown_minutes":{"anyOf":[{"type":"number","const":0},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":120},{"type":"number","const":240},{"type":"number","const":360},{"type":"number","const":720},{"type":"number","const":1440},{"type":"number","const":2880},{"type":"number","const":10080}]},"max_actions_per_day":{"anyOf":[{"type":"integer","minimum":1,"maximum":1000},{"type":"null"}]},"post_failure_cooldown_minutes":{"anyOf":[{"anyOf":[{"type":"number","const":0},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":120},{"type":"number","const":240},{"type":"number","const":360},{"type":"number","const":720},{"type":"number","const":1440},{"type":"number","const":2880},{"type":"number","const":10080}]},{"type":"null"}]},"execute_mode":{"type":"string","enum":["execute_and_alert","execute","alert_only"]},"execute_when_paused":{"type":"boolean"},"active_hours":{"anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","minimum":0,"maximum":23}},{"type":"null"}]},"active_days":{"anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","minimum":0,"maximum":6}},{"type":"null"}]},"daypart_timezone":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"daypart_window_start":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"daypart_window_end":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"daypart_window_mode":{"anyOf":[{"type":"string","enum":["active","pause"]},{"type":"null"}]},"applies_to_boosts":{"type":"boolean"},"is_active":{"type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["name","action_type"]}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["null","string","number","object"]},"fb_account_ids":{"type":"array","items":{"type":["string","null"]}},"name":{"type":["string","null"]},"description":{"type":["null","string","number","object"]},"action_type":{"type":["string","null"]},"action_params":{"type":"object","properties":{}},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"schedule":{"type":["string","null"]},"cooldown_minutes":{"type":["number","null"]},"max_actions_per_day":{"type":["null","string","number","object"]},"execute_mode":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"last_executed":{"type":["string","null"]},"execution_count":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"0f1e2d3c-4b5a-4968-8776-655443322110","fb_account_id":null,"fb_account_ids":["act_123456789"],"name":"Pause losers after $50","description":null,"action_type":"pause_campaign","action_params":{},"conditions":[{"metric":"spend","operator":"greater_than","value":50},{"metric":"tracker_conversions","operator":"equals","value":0}],"data_interval":"today","apply_to":"campaign","campaign_ids":["120210000000000001"],"schedule":"every_15m","cooldown_minutes":60,"max_actions_per_day":null,"execute_mode":"execute_and_alert","is_active":true,"last_executed":"2026-10-19T08:45:00.000-04:00","execution_count":14,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules/{rule_id}":{"get":{"operationId":"getAutomationRule","summary":"Get an automation rule","description":"One automation rule.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Rule.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["null","string","number","object"]},"fb_account_ids":{"type":"array","items":{"type":["string","null"]}},"name":{"type":["string","null"]},"description":{"type":["null","string","number","object"]},"action_type":{"type":["string","null"]},"action_params":{"type":"object","properties":{}},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"schedule":{"type":["string","null"]},"cooldown_minutes":{"type":["number","null"]},"max_actions_per_day":{"type":["null","string","number","object"]},"execute_mode":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"last_executed":{"type":["string","null"]},"execution_count":{"type":["number","null"]},"created_at":{"type":["string","null"]}}},"example":{"id":"0f1e2d3c-4b5a-4968-8776-655443322110","fb_account_id":null,"fb_account_ids":["act_123456789"],"name":"Pause losers after $50","description":null,"action_type":"pause_campaign","action_params":{},"conditions":[{"metric":"spend","operator":"greater_than","value":50},{"metric":"tracker_conversions","operator":"equals","value":0}],"data_interval":"today","apply_to":"campaign","campaign_ids":["120210000000000001"],"schedule":"every_15m","cooldown_minutes":60,"max_actions_per_day":null,"execute_mode":"execute_and_alert","is_active":true,"last_executed":"2026-10-19T08:45:00.000-04:00","execution_count":14,"created_at":"2026-09-02T10:00:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateAutomationRule","summary":"Update an automation rule","description":"Pass only the fields to change. Everything else keeps its current value, then the whole rule is re-validated. The account anchor (`fb_account_id` / `fb_account_ids`) cannot be changed; create a new rule instead. Edits that leave the rule moving money can be queued by approval rules (202).","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","x-approval-gated":true,"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"rule_group":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"data_interval":{"type":"string","enum":["today","yesterday","today_yesterday","this_week","last_week","this_month","last_30_days","last_7_days","last_1d","last_3d","last_7d","last_14d","last_30d","last_60d","last_90d","mtd","all_time"]},"exclude_days":{"anyOf":[{"anyOf":[{"type":"integer","minimum":0,"maximum":6},{"type":"array","items":{"type":"integer","minimum":0,"maximum":6}}]},{"type":"null"}]},"conditions":{"anyOf":[{"maxItems":20,"type":"array","items":{"type":"object","properties":{"metric":{"anyOf":[{"type":"string","enum":["roas","revenue","spend","conversions","ctr","cpc","cpa","impressions","clicks"]},{"type":"string","enum":["tracker_roas","tracker_conversions","tracker_revenue","tracker_cpa"]}]},"operator":{"type":"string","enum":["less_than","greater_than","equals","less_than_or_equal","greater_than_or_equal"]},"value":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"useTrackerData":{"type":"boolean"}},"required":["metric","operator","value"],"additionalProperties":false}},{"type":"null"}]},"rule_type":{"type":"string","maxLength":50},"action_type":{"type":"string","enum":["pause_campaign","activate_campaign","pause_adset","activate_adset","pause_ad","activate_ad","send_alert","scale_budget","scale_campaign_budget","duplicate_campaign","set_budget_schedule","adjust_bid_cap","set_bid_cap"]},"action_params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"apply_to":{"type":"string","enum":["all","campaign","adset","ad"]},"campaign_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"adset_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"schedule":{"type":"string","enum":["every_5m","every_15m","every_30m","hourly","every_2h","every_4h","every_6h","daily","daily_12pm_utc"]},"cooldown_minutes":{"anyOf":[{"type":"number","const":0},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":120},{"type":"number","const":240},{"type":"number","const":360},{"type":"number","const":720},{"type":"number","const":1440},{"type":"number","const":2880},{"type":"number","const":10080}]},"max_actions_per_day":{"anyOf":[{"type":"integer","minimum":1,"maximum":1000},{"type":"null"}]},"post_failure_cooldown_minutes":{"anyOf":[{"anyOf":[{"type":"number","const":0},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":120},{"type":"number","const":240},{"type":"number","const":360},{"type":"number","const":720},{"type":"number","const":1440},{"type":"number","const":2880},{"type":"number","const":10080}]},{"type":"null"}]},"execute_mode":{"type":"string","enum":["execute_and_alert","execute","alert_only"]},"execute_when_paused":{"type":"boolean"},"active_hours":{"anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","minimum":0,"maximum":23}},{"type":"null"}]},"active_days":{"anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","minimum":0,"maximum":6}},{"type":"null"}]},"daypart_timezone":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"daypart_window_start":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"daypart_window_end":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"daypart_window_mode":{"anyOf":[{"type":"string","enum":["active","pause"]},{"type":"null"}]},"applies_to_boosts":{"type":"boolean"},"is_active":{"type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["null","string","number","object"]},"fb_account_ids":{"type":"array","items":{"type":["string","null"]}},"name":{"type":["string","null"]},"description":{"type":["null","string","number","object"]},"action_type":{"type":["string","null"]},"action_params":{"type":"object","properties":{}},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"schedule":{"type":["string","null"]},"cooldown_minutes":{"type":["number","null"]},"max_actions_per_day":{"type":["null","string","number","object"]},"execute_mode":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"last_executed":{"type":["string","null"]},"execution_count":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"0f1e2d3c-4b5a-4968-8776-655443322110","fb_account_id":null,"fb_account_ids":["act_123456789"],"name":"Pause losers after $50","description":null,"action_type":"pause_campaign","action_params":{},"conditions":[{"metric":"spend","operator":"greater_than","value":50},{"metric":"tracker_conversions","operator":"equals","value":0}],"data_interval":"today","apply_to":"campaign","campaign_ids":["120210000000000001"],"schedule":"every_15m","cooldown_minutes":60,"max_actions_per_day":null,"execute_mode":"execute_and_alert","is_active":true,"last_executed":"2026-10-19T08:45:00.000-04:00","execution_count":14,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteAutomationRule","summary":"Delete an automation rule","description":"Deletes the rule. For budget-schedule rules, the Facebook budget schedules it created are removed too; if Meta can't be reached the call fails unless `force=true` (left-over schedules expire at their end time). Requires `?confirm=true`.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"name":"force","in":"query","required":false,"description":"Delete even if Facebook cleanup fails.","schema":{"type":"string","enum":["true","false"]}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"deleted_budget_schedules":{"type":["number","null"]},"skipped_budget_schedules":{"type":["number","null"]}}},"example":{"status":"completed","deleted_budget_schedules":0,"skipped_budget_schedules":0}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules/{rule_id}/status":{"post":{"operationId":"setAutomationRuleStatus","summary":"Pause or resume an automation rule","description":"Turns the rule on (`active: true`) or off.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean","description":"true = rule runs; false = paused."},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["active"]}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule_id":{"type":["string","null"]},"active":{"type":["boolean","null"]}}},"example":{"status":"completed","rule_id":"0f1e2d3c-4b5a-4968-8776-655443322110","active":false}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules/{rule_id}/campaigns":{"post":{"operationId":"assignAutomationRule","summary":"Attach a rule to campaigns","description":"Adds campaigns to a campaign-scoped rule (for a workspace-wide rule, re-includes previously excluded campaigns). Results are per campaign.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaign_ids":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{5,25}$","description":"Numeric Facebook id (campaign / ad set / ad)."}},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["campaign_ids"]}}}},"responses":{"200":{"description":"Per-campaign results.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule_id":{"type":["string","null"]},"results":{"type":"array","items":{"type":"object","properties":{"campaign_id":{"type":["string","null"]},"ok":{"type":["boolean","null"]},"already_assigned":{"type":["boolean","null"]}}}},"total_campaigns":{"type":["number","null"]}}},"example":{"status":"completed","rule_id":"0f1e2d3c-4b5a-4968-8776-655443322110","results":[{"campaign_id":"120210000000000001","ok":true,"already_assigned":false}],"total_campaigns":2}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules/{rule_id}/campaigns/{campaign_id}":{"delete":{"operationId":"unassignAutomationRule","summary":"Detach a rule from a campaign","description":"Removes the campaign from a campaign-scoped rule (for a workspace-wide rule, excludes the campaign).","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"campaign_id","in":"path","required":true,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Detached.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"removed":{"type":["boolean","null"]}}},"example":{"status":"completed","removed":true}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/rules/{rule_id}/executions":{"get":{"operationId":"listAutomationRuleExecutions","summary":"List a rule’s executions","description":"What the rule did, newest first: action, target, old → new value, money saved, success or failure.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Executions.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"executions":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"executed_at":{"type":["string","null"]},"action":{"type":["string","null"]},"status":{"type":["string","null"]},"reason":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"fb_adset_id":{"type":["null","string","number","object"]},"fb_ad_id":{"type":["null","string","number","object"]},"old_value":{"type":["string","null"]},"new_value":{"type":["string","null"]},"money_saved":{"type":["number","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"executions":[{"id":"5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b","executed_at":"2026-10-19T08:45:00.000-04:00","action":"pause_campaign","status":"success","reason":"spend 52.10 > 50 and tracker_conversions 0 = 0","fb_campaign_id":"120210000000000001","fb_adset_id":null,"fb_ad_id":null,"old_value":"ACTIVE","new_value":"PAUSED","money_saved":31.4}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/clone-rules":{"get":{"operationId":"listCloneRules","summary":"List clone rules","description":"Auto-scaling rules that duplicate winning campaigns when their conditions are met.","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}},{"name":"active","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Rules.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"clone_mode":{"type":["string","null"]},"budget_override":{"type":["number","null"]},"start_immediately":{"type":["boolean","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"max_clones_per_day":{"type":["number","null"]},"min_hours_between_clones":{"type":["number","null"]},"is_active":{"type":["boolean","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"rules":[{"id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","fb_account_id":"act_123456789","name":"Scale winners","conditions":[{"metric":"tracker_roas","operator":"greater_than_or_equal","value":2.5}],"data_interval":"last_3d","clone_mode":"simple","budget_override":100,"start_immediately":true,"apply_to":"campaign","campaign_ids":["120210000000000001"],"max_clones_per_day":3,"min_hours_between_clones":24,"is_active":true,"created_at":"2026-09-02T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createCloneRule","summary":"Create a clone rule","description":"Creates an auto-scaling rule (simple mode; AI copy modes are set up in the app). Conditions use `spend`, `tracker_roas`, `tracker_conversions`, `tracker_revenue`. `budget_override` is MAJOR currency. Creating a clone rule clears the workspace's campaign-creation approval rules (202 when queued).","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","x-approval-gated":true,"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fb_account_id":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"conditions":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"metric":{"type":"string","enum":["spend","tracker_roas","tracker_conversions","tracker_revenue"]},"operator":{"type":"string","enum":["less_than","greater_than","equals","less_than_or_equal","greater_than_or_equal"]},"value":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"useTrackerData":{"type":"boolean"}},"required":["metric","operator","value"],"additionalProperties":false}},"data_interval":{"type":"string","enum":["today","yesterday","today_yesterday","this_week","last_week","this_month","last_30_days","last_7_days","last_1d","last_3d","last_7d","last_14d","last_30d","last_60d","last_90d","mtd","all_time"]},"clone_mode":{"type":"string","enum":["simple","ai_headlines","ai_scripts","ai_full"]},"budget_override":{"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":100000},{"type":"null"}]},"page_override":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"start_immediately":{"type":"boolean"},"copy_automation_rules":{"type":"boolean"},"name_suffix":{"type":"string","maxLength":100},"ai_headline_count":{"anyOf":[{"type":"integer","minimum":0,"maximum":50},{"type":"null"}]},"ai_script_count":{"anyOf":[{"type":"integer","minimum":0,"maximum":50},{"type":"null"}]},"ai_persona":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"ai_tone":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"ai_provider":{"anyOf":[{"type":"string","enum":["anthropic","openai"]},{"type":"null"}]},"ai_model":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"ai_headline_prompt_version":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"ai_script_prompt_version":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"max_clones_per_day":{"type":"integer","minimum":1,"maximum":100},"min_hours_between_clones":{"type":"integer","minimum":1,"maximum":720},"post_failure_cooldown_hours":{"anyOf":[{"type":"integer","minimum":0,"maximum":720},{"type":"null"}]},"apply_to":{"type":"string","enum":["all","campaign"]},"campaign_ids":{"anyOf":[{"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":50}},{"type":"null"}]},"scheduling_mode":{"type":"string","enum":["trigger","scheduled"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"recurring_pattern":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly"]},{"type":"null"}]},"recurring_hour":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"recurring_day":{"anyOf":[{"type":"integer","minimum":0,"maximum":31},{"type":"null"}]},"schedule_timezone":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"next_scheduled_run":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"active_hours_start":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"active_hours_end":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"is_active":{"type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["fb_account_id","name","conditions"]}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"clone_mode":{"type":["string","null"]},"budget_override":{"type":["number","null"]},"start_immediately":{"type":["boolean","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"max_clones_per_day":{"type":["number","null"]},"min_hours_between_clones":{"type":["number","null"]},"is_active":{"type":["boolean","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","fb_account_id":"act_123456789","name":"Scale winners","conditions":[{"metric":"tracker_roas","operator":"greater_than_or_equal","value":2.5}],"data_interval":"last_3d","clone_mode":"simple","budget_override":100,"start_immediately":true,"apply_to":"campaign","campaign_ids":["120210000000000001"],"max_clones_per_day":3,"min_hours_between_clones":24,"is_active":true,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/clone-rules/{rule_id}":{"get":{"operationId":"getCloneRule","summary":"Get a clone rule","description":"One clone rule.","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Rule.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"clone_mode":{"type":["string","null"]},"budget_override":{"type":["number","null"]},"start_immediately":{"type":["boolean","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"max_clones_per_day":{"type":["number","null"]},"min_hours_between_clones":{"type":["number","null"]},"is_active":{"type":["boolean","null"]},"created_at":{"type":["string","null"]}}},"example":{"id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","fb_account_id":"act_123456789","name":"Scale winners","conditions":[{"metric":"tracker_roas","operator":"greater_than_or_equal","value":2.5}],"data_interval":"last_3d","clone_mode":"simple","budget_override":100,"start_immediately":true,"apply_to":"campaign","campaign_ids":["120210000000000001"],"max_clones_per_day":3,"min_hours_between_clones":24,"is_active":true,"created_at":"2026-09-02T10:00:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateCloneRule","summary":"Update a clone rule","description":"Pass only the fields to change. Material changes (conditions, budget, targets, limits, re-activation) clear the approval rules (202 when queued); name / description / pausing never do.","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","x-approval-gated":true,"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"conditions":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"metric":{"type":"string","enum":["spend","tracker_roas","tracker_conversions","tracker_revenue"]},"operator":{"type":"string","enum":["less_than","greater_than","equals","less_than_or_equal","greater_than_or_equal"]},"value":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"useTrackerData":{"type":"boolean"}},"required":["metric","operator","value"],"additionalProperties":false}},"data_interval":{"type":"string","enum":["today","yesterday","today_yesterday","this_week","last_week","this_month","last_30_days","last_7_days","last_1d","last_3d","last_7d","last_14d","last_30d","last_60d","last_90d","mtd","all_time"]},"clone_mode":{"type":"string","enum":["simple","ai_headlines","ai_scripts","ai_full"]},"budget_override":{"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":100000},{"type":"null"}]},"page_override":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"start_immediately":{"type":"boolean"},"copy_automation_rules":{"type":"boolean"},"name_suffix":{"type":"string","maxLength":100},"ai_headline_count":{"anyOf":[{"type":"integer","minimum":0,"maximum":50},{"type":"null"}]},"ai_script_count":{"anyOf":[{"type":"integer","minimum":0,"maximum":50},{"type":"null"}]},"ai_persona":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"ai_tone":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"ai_provider":{"anyOf":[{"type":"string","enum":["anthropic","openai"]},{"type":"null"}]},"ai_model":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"ai_headline_prompt_version":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"ai_script_prompt_version":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"max_clones_per_day":{"type":"integer","minimum":1,"maximum":100},"min_hours_between_clones":{"type":"integer","minimum":1,"maximum":720},"post_failure_cooldown_hours":{"anyOf":[{"type":"integer","minimum":0,"maximum":720},{"type":"null"}]},"apply_to":{"type":"string","enum":["all","campaign"]},"campaign_ids":{"anyOf":[{"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":50}},{"type":"null"}]},"scheduling_mode":{"type":"string","enum":["trigger","scheduled"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"recurring_pattern":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly"]},{"type":"null"}]},"recurring_hour":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"recurring_day":{"anyOf":[{"type":"integer","minimum":0,"maximum":31},{"type":"null"}]},"schedule_timezone":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"next_scheduled_run":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"active_hours_start":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"active_hours_end":{"anyOf":[{"type":"integer","minimum":0,"maximum":23},{"type":"null"}]},"is_active":{"type":"boolean"},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"name":{"type":["string","null"]},"conditions":{"type":"array","items":{"type":"object","properties":{"metric":{"type":["string","null"]},"operator":{"type":["string","null"]},"value":{"type":["number","null"]}}}},"data_interval":{"type":["string","null"]},"clone_mode":{"type":["string","null"]},"budget_override":{"type":["number","null"]},"start_immediately":{"type":["boolean","null"]},"apply_to":{"type":["string","null"]},"campaign_ids":{"type":"array","items":{"type":["string","null"]}},"max_clones_per_day":{"type":["number","null"]},"min_hours_between_clones":{"type":["number","null"]},"is_active":{"type":["boolean","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","fb_account_id":"act_123456789","name":"Scale winners","conditions":[{"metric":"tracker_roas","operator":"greater_than_or_equal","value":2.5}],"data_interval":"last_3d","clone_mode":"simple","budget_override":100,"start_immediately":true,"apply_to":"campaign","campaign_ids":["120210000000000001"],"max_clones_per_day":3,"min_hours_between_clones":24,"is_active":true,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteCloneRule","summary":"Delete a clone rule","description":"Deletes the rule and its run history. Campaigns it already created are untouched. Requires `?confirm=true`.","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]}}},"example":{"status":"completed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/clone-rules/{rule_id}/status":{"post":{"operationId":"setCloneRuleStatus","summary":"Pause or resume a clone rule","description":"Pausing is immediate; resuming clears the approval rules (202 when queued).","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","x-approval-gated":true,"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean","description":"true = rule runs; false = paused."},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["active"]}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule_id":{"type":["string","null"]},"active":{"type":["boolean","null"]}}},"example":{"status":"completed","rule_id":"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d","active":false}}}},"202":{"description":"Queued for approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"pending_action_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}}},"example":{"status":"pending_approval","pending_action_id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","expires_at":"2026-10-20T14:00:00.000Z","message":"A workspace approval rule matched. An owner or admin must approve this in ROAS.to."}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/clone-rules/{rule_id}/jobs":{"get":{"operationId":"listCloneRuleJobs","summary":"List a clone rule’s runs","description":"Each clone the rule triggered: status, source and new campaign, ads created, errors.","tags":["Clone rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Runs.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"jobs":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"status":{"type":["string","null"]},"parent_campaign_id":{"type":["string","null"]},"new_campaign_id":{"type":["string","null"]},"launch_id":{"type":["string","null"]},"ads_created":{"type":["number","null"]},"clone_mode":{"type":["string","null"]},"error_message":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"jobs":[{"id":"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e","status":"completed","parent_campaign_id":"120210000000000001","new_campaign_id":"120210000000000099","launch_id":"b9a7c1d2-3e4f-4a5b-8c6d-7e8f9a0b1c2d","ads_created":6,"clone_mode":"simple","error_message":null,"created_at":"2026-10-19T06:00:00.000-04:00","completed_at":"2026-10-19T06:00:41.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/auto-boost-rules":{"get":{"operationId":"listAutoBoostRules","summary":"List auto-boost rules","description":"Rules that boost organic Page posts once they cross an engagement threshold.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"account_id","in":"query","required":false,"description":"Facebook ad account id, e.g. act_1234567890.","schema":{"type":"string","pattern":"^act_\\d{1,25}$"}}],"responses":{"200":{"description":"Rules.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"fb_page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"is_enabled":{"type":["boolean","null"]},"trigger_metric":{"type":["string","null"]},"trigger_threshold":{"type":["number","null"]},"template_adset_fb_id":{"type":["string","null"]},"daily_budget_major":{"type":["number","null"]},"objective":{"type":["string","null"]},"cooldown_per_post_hours":{"type":["number","null"]},"max_boosts_per_day":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"rules":[{"id":"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f","fb_account_id":"act_123456789","fb_page_id":"104455667788990","name":"Boost viral posts","is_enabled":true,"trigger_metric":"engagement_24h_delta","trigger_threshold":200,"template_adset_fb_id":"120210000000000002","daily_budget_major":25,"objective":"OUTCOME_ENGAGEMENT","cooldown_per_post_hours":168,"max_boosts_per_day":3,"created_at":"2026-09-02T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createAutoBoostRule","summary":"Create an auto-boost rule","description":"`template_adset_fb_id` is an existing ad set whose targeting / optimization each boost copies. `daily_budget_major` is MAJOR currency.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"is_enabled":{"type":"boolean"},"fb_account_id":{"type":"string","minLength":1},"fb_page_id":{"type":["string","null"]},"trigger_metric":{"type":"string","enum":["likes_24h_delta","comments_24h_delta","shares_24h_delta","engagement_24h_delta","engagement_72h_delta","total_engagement"]},"trigger_threshold":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"template_adset_fb_id":{"type":"string","minLength":1},"daily_budget_major":{"type":"number","exclusiveMinimum":0,"maximum":100000},"objective":{"type":"string","minLength":1,"maxLength":40},"cooldown_per_post_hours":{"type":"integer","minimum":1,"maximum":720},"max_boosts_per_day":{"type":"integer","minimum":1,"maximum":50},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["name","fb_account_id","trigger_metric","trigger_threshold","template_adset_fb_id","daily_budget_major"]}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"fb_page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"is_enabled":{"type":["boolean","null"]},"trigger_metric":{"type":["string","null"]},"trigger_threshold":{"type":["number","null"]},"template_adset_fb_id":{"type":["string","null"]},"daily_budget_major":{"type":["number","null"]},"objective":{"type":["string","null"]},"cooldown_per_post_hours":{"type":["number","null"]},"max_boosts_per_day":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f","fb_account_id":"act_123456789","fb_page_id":"104455667788990","name":"Boost viral posts","is_enabled":true,"trigger_metric":"engagement_24h_delta","trigger_threshold":200,"template_adset_fb_id":"120210000000000002","daily_budget_major":25,"objective":"OUTCOME_ENGAGEMENT","cooldown_per_post_hours":168,"max_boosts_per_day":3,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/auto-boost-rules/{rule_id}":{"get":{"operationId":"getAutoBoostRule","summary":"Get an auto-boost rule","description":"One auto-boost rule.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Rule.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"fb_page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"is_enabled":{"type":["boolean","null"]},"trigger_metric":{"type":["string","null"]},"trigger_threshold":{"type":["number","null"]},"template_adset_fb_id":{"type":["string","null"]},"daily_budget_major":{"type":["number","null"]},"objective":{"type":["string","null"]},"cooldown_per_post_hours":{"type":["number","null"]},"max_boosts_per_day":{"type":["number","null"]},"created_at":{"type":["string","null"]}}},"example":{"id":"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f","fb_account_id":"act_123456789","fb_page_id":"104455667788990","name":"Boost viral posts","is_enabled":true,"trigger_metric":"engagement_24h_delta","trigger_threshold":200,"template_adset_fb_id":"120210000000000002","daily_budget_major":25,"objective":"OUTCOME_ENGAGEMENT","cooldown_per_post_hours":168,"max_boosts_per_day":3,"created_at":"2026-09-02T10:00:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateAutoBoostRule","summary":"Update an auto-boost rule","description":"Pass only the fields to change. The ad account cannot be changed.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"is_enabled":{"type":"boolean"},"fb_page_id":{"type":["string","null"]},"trigger_metric":{"type":"string","enum":["likes_24h_delta","comments_24h_delta","shares_24h_delta","engagement_24h_delta","engagement_72h_delta","total_engagement"]},"trigger_threshold":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"template_adset_fb_id":{"type":"string","minLength":1},"daily_budget_major":{"type":"number","exclusiveMinimum":0,"maximum":100000},"objective":{"type":"string","minLength":1,"maxLength":40},"cooldown_per_post_hours":{"type":"integer","minimum":1,"maximum":720},"max_boosts_per_day":{"type":"integer","minimum":1,"maximum":50},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"id":{"type":["string","null"]},"fb_account_id":{"type":["string","null"]},"fb_page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"is_enabled":{"type":["boolean","null"]},"trigger_metric":{"type":["string","null"]},"trigger_threshold":{"type":["number","null"]},"template_adset_fb_id":{"type":["string","null"]},"daily_budget_major":{"type":["number","null"]},"objective":{"type":["string","null"]},"cooldown_per_post_hours":{"type":["number","null"]},"max_boosts_per_day":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}},"example":{"status":"completed","rule":{"id":"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f","fb_account_id":"act_123456789","fb_page_id":"104455667788990","name":"Boost viral posts","is_enabled":true,"trigger_metric":"engagement_24h_delta","trigger_threshold":200,"template_adset_fb_id":"120210000000000002","daily_budget_major":25,"objective":"OUTCOME_ENGAGEMENT","cooldown_per_post_hours":168,"max_boosts_per_day":3,"created_at":"2026-09-02T10:00:00.000-04:00"}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteAutoBoostRule","summary":"Delete an auto-boost rule","description":"Deletes the rule. Boosts it already created keep running. Requires `?confirm=true`.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]}}},"example":{"status":"completed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/auto-boost-rules/{rule_id}/status":{"post":{"operationId":"setAutoBoostRuleStatus","summary":"Enable or disable an auto-boost rule","description":"Turns the rule on or off. Re-enabling clears its last error.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:automation"],"x-minimum-role":"admin","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean","description":"true = rule runs; false = paused."},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["active"]}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"rule_id":{"type":["string","null"]},"active":{"type":["boolean","null"]}}},"example":{"status":"completed","rule_id":"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f","active":true}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/auto-boost-rules/{rule_id}/executions":{"get":{"operationId":"listAutoBoostExecutions","summary":"List an auto-boost rule’s boosts","description":"Each post the rule boosted (or tried to): status, campaign created, metric at fire time, errors.","tags":["Auto-boost rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"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)$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Executions.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"executions":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"status":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"metric_value_at_fire":{"type":["number","null"]},"error_message":{"type":["null","string","number","object"]},"executed_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"executions":[{"id":"4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a","status":"success","fb_campaign_id":"120210000000000120","metric_value_at_fire":214,"error_message":null,"executed_at":"2026-10-19T07:10:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/conversions":{"get":{"operationId":"listConversions","summary":"List conversions","description":"Every recorded conversion (from postbacks, the pixel, Shopify, and this API), newest first, with how it was attributed. Account-restricted keys only see conversions attributed to their ad accounts.","tags":["Conversions"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:conversions"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"query","required":false,"description":"Only conversions from this page test.","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"campaign_id","in":"query","required":false,"description":"Numeric Facebook id (campaign / ad set / ad).","schema":{"type":"string","pattern":"^\\d{5,25}$"}},{"name":"attributed","in":"query","required":false,"description":"true = attributed to a Facebook ad; false = unattributed.","schema":{"type":"string","enum":["true","false"]}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone (e.g. today, yesterday, last_7d, last_30d, this_month, all_time). Default last_30d.","schema":{"type":"string","enum":["today","yesterday","today_yesterday","last_3_days","last_3d","last_7_days","last_7d","last_14_days","last_14d","last_30_days","last_30d","last_60_days","last_60d","last_90_days","last_90d","this_week","last_week","this_month","mtd","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive). Max range 548 days. Ignored when date_range is set.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Conversions.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"conversions":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"timestamp":{"type":["string","null"]},"revenue":{"type":["number","null"]},"currency":{"type":["string","null"]},"transaction_id":{"type":["string","null"]},"order_id":{"type":["string","null"]},"attribution_method":{"type":["string","null"]},"page_id":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"fb_campaign_id":{"type":["string","null"]},"fb_adset_id":{"type":["string","null"]},"fb_ad_id":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"conversions":[{"id":"3b4c5d6e-7f8a-4b9c-8d0e-1f2a3b4c5d6e","timestamp":"2026-10-19T08:42:11.000-04:00","revenue":49,"currency":"USD","transaction_id":"ord_1001","order_id":"1001","attribution_method":"sub4_session","page_id":"keto-advertorial","variant_id":"v2","fb_campaign_id":"120210000000000001","fb_adset_id":"120210000000000002","fb_ad_id":"120210000000000003"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"recordConversion","summary":"Record a conversion (server-side)","description":"Sends a sale from your server. It runs through the same pipeline as tracker postbacks: attribution (sub4 first, then sub1/2/3), cross-source dedup on `order_id`, the boosted-post guard, and Meta Conversions API delivery. Idempotent on `order_id` / `transaction_id`.","tags":["Conversions"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:conversions"],"x-minimum-role":"editor","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"revenue":{"type":"number","minimum":0,"maximum":100000,"description":"Sale amount (MAJOR units)."},"currency":{"description":"ISO 4217 code. Defaults to the workspace currency.","type":"string","pattern":"^[A-Z]{3}$"},"order_id":{"description":"Your order id (dedupes with Shopify).","type":"string","minLength":1,"maxLength":96},"transaction_id":{"description":"Unique sale id.","type":"string","minLength":1,"maxLength":100},"sub4":{"description":"The sub4 click id the visitor arrived with (the deterministic attribution bond).","type":"string","pattern":"^[a-z0-9_.-]+:[a-z0-9_.-]+:[a-z0-9_.-]+(:[a-z0-9_.-]+(:[a-z0-9_.-]+)?)?$"},"sub1":{"description":"Campaign id from the click URL.","type":"string","maxLength":255},"sub2":{"description":"Ad set id from the click URL.","type":"string","maxLength":255},"sub3":{"description":"Ad id from the click URL.","type":"string","maxLength":255},"product_id":{"type":"string","maxLength":128},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["revenue"]}}}},"responses":{"201":{"description":"Recorded.","content":{"application/json":{"schema":{"type":"object","properties":{"recorded":{"type":["boolean","null"]}}},"example":{"recorded":true}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/automation/history":{"get":{"operationId":"getAutomationHistory","summary":"Automation history","description":"Everything your automation did across all rules: pauses, scales, duplicates, and alerts, with targets, values, and money saved.","tags":["Automation rules"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"action","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["paused","scaled","duplicated","alerted","all"]}},{"name":"status","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["success","failure","all"]}},{"name":"campaign_search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"date_range","in":"query","required":false,"description":"Relative range in the workspace timezone. Not every endpoint supports every value.","schema":{"type":"string","enum":["today","yesterday","last_3d","last_7d","last_30d","this_week","last_week","this_month","all_time"]}},{"name":"start_date","in":"query","required":false,"description":"YYYY-MM-DD, use with end_date.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"end_date","in":"query","required":false,"description":"YYYY-MM-DD (inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Log + summary.","content":{"application/json":{"schema":{"type":"object","properties":{"logs":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"executed_at":{"type":["string","null"]},"action_taken":{"type":["string","null"]},"status":{"type":["string","null"]},"rule":{"type":"object","properties":{"name":{"type":["string","null"]}}},"target":{"type":"object","properties":{"campaign_id":{"type":["string","null"]}}},"money_saved":{"type":["number","null"]}}}},"summary":{"type":"object","properties":{"total_actions":{"type":["number","null"]},"success_count":{"type":["number","null"]},"failure_count":{"type":["number","null"]},"money_saved":{"type":["number","null"]}}}}},"example":{"logs":[{"id":"5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b","executed_at":"2026-10-19T08:45:00.000-04:00","action_taken":"pause_campaign","status":"success","rule":{"name":"Pause losers after $50"},"target":{"campaign_id":"120210000000000001"},"money_saved":31.4}],"summary":{"total_actions":1,"success_count":1,"failure_count":0,"money_saved":31.4}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tracker/offers":{"get":{"operationId":"listTrackerOffers","summary":"Tracker offers","description":"Offers, landing pages, and smart links from your connected tracker (Everflow), with status and URLs.","tags":["Conversions"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:conversions"],"x-minimum-role":"viewer","parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["active","paused","expired","all"]}},{"name":"limit","in":"query","required":false,"description":"Rows (1–50, default 20).","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Offers.","content":{"application/json":{"schema":{"type":"object","properties":{"offers":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"external_offer_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"payout":{"type":["number","null"]},"payout_type":{"type":["string","null"]},"urls":{"type":"array","items":{}}}}}}},"example":{"offers":[{"id":"2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d","external_offer_id":"12","name":"Keto Gummies — US","status":"active","payout":45,"payout_type":"cpa","urls":[]}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/activity":{"get":{"operationId":"listActivity","summary":"Workspace activity log","description":"Who changed what, newest first: launches, edits, rule changes, approvals, API and MCP actions. Admin role and an unrestricted key required.","tags":["Account"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"admin","parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"action","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string","maxLength":100}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Entries.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"user_id":{"type":["string","null"]},"action":{"type":["string","null"]},"entity_type":{"type":["string","null"]},"entity_id":{"type":["string","null"]},"summary":{"type":["string","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"entries":[{"id":"6f7a8b9c-0d1e-4f2a-8b3c-4d5e6f7a8b9c","user_id":"user_2abc","action":"executed","entity_type":"api_key","entity_id":"7e1f…","summary":"API launchCampaign: Launched campaign \"TOF — Broad — US\" (6 ads)","created_at":"2026-10-19T09:00:41.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/approvals":{"get":{"operationId":"listApprovals","summary":"List approval requests","description":"Writes that a workspace approval rule queued (the API returned 202 + `pending_action_id`). Owners and admins see the whole workspace; other roles see only their own requests. Statuses: pending → approved → executed / failed, or rejected / expired. Approving happens in ROAS.to (Team → Approvals). A human gate can't be approved by the key it gates.","tags":["Approvals"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","approved","rejected","expired","executed","failed"]}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Requests, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"approvals":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"action_type":{"type":["string","null"]},"target_summary":{"type":["string","null"]},"status":{"type":["string","null"]},"requested_by_user_id":{"type":["string","null"]},"requested_by_you":{"type":["boolean","null"]},"approver_user_id":{"type":["null","string","number","object"]},"decision_at":{"type":["null","string","number","object"]},"decision_note":{"type":["null","string","number","object"]},"executed_at":{"type":["null","string","number","object"]},"execution_error":{"type":["null","string","number","object"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"approvals":[{"id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","action_type":"budget_increase","target_summary":"Set daily budget on 1 campaign(s) (API)","status":"pending","requested_by_user_id":"user_2abc","requested_by_you":true,"approver_user_id":null,"decision_at":null,"decision_note":null,"executed_at":null,"execution_error":null,"expires_at":"2026-10-20T09:00:00.000-04:00","created_at":"2026-10-19T09:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/approvals/{approval_id}":{"get":{"operationId":"getApproval","summary":"Get an approval request","description":"Poll this after a 202 to learn whether the write was approved and executed.","tags":["Approvals"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:automation"],"x-minimum-role":"viewer","parameters":[{"name":"approval_id","in":"path","required":true,"schema":{"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)$"}}],"responses":{"200":{"description":"Request.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"action_type":{"type":["string","null"]},"target_summary":{"type":["string","null"]},"status":{"type":["string","null"]},"requested_by_user_id":{"type":["string","null"]},"requested_by_you":{"type":["boolean","null"]},"approver_user_id":{"type":["null","string","number","object"]},"decision_at":{"type":["null","string","number","object"]},"decision_note":{"type":["null","string","number","object"]},"executed_at":{"type":["null","string","number","object"]},"execution_error":{"type":["null","string","number","object"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}}},"example":{"id":"5d0c3a52-6b1f-4c1e-9d8f-2a6b7f0c9e11","action_type":"budget_increase","target_summary":"Set daily budget on 1 campaign(s) (API)","status":"pending","requested_by_user_id":"user_2abc","requested_by_you":true,"approver_user_id":null,"decision_at":null,"decision_note":null,"executed_at":null,"execution_error":null,"expires_at":"2026-10-20T09:00:00.000-04:00","created_at":"2026-10-19T09:00:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/approvals/{approval_id}/cancel":{"post":{"operationId":"cancelApproval","summary":"Withdraw your pending request","description":"Withdraws a still-pending request made by this key’s creator.","tags":["Approvals"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:status","write:budgets","write:bids","write:clone","write:create","write:delete","write:automation"],"x-minimum-role":"viewer","parameters":[{"name":"approval_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Withdrawn.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"approval_status":{"type":["string","null"]}}},"example":{"status":"completed","approval_status":"rejected"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/event-types":{"get":{"operationId":"listWebhookEventTypes","summary":"List webhook event types","description":"Every event you can subscribe to, with what triggers it.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:webhooks"],"x-minimum-role":"viewer","responses":{"200":{"description":"Event catalog.","content":{"application/json":{"schema":{"type":"object","properties":{"event_types":{"type":"array","items":{"type":"object","properties":{"type":{"type":["string","null"]},"description":{"type":["string","null"]}}}}}},"example":{"event_types":[{"type":"test.verdict.winner","description":"A page-test variant reached a winning verdict."}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/endpoints":{"get":{"operationId":"listWebhookEndpoints","summary":"List webhook endpoints","description":"Configured endpoints (secrets are never returned).\n\nDeliveries are signed with the Standard Webhooks scheme (`webhook-id`, `webhook-timestamp`, `webhook-signature` headers; HMAC-SHA256 with your `whsec_…` secret). Retries back off up to 6 times; an endpoint is disabled after 20 consecutive failures.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:webhooks"],"x-minimum-role":"admin","responses":{"200":{"description":"Endpoints.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoints":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"url":{"type":["string","null"]},"events":{"type":"array","items":{"type":["string","null"]}},"description":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"consecutive_failures":{"type":["number","null"]},"disabled_reason":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]}}}}}},"example":{"endpoints":[{"id":"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","url":"https://example.com/hooks/roas","events":["*"],"description":"Prod receiver","is_active":true,"consecutive_failures":0,"disabled_reason":null,"created_at":"2026-10-01T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createWebhookEndpoint","summary":"Create a webhook endpoint","description":"Registers an https URL. The response includes the signing `secret`. It is shown only once, so store it. Up to 5 endpoints per workspace.\n\nDeliveries are signed with the Standard Webhooks scheme (`webhook-id`, `webhook-timestamp`, `webhook-signature` headers; HMAC-SHA256 with your `whsec_…` secret). Retries back off up to 6 times; an endpoint is disabled after 20 consecutive failures.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:webhooks"],"x-minimum-role":"admin","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"minItems":1,"maxItems":15,"type":"array","items":{"anyOf":[{"type":"string","const":"*"},{"type":"string","enum":["test.variant.promoted","test.variant.paused","test.verdict.winner","test.verdict.futility","test.variant.created","snippet.went_dark","launch.completed","launch.failed","clone.completed","clone.failed","automation.action_executed","conversion.recorded","account.access_lost","budget_alert.created"]}]},"description":"Event types to receive, or ['*'] for all."},"description":{"type":"string","maxLength":200},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["url","events"]}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"url":{"type":["string","null"]},"events":{"type":"array","items":{"type":["string","null"]}},"description":{"type":["string","null"]},"is_active":{"type":["boolean","null"]},"consecutive_failures":{"type":["number","null"]},"disabled_reason":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]},"secret":{"type":["string","null"]}}},"example":{"id":"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","url":"https://example.com/hooks/roas","events":["*"],"description":"Prod receiver","is_active":true,"consecutive_failures":0,"disabled_reason":null,"created_at":"2026-10-01T10:00:00.000-04:00","secret":"whsec_Zm9vYmFyYmF6cXV4Li4u"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/endpoints/{endpoint_id}":{"patch":{"operationId":"updateWebhookEndpoint","summary":"Update a webhook endpoint","description":"Enable / disable, change subscribed events, or edit the description. Re-enabling resets the failure count.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:webhooks"],"x-minimum-role":"admin","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"is_active":{"type":"boolean"},"events":{"minItems":1,"maxItems":15,"type":"array","items":{"anyOf":[{"type":"string","const":"*"},{"type":"string","enum":["test.variant.promoted","test.variant.paused","test.verdict.winner","test.verdict.futility","test.variant.created","snippet.went_dark","launch.completed","launch.failed","clone.completed","clone.failed","automation.action_executed","conversion.recorded","account.access_lost","budget_alert.created"]}]},"description":"Event types to receive, or ['*'] for all."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]}}},"example":{"status":"completed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteWebhookEndpoint","summary":"Delete a webhook endpoint","description":"Stops deliveries to the endpoint. Requires `?confirm=true`.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:webhooks"],"x-minimum-role":"admin","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"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)$"}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]}}},"example":{"status":"completed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/endpoints/{endpoint_id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate a signing secret","description":"Issues a new signing secret (returned once). The old secret stops verifying immediately.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:webhooks"],"x-minimum-role":"admin","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Rotated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"secret":{"type":["string","null"]}}},"example":{"status":"completed","secret":"whsec_bmV3c2VjcmV0Li4u"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/endpoints/{endpoint_id}/test":{"post":{"operationId":"sendWebhookTest","summary":"Send a test event","description":"Sends a real, signed `webhook.test` event through the delivery pipeline to this endpoint only. If your receiver verifies this, it verifies production events.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:webhooks"],"x-minimum-role":"admin","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"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)$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"event_id":{"type":["string","null"]}}},"example":{"status":"queued","event_id":"evt_3f1e2d3c-4b5a-4968-8776-655443322110"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/webhooks/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"List webhook deliveries","description":"Delivery attempts, newest first, with status and the receiver’s last HTTP status.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:webhooks"],"x-minimum-role":"admin","parameters":[{"name":"endpoint_id","in":"query","required":false,"schema":{"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)$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","delivered","failed"]}},{"name":"event_type","in":"query","required":false,"schema":{"type":"string","maxLength":60}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Deliveries.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"deliveries":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"endpoint_id":{"type":["string","null"]},"event_id":{"type":["string","null"]},"event_type":{"type":["string","null"]},"status":{"type":["string","null"]},"attempts":{"type":["number","null"]},"last_response_status":{"type":["number","null"]},"last_attempt_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"deliveries":[{"id":"8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e","endpoint_id":"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","event_id":"evt_3f1e2d3c-4b5a-4968-8776-655443322110","event_type":"test.verdict.winner","status":"delivered","attempts":1,"last_response_status":200,"last_attempt_at":"2026-10-19T09:00:02.000-04:00","created_at":"2026-10-19T09:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/events":{"get":{"operationId":"listWebhookEventsLegacy","summary":"Recent webhook deliveries (legacy)","description":"Recent deliveries, newest first (50 by default). Superseded by GET /v1/webhooks/deliveries.","tags":["Webhooks"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:webhooks"],"x-minimum-role":"admin","deprecated":true,"parameters":[{"name":"limit","in":"query","required":false,"description":"Rows per page (1–100).","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Deliveries.","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":["string","null"]},"event_type":{"type":["string","null"]},"delivery_status":{"type":["string","null"]},"attempts":{"type":["number","null"]},"last_response_status":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"events":[{"event_id":"evt_3f1e2d3c-4b5a-4968-8776-655443322110","event_type":"test.verdict.winner","delivery_status":"delivered","attempts":1,"last_response_status":200,"created_at":"2026-10-19T09:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests":{"get":{"operationId":"listTests","summary":"List page tests","description":"Every page test in the workspace, newest first, with install health.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"limit","in":"query","required":false,"description":"Rows per page (1–100).","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Page of tests.","content":{"application/json":{"schema":{"type":"object","properties":{"tests":{"type":"array","items":{"type":"object","properties":{"page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"url":{"type":["string","null"]},"variant_count":{"type":["number","null"]},"active_variant_count":{"type":["number","null"]},"status":{"type":["string","null"]},"split_mode":{"type":["string","null"]},"auto_generation_enabled":{"type":["boolean","null"]},"target_test_count":{"type":["number","null"]},"baseline_traffic_pct":{"type":["number","null"]},"health":{"type":"object","properties":{"install_state":{"type":["string","null"]},"checked_at":{"type":["string","null"]},"last_seen_traffic_at":{"type":["string","null"]}}},"created_at":{"type":["string","null"]}}}},"pagination":{"type":"object","properties":{"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"returned":{"type":["number","null"]},"total":{"type":["number","null"]},"has_more":{"type":["boolean","null"]}}}}},"example":{"tests":[{"page_id":"keto-advertorial","name":"Keto advertorial","url":"https://example.com/keto","variant_count":3,"active_variant_count":3,"status":"active","split_mode":"auto","auto_generation_enabled":true,"target_test_count":2,"baseline_traffic_pct":60,"health":{"install_state":"installed","checked_at":"2026-10-19T08:00:00.000-04:00","last_seen_traffic_at":"2026-10-19T08:59:00.000-04:00"},"created_at":"2026-09-01T10:00:00.000-04:00"}],"pagination":{"limit":20,"offset":0,"returned":1,"total":1,"has_more":false}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createTest","summary":"Create a page test","description":"Creates a test on your page with its baseline (the page as-is, plus any `modifications`). Add challengers with `POST /v1/tests/{page_id}/variants`, install the snippet from `GET /v1/tests/{page_id}/install`.\n\n`tracking.mode`:\n- `redirect` (default): links matched by `tracking.linkTargeting` are tracked; `redirectAction: 'append'` keeps each link's own destination, `'replace'` sends them to `direct_affiliate_link`.\n- `passthrough`: links are untouched; conversions attribute through your on-site pixel.\n\nThe `page_id` is normalized (lowercase, a–z 0–9 -) and suffixed if another workspace already uses it. Always use the returned `page_id`.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":"string","minLength":1,"maxLength":200},"page_name":{"type":"string","minLength":1},"original_url":{"type":"string","format":"uri"},"product_id":{"type":["string","null"]},"traffic_source_id":{"type":["string","null"]},"direct_affiliate_link":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"modifications":{"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"action":{"type":"string","enum":["replace_text","replace_html","replace_attribute","hide","show","add_class","remove_class","set_style","inject_css","move_element"]},"value":{"type":"string","maxLength":50000},"attribute":{"type":"string","maxLength":100},"position":{"type":"string","enum":["before","after","prepend","append"]},"conditions":{},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000},"textHash":{"type":"string","maxLength":200}}}},"required":["selector","action"]}},"tracking":{"type":"object","properties":{"mode":{"default":"redirect","type":"string","enum":["redirect","passthrough"]},"linkTargeting":{"type":"object","properties":{"matchers":{"maxItems":25,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"href_contains"},"value":{"type":"string","minLength":1,"maxLength":300}},"required":["type","value"]},{"type":"object","properties":{"type":{"type":"string","const":"text_contains"},"value":{"type":"string","minLength":1,"maxLength":300}},"required":["type","value"]},{"type":"object","properties":{"type":{"type":"string","const":"element"},"selector":{"type":"string","minLength":1,"maxLength":500},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000}}},"href":{"type":"string","maxLength":2000}},"required":["type","selector"]}]}},"exceptions":{"maxItems":50,"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000}}}},"required":["selector"]}},"redirectAction":{"default":"append","type":"string","enum":["append","replace"]}},"required":["matchers"]}},"required":["linkTargeting"]},"detected_elements":{},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["page_id","page_name","original_url","modifications","tracking"]}}}},"responses":{"201":{"description":"Created and deployed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"page_id":{"type":["string","null"]},"public_id":{"type":["string","null"]},"snippet_url":{"type":["string","null"]}}},"example":{"status":"completed","page_id":"keto-advertorial","public_id":"p_8Hc2kQ","snippet_url":"https://t.example.com/l/p_8Hc2kQ"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}":{"get":{"operationId":"getTest","summary":"Get a page test","description":"One test with all of its variants (including paused and archived).","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"The test.","content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":["string","null"]},"name":{"type":["string","null"]},"url":{"type":["string","null"]},"variant_count":{"type":["number","null"]},"active_variant_count":{"type":["number","null"]},"status":{"type":["string","null"]},"split_mode":{"type":["string","null"]},"auto_generation_enabled":{"type":["boolean","null"]},"target_test_count":{"type":["number","null"]},"baseline_traffic_pct":{"type":["number","null"]},"health":{"type":"object","properties":{"install_state":{"type":["string","null"]},"checked_at":{"type":["string","null"]},"last_seen_traffic_at":{"type":["string","null"]}}},"created_at":{"type":["string","null"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"is_baseline":{"type":["boolean","null"]},"status":{"type":["string","null"]},"stage":{"type":["string","null"]},"traffic_pct":{"type":["number","null"]},"hypothesis":{"type":["string","null"]},"generation_method":{"type":["string","null"]},"changes_description":{"type":["string","null"]},"test_started_at":{"type":["string","null"]},"promoted_at":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]}}}}}},"example":{"page_id":"keto-advertorial","name":"Keto advertorial","url":"https://example.com/keto","variant_count":3,"active_variant_count":3,"status":"active","split_mode":"auto","auto_generation_enabled":true,"target_test_count":2,"baseline_traffic_pct":60,"health":{"install_state":"installed","checked_at":"2026-10-19T08:00:00.000-04:00","last_seen_traffic_at":"2026-10-19T08:59:00.000-04:00"},"created_at":"2026-09-01T10:00:00.000-04:00","variants":[{"id":"2f1d7c8e-0a4b-4e5f-9a1b-3c4d5e6f7a8b","variant_id":"v2","is_baseline":false,"status":"active","stage":"growing","traffic_pct":20,"hypothesis":"Benefit-led headline beats feature-led","generation_method":"ai","changes_description":"Headline rewritten around the main benefit","test_started_at":"2026-10-12T09:00:00.000-04:00","promoted_at":null,"created_at":"2026-10-12T08:55:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateTest","summary":"Edit the baseline","description":"Replace the baseline's `modifications` and/or notes. Deployed to the edge immediately.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"modifications":{"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"action":{"type":"string","enum":["replace_text","replace_html","replace_attribute","hide","show","add_class","remove_class","set_style","inject_css","move_element"]},"value":{"type":"string","maxLength":50000},"attribute":{"type":"string","maxLength":100},"position":{"type":"string","enum":["before","after","prepend","append"]},"conditions":{},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000},"textHash":{"type":"string","maxLength":200}}}},"required":["selector","action"]}},"notes":{"type":"string","maxLength":2000},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteTest","summary":"Delete a test permanently","description":"Deletes the test, its variants, and its recorded views, clicks, and conversions. Cannot be undone; prefer archive. Requires `?confirm=true` and the admin role.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"admin","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"cleaned"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/results":{"get":{"operationId":"getTestResults","summary":"Get test results + verdict","description":"Per-variant lifetime and evaluation-window stats (views, clicks, conversions, revenue, revenue per view) plus the full Bayesian verdict the optimizer acts on: probability each variant beats the baseline on revenue per view, the practical-equivalence (futility) mass, a 90% credible interval on lift, a winner / loser / equivalent / collecting classification, and a distance-to-decision forecast.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"Results.","content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":["string","null"]},"eval_started_at":{"type":["string","null"]},"verdict":{"type":"object","properties":{"status":{"type":["string","null"]},"leader_variant_id":{"type":["string","null"]},"confidence":{"type":["number","null"]},"forecast":{"type":"object","properties":{"direction":{"type":["string","null"]},"additional_views":{"type":["number","null"]},"additional_days":{"type":["number","null"]}}}}},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"is_baseline":{"type":["boolean","null"]},"status":{"type":["string","null"]},"stage":{"type":["string","null"]},"traffic_pct":{"type":["number","null"]},"hypothesis":{"type":["string","null"]},"generation_method":{"type":["string","null"]},"changes_description":{"type":["string","null"]},"test_started_at":{"type":["string","null"]},"promoted_at":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]},"lifetime":{"type":"object","properties":{"views":{"type":["number","null"]},"clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue_usd":{"type":["number","null"]},"epv_usd":{"type":["number","null"]}}},"evaluation":{"type":"object","properties":{"views":{"type":["number","null"]},"clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue_usd":{"type":["number","null"]},"epv_usd":{"type":["number","null"]}}},"confidence":{"type":["number","null"]},"classification":{"type":["string","null"]},"comparison":{"type":"object","properties":{"p_beat_baseline":{"type":["number","null"]},"p_within_margin":{"type":["number","null"]},"p_practical_win":{"type":["number","null"]},"lift_median":{"type":["number","null"]},"lift_q05":{"type":["number","null"]},"lift_q95":{"type":["number","null"]}}}}}}}},"example":{"page_id":"keto-advertorial","eval_started_at":"2026-10-12T09:00:00.000-04:00","verdict":{"status":"collecting","leader_variant_id":"v2","confidence":0.83,"forecast":{"direction":"winner","additional_views":2400,"additional_days":3.1}},"variants":[{"id":"2f1d7c8e-0a4b-4e5f-9a1b-3c4d5e6f7a8b","variant_id":"v2","is_baseline":false,"status":"active","stage":"growing","traffic_pct":20,"hypothesis":"Benefit-led headline beats feature-led","generation_method":"ai","changes_description":"Headline rewritten around the main benefit","test_started_at":"2026-10-12T09:00:00.000-04:00","promoted_at":null,"created_at":"2026-10-12T08:55:00.000-04:00","lifetime":{"views":5120,"clicks":1490,"conversions":61,"revenue_usd":2745,"epv_usd":0.5361},"evaluation":{"views":4012,"clicks":1170,"conversions":49,"revenue_usd":2205,"epv_usd":0.5496},"confidence":0.83,"classification":"collecting","comparison":{"p_beat_baseline":0.83,"p_within_margin":0.11,"p_practical_win":0.71,"lift_median":0.14,"lift_q05":-0.04,"lift_q95":0.33}}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/settings":{"get":{"operationId":"getTestSettings","summary":"Get test automation settings","description":"Traffic split mode, baseline share, auto-generation, auto-promote / auto-pause / auto-cull, decision thresholds, and holdout. Unset thresholds (null) use the workspace defaults.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"Settings.","content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":["string","null"]},"split_mode":{"type":["string","null"]},"baseline_traffic_pct":{"type":["number","null"]},"target_test_count":{"type":["number","null"]},"auto_generation_enabled":{"type":["boolean","null"]},"auto_promote_enabled":{"type":["boolean","null"]},"auto_pause_enabled":{"type":["boolean","null"]},"auto_cull_enabled":{"type":["boolean","null"]},"min_views_for_promotion":{"type":["null","string","number","object"]},"min_views_for_eval":{"type":["null","string","number","object"]},"weak_loser_views":{"type":["null","string","number","object"]},"weak_loser_threshold":{"type":["null","string","number","object"]},"promotion_confidence":{"type":["null","string","number","object"]},"pause_threshold":{"type":["null","string","number","object"]},"holdout_enabled":{"type":["boolean","null"]},"holdout_percentage":{"type":["number","null"]}}},"example":{"page_id":"keto-advertorial","split_mode":"auto","baseline_traffic_pct":60,"target_test_count":2,"auto_generation_enabled":true,"auto_promote_enabled":true,"auto_pause_enabled":true,"auto_cull_enabled":false,"min_views_for_promotion":null,"min_views_for_eval":null,"weak_loser_views":null,"weak_loser_threshold":null,"promotion_confidence":null,"pause_threshold":null,"holdout_enabled":false,"holdout_percentage":500}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateTestSettings","summary":"Edit test automation settings","description":"Pass only the fields to change; `null` resets a threshold to the workspace default.\n\n- `split_mode: 'manual'` stops the optimizer from moving traffic, promoting, or pausing on this page.\n- `auto_generation_enabled` + `target_test_count`: keep N AI challengers running.\n- Thresholds: `promotion_confidence` (0.85–1), `pause_threshold` (0.1–0.85), `weak_loser_threshold` (0.1–0.6, ≤ pause_threshold), view minimums (50–100000).","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"split_mode":{"type":"string","enum":["auto","manual"]},"baseline_traffic_pct":{"type":"number","minimum":0,"maximum":100},"target_test_count":{"type":"integer","minimum":0,"maximum":20},"auto_generation_enabled":{"type":"boolean"},"auto_promote_enabled":{"type":"boolean"},"auto_pause_enabled":{"type":"boolean"},"auto_cull_enabled":{"type":"boolean"},"holdout_enabled":{"type":"boolean"},"holdout_percentage":{"description":"Holdout share in basis points (500 = 5%).","type":"integer","minimum":0,"maximum":5000},"min_views_for_promotion":{"anyOf":[{"type":"integer","minimum":50,"maximum":100000},{"type":"null"}]},"min_views_for_eval":{"anyOf":[{"type":"integer","minimum":50,"maximum":100000},{"type":"null"}]},"weak_loser_views":{"anyOf":[{"type":"integer","minimum":50,"maximum":100000},{"type":"null"}]},"weak_loser_threshold":{"anyOf":[{"type":"number","minimum":0.1,"maximum":0.6},{"type":"null"}]},"promotion_confidence":{"anyOf":[{"type":"number","minimum":0.85,"maximum":1},{"type":"null"}]},"pause_threshold":{"anyOf":[{"type":"number","minimum":0.1,"maximum":0.85},{"type":"null"}]},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/tracking":{"patch":{"operationId":"updateTestTracking","summary":"Edit link tracking","description":"Change how the test's links are tracked, for every active variant: tracking mode, link targeting rules, the replace-destination URL, and stamp timing (`click` = links stay static until a real click; `render` = stamped on page load).","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["redirect","passthrough"]},"link_targeting":{"type":"object","properties":{"matchers":{"maxItems":25,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"href_contains"},"value":{"type":"string","minLength":1,"maxLength":300}},"required":["type","value"]},{"type":"object","properties":{"type":{"type":"string","const":"text_contains"},"value":{"type":"string","minLength":1,"maxLength":300}},"required":["type","value"]},{"type":"object","properties":{"type":{"type":"string","const":"element"},"selector":{"type":"string","minLength":1,"maxLength":500},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000}}},"href":{"type":"string","maxLength":2000}},"required":["type","selector"]}]}},"exceptions":{"maxItems":50,"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000}}}},"required":["selector"]}},"redirectAction":{"default":"append","type":"string","enum":["append","replace"]}},"required":["matchers"]},"direct_affiliate_link":{"description":"Replace-destination URL. Omit to keep the current one; null clears it.","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"stamp_timing":{"type":"string","enum":["render","click"]},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"updated":{"type":["number","null"]}}},"example":{"status":"completed","kv":"deployed","updated":3}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/install":{"get":{"operationId":"getInstallCode","summary":"Get the install snippet","description":"The `<script>` tag to paste into the page's `<head>`. It's served from your custom tracking domain (first-party).","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"Install code.","content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":["string","null"]},"public_id":{"type":["string","null"]},"snippet_url":{"type":["string","null"]},"html":{"type":["string","null"]}}},"example":{"page_id":"keto-advertorial","public_id":"p_8Hc2kQ","snippet_url":"https://t.example.com/l/p_8Hc2kQ","html":"<script>…</script>"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/archive":{"post":{"operationId":"archiveTest","summary":"Archive a test","description":"Stops the test and removes it from the edge (the page renders untouched). Data is kept.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Archived.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"cleaned"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/unarchive":{"post":{"operationId":"unarchiveTest","summary":"Restore an archived test","description":"Restores the latest baseline at 100%; other variants come back paused.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Restored.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"restored":{"type":["string","null"]},"variants":{"type":["number","null"]}}},"example":{"status":"completed","kv":"deployed","restored":"baseline","variants":3}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/split":{"put":{"operationId":"setTrafficSplit","summary":"Set the traffic split","description":"- `mode: 'manual'` + `allocations`: pin exact shares for the listed variants (the rest share the remainder). The optimizer stops moving traffic.\n- `mode: 'even'`: split evenly across active variants, manual mode.\n- `mode: 'auto'`: hand traffic back to the optimizer.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["auto","manual","even"]},"allocations":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"variant_id":{"type":"string","minLength":1,"maxLength":50,"description":"Variant id within a test."},"traffic_pct":{"type":"number","minimum":0,"maximum":100}},"required":["variant_id","traffic_pct"]}},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["mode"]}}}},"responses":{"200":{"description":"Applied.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"split_mode":{"type":["string","null"]},"split":{"type":"object","properties":{"baseline":{"type":["number","null"]},"v2":{"type":["number","null"]},"v3":{"type":["number","null"]}}}}},"example":{"status":"completed","kv":"deployed","split_mode":"manual","split":{"baseline":50,"v2":30,"v3":20}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/evaluation/restart":{"post":{"operationId":"restartEvaluation","summary":"Restart the evaluation window","description":"Starts a fresh evaluation window for every active variant (e.g. after you changed the offer). Lifetime stats are kept; the verdict only counts data from now on.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Restarted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"variants":{"type":"array","items":{"type":["string","null"]}},"started_at":{"type":["string","null"]}}},"example":{"status":"completed","variants":["baseline","v2"],"started_at":"2026-10-19T09:00:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/deploy":{"post":{"operationId":"deployTest","summary":"Force a redeploy to the edge","description":"Re-publishes the current test config to the edge. Normally automatic.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Deployed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/selector-health":{"get":{"operationId":"getSelectorHealth","summary":"Get selector health","description":"Selector-drift telemetry reported by the snippet: which CSS selectors stopped matching on the live page (e.g. after a site redesign) and how often they recovered.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"Selector telemetry.","content":{"application/json":{"schema":{"type":"object","properties":{"page_id":{"type":["string","null"]},"selectors":{"type":"array","items":{"type":"object","properties":{"variant_id":{"type":["string","null"]},"selector":{"type":["string","null"]},"last_status":{"type":["string","null"]},"recovery_count":{"type":["number","null"]},"failure_count":{"type":["number","null"]},"first_seen_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}},"example":{"page_id":"keto-advertorial","selectors":[{"variant_id":"v2","selector":"h1.headline","last_status":"ok","recovery_count":1,"failure_count":3,"first_seen_at":"2026-10-12T09:00:00.000-04:00","last_seen_at":"2026-10-19T08:59:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/variants":{"post":{"operationId":"createVariant","summary":"Add a variant","description":"Adds a challenger. It starts active as a seedling with a small traffic share and the evaluation clock starts automatically. Omit `modifications` to start from the baseline's. `variant_id` defaults to the next `vN`.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant_id":{"type":"string","pattern":"^[a-z0-9_-]{1,50}$"},"modifications":{"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"action":{"type":"string","enum":["replace_text","replace_html","replace_attribute","hide","show","add_class","remove_class","set_style","inject_css","move_element"]},"value":{"type":"string","maxLength":50000},"attribute":{"type":"string","maxLength":100},"position":{"type":"string","enum":["before","after","prepend","append"]},"conditions":{},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000},"textHash":{"type":"string","maxLength":200}}}},"required":["selector","action"]}},"changes_description":{"type":"string","maxLength":2000},"hypothesis":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":2000},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"201":{"description":"Created and deployed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"variant_id":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","variant_id":"v3"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/variants/{variant_id}":{"get":{"operationId":"getVariant","summary":"Get a variant","description":"One variant of a page test.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"description":"Variant id within a test.","schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"The variant.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"is_baseline":{"type":["boolean","null"]},"status":{"type":["string","null"]},"stage":{"type":["string","null"]},"traffic_pct":{"type":["number","null"]},"hypothesis":{"type":["string","null"]},"generation_method":{"type":["string","null"]},"changes_description":{"type":["string","null"]},"test_started_at":{"type":["string","null"]},"promoted_at":{"type":["null","string","number","object"]},"created_at":{"type":["string","null"]}}},"example":{"id":"2f1d7c8e-0a4b-4e5f-9a1b-3c4d5e6f7a8b","variant_id":"v2","is_baseline":false,"status":"active","stage":"growing","traffic_pct":20,"hypothesis":"Benefit-led headline beats feature-led","generation_method":"ai","changes_description":"Headline rewritten around the main benefit","test_started_at":"2026-10-12T09:00:00.000-04:00","promoted_at":null,"created_at":"2026-10-12T08:55:00.000-04:00"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateVariant","summary":"Edit, pause, or resume a variant","description":"`status: 'paused'` stops serving it (its traffic is redistributed); `status: 'active'` resumes a paused variant. You can also replace its `modifications`, `hypothesis`, or `notes`. The baseline's status can't be changed; promote a variant instead.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"description":"Variant id within a test.","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused"]},"modifications":{"type":"array","items":{"type":"object","properties":{"selector":{"type":"string","minLength":1,"maxLength":500},"action":{"type":"string","enum":["replace_text","replace_html","replace_attribute","hide","show","add_class","remove_class","set_style","inject_css","move_element"]},"value":{"type":"string","maxLength":50000},"attribute":{"type":"string","maxLength":100},"position":{"type":"string","enum":["before","after","prepend","append"]},"conditions":{},"fingerprint":{"type":"object","properties":{"tagName":{"type":"string","maxLength":20},"innerTextPreview":{"type":"string","maxLength":300},"positionIndex":{"type":"integer","minimum":0,"maximum":100000},"textHash":{"type":"string","maxLength":200}}}},"required":["selector","action"]}},"hypothesis":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":2000},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"variant_status":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","variant_id":"v2","variant_status":"paused"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"archiveVariant","summary":"Archive a variant","description":"Retires a variant (kept for history). The baseline cannot be archived.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"description":"Variant id within a test.","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Archived.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/tests/{page_id}/variants/{variant_id}/promote":{"post":{"operationId":"promoteVariant","summary":"Promote a variant to baseline","description":"Makes the variant the new baseline (the old baseline is archived) at the page's baseline traffic share. Use it when you've seen enough. The optimizer does this automatically when auto-promote is on.","tags":["Page tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"page_id","in":"path","required":true,"description":"Page test id (the page_id slug).","schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"description":"Variant id within a test.","schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Promoted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"promoted":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","promoted":"v2"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests":{"get":{"operationId":"listLinkTests","summary":"List link tests","description":"Link tests with their public tracking `link_url` (use it as the ad destination).","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"status","in":"query","required":false,"schema":{"default":"active","type":"string","enum":["active","archived","all"]}},{"name":"limit","in":"query","required":false,"description":"Rows per page (1–1000, default 100).","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}},{"name":"offset","in":"query","required":false,"description":"Rows to skip.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Link tests.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":["number","null"]},"limit":{"type":["number","null"]},"offset":{"type":["number","null"]},"has_more":{"type":["boolean","null"]},"link_tests":{"type":"array","items":{"type":"object","properties":{"group_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"link_url":{"type":["string","null"]},"baseline_url":{"type":["string","null"]},"baseline_traffic_pct":{"type":["number","null"]},"auto_promote_enabled":{"type":["boolean","null"]},"auto_pause_enabled":{"type":["boolean","null"]},"variant_count":{"type":["number","null"]},"created_at":{"type":["string","null"]}}}}}},"example":{"total":1,"limit":100,"offset":0,"has_more":false,"link_tests":[{"group_id":"keto-split","name":"Keto split","status":"active","link_url":"https://go.example.com/link/keto-split","baseline_url":"https://example.com/offer-a","baseline_traffic_pct":60,"auto_promote_enabled":true,"auto_pause_enabled":true,"variant_count":3,"created_at":"2026-09-15T10:00:00.000-04:00"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"createLinkTest","summary":"Create a link test","description":"Creates a link test with a baseline destination and optional challengers, splits traffic (`baseline_traffic_pct` to the baseline, the rest evenly), and deploys it. Returns the tracking `link_url`. `kv: \"deploy_failed\"` means the test was created but not yet published — call POST …/deploy. `id` becomes part of the URL and must be unique across ROAS.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":50,"pattern":"^[a-zA-Z0-9_-]+$"},"name":{"type":"string","minLength":1},"source_network":{"type":"string"},"baseline_url":{"type":"string","format":"uri"},"baseline_destination_type":{"type":"string","minLength":1},"baseline_destination_id":{"type":"string"},"baseline_traffic_pct":{"default":60,"type":"number","minimum":1,"maximum":100},"auto_promote_enabled":{"default":false,"type":"boolean"},"auto_pause_enabled":{"default":false,"type":"boolean"},"target_test_count":{"default":3,"type":"integer","minimum":1,"maximum":9007199254740991},"test_variants":{"default":[],"type":"array","items":{"type":"object","properties":{"destination_url":{"type":"string","format":"uri"},"destination_type":{"type":"string","minLength":1},"destination_id":{"type":"string"}},"required":["destination_url","destination_type"]}},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["id","name","baseline_url","baseline_destination_type"]}}}},"responses":{"201":{"description":"Created and deployed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"group_id":{"type":["string","null"]},"link_url":{"type":["string","null"]},"variants_created":{"type":["number","null"]},"traffic_split":{"type":"object","properties":{"baseline":{"type":["number","null"]},"per_test":{"type":["number","null"]}}}}},"example":{"status":"completed","kv":"deployed","group_id":"keto-split","link_url":"https://go.example.com/link/keto-split","variants_created":3,"traffic_split":{"baseline":60,"per_test":20}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}":{"get":{"operationId":"getLinkTest","summary":"Get a link test with results","description":"The link test plus every variant with traffic share and performance: views, clicks, conversions, revenue, EPC, EPV, and the confidence (0–100) that it earns more per visitor than the baseline.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["read:snippets"],"x-minimum-role":"viewer","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}}],"responses":{"200":{"description":"Link test.","content":{"application/json":{"schema":{"type":"object","properties":{"group_id":{"type":["string","null"]},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"link_url":{"type":["string","null"]},"baseline_url":{"type":["string","null"]},"baseline_traffic_pct":{"type":["number","null"]},"auto_promote_enabled":{"type":["boolean","null"]},"auto_pause_enabled":{"type":["boolean","null"]},"variant_count":{"type":["number","null"]},"created_at":{"type":["string","null"]},"variants":{"type":"array","items":{"type":"object","properties":{"variant_id":{"type":["string","null"]},"destination":{"type":"object","properties":{"url":{"type":["string","null"]},"type":{"type":["string","null"]},"id":{"type":["null","string","number","object"]}}},"status":{"type":["string","null"]},"stage":{"type":["string","null"]},"traffic_pct":{"type":["number","null"]},"hypothesis":{"type":["string","null"]},"performance":{"type":"object","properties":{"views":{"type":["number","null"]},"clicks":{"type":["number","null"]},"conversions":{"type":["number","null"]},"revenue":{"type":["number","null"]},"epc":{"type":["number","null"]},"epv":{"type":["number","null"]},"ctr":{"type":["number","null"]},"cvr":{"type":["number","null"]},"confidence_vs_baseline":{"type":["number","null"]}}}}}},"promotions":{"type":"array","items":{}}}},"example":{"group_id":"keto-split","name":"Keto split","status":"active","link_url":"https://go.example.com/link/keto-split","baseline_url":"https://example.com/offer-a","baseline_traffic_pct":60,"auto_promote_enabled":true,"auto_pause_enabled":true,"variant_count":3,"created_at":"2026-09-15T10:00:00.000-04:00","variants":[{"variant_id":"test_1","destination":{"url":"https://example.com/offer-b","type":"offer","id":null},"status":"active","stage":"growing","traffic_pct":20,"hypothesis":"Shorter checkout wins","performance":{"views":4012,"clicks":1170,"conversions":49,"revenue":2205,"epc":1.88,"epv":0.55,"ctr":29.2,"cvr":4.19,"confidence_vs_baseline":81.4}}],"promotions":[]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteLinkTest","summary":"Delete a link test permanently","description":"Deletes the test and its tracking data. The link stops working. Requires `?confirm=true` and the admin role.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"admin","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"confirm","in":"query","required":true,"description":"Must be \"true\". Guards against accidental deletes.","schema":{"type":"string","const":"true"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"cleaned"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/archive":{"post":{"operationId":"archiveLinkTest","summary":"Archive a link test","description":"Stops the test and removes it from the edge. Data is kept.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Archived.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"cleaned"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/unarchive":{"post":{"operationId":"unarchiveLinkTest","summary":"Restore an archived link test","description":"Restores the test and redeploys it.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Restored.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/deploy":{"post":{"operationId":"deployLinkTest","summary":"Force a redeploy to the edge","description":"Re-publishes the current split to the edge. Normally automatic.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Deployed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/variants":{"post":{"operationId":"addLinkVariant","summary":"Add a destination","description":"Adds a challenger destination (starts as a seedling with a small share).","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination_url":{"type":"string","format":"uri"},"destination_type":{"default":"url","type":"string","minLength":1,"maxLength":40},"destination_id":{"type":"string","maxLength":100},"hypothesis":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":2000},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}},"required":["destination_url"]}}}},"responses":{"201":{"description":"Added.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"variant_id":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","variant_id":"test_3"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/variants/{variant_id}":{"patch":{"operationId":"updateLinkVariant","summary":"Edit, pause, or resume a destination","description":"`status: 'paused' | 'active'` stops / resumes a challenger (the baseline can't be paused; promote a destination instead). You can also change the destination URL, hypothesis, or notes.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused"]},"destination_url":{"type":"string","format":"uri"},"hypothesis":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":2000},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"variant_id":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","variant_id":"test_1"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"archiveLinkVariant","summary":"Archive a destination","description":"Retires a challenger destination (kept for history).","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Archived.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/link-tests/{group_id}/variants/{variant_id}/promote":{"post":{"operationId":"promoteLinkVariant","summary":"Promote a destination","description":"`mode: 'promote'` (default) makes it the new baseline at the test's baseline share and keeps testing; `mode: 'winner'` sends 100% of traffic to it and pauses the rest.","tags":["Link tests"],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"x-required-scope":["write:snippets"],"x-minimum-role":"editor","parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":50}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"default":"promote","type":"string","enum":["promote","winner"]},"created_by":{"description":"Free-text attribution (your script, agent, or person). Recorded in the workspace audit log next to the API key.","type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"200":{"description":"Promoted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":["string","null"]},"kv":{"type":["string","null"]},"promoted":{"type":["string","null"]},"lift_pct":{"type":["string","null"]}}},"example":{"status":"completed","kv":"deployed","promoted":"test_1","lift_pct":"14.2"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer roas_… (mint keys in Settings → API Keys)."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key"}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional unique key (1–200 chars). A retry with the same key and same request returns the original response (header Idempotent-Replay: true) instead of acting twice. Keys live 24 hours.","schema":{"type":"string","minLength":1,"maxLength":200}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","not_found","invalid_request","conflict","unprocessable","rate_limit_exceeded","upstream_error","internal_error","service_unavailable"]},"message":{"type":"string"},"problems":{"type":"array","description":"Every validation problem (invalid_request only).","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}}}}},"responses":{"InvalidRequest":{"description":"The request failed validation. `problems` lists every issue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, invalid, expired, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks the required scope, its creator's role is too low, or the ad account is outside the creator's access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests. Retry after the Retry-After header (seconds).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"x-scopes":{"read:campaigns":"Read ad accounts, campaigns, ad sets, ads, creatives, launch history, audiences, pixels, pages, and media.","read:analytics":"Read performance analytics: daily, hourly, funnel, placements, profitability, account health, and data freshness.","read:conversions":"Read attributed conversions and offer performance.","read:snippets":"Read page tests, link tests, and landing-page experiments — including verdicts, beat-baseline confidence, snippet health, and selector drift.","read:automation":"Read automation, clone, and auto-boost rules, their execution history, budget alerts, and pending approvals.","write:status":"Pause and activate campaigns, ad sets, and ads.","write:budgets":"Scale or set campaign and ad set budgets.","write:bids":"Update bid amounts where supported.","write:clone":"Duplicate campaigns (with optional overrides).","write:create":"Launch campaigns, ad sets, and ads from scratch, edit schedules and names, and upload media.","write:delete":"Delete or archive campaigns, ad sets, and ads.","write:automation":"Create, edit, assign, delete, and pause/resume automation, clone, and auto-boost rules.","write:snippets":"Create and manage page tests and link tests: variants, traffic split, promotion, settings, and archiving.","write:conversions":"Send conversions (sales) from your own server.","read:webhooks":"List webhook endpoints and the webhook delivery log.","write:webhooks":"Create, edit, delete, and send test events to webhook endpoints."}}