POST /v4/analytics/apple-ads/entity/update without Qonversion MCP authorization returns 403 control_forbidden. Programmatically, campaign changes are available only through the Qonversion MCP server; people can also make them in the dashboard.
For accounts without access to the Apple Ads report, the Apple Ads REST read endpoints and the connection endpoint return 404
not_found, indistinguishable from a nonexistent endpoint. The Apple Ads report is available on all accounts; if yours gets this 404, contact support. For such accounts the change endpoint POST /v4/analytics/apple-ads/entity/update also answers HTTP 404 — as it does for accounts that have the Apple Ads report without campaign management — after its authorization check: a request without Qonversion MCP authorization gets 403 control_forbidden first. On accounts with the report only, the report and series endpoints also answer 404 for a project without per-app scope.Which Apple Ads endpoints does REST API v4 have?
The public REST API v4 has four Apple Ads endpoints:
REST responses carry an
object type and a canonical url: analytics_apple_ads_report (/v4/analytics/apple-ads/report), analytics_apple_ads_series (/v4/analytics/apple-ads/report/series) and apple_ads_connection (/v4/integrations/apple-ads/connection).
How do I authenticate Apple Ads requests?
POST /v4/analytics/apple-ads/entity/update without Qonversion MCP authorization (an acting dashboard user plus the apple_ads:write scope) returns 403 control_forbidden. Even with MCP authorization, every change is re-checked at request time: the request must name a dashboard user, carry apple_ads:write, and that user must still hold the Manage Apple Ads campaigns permission in the account; otherwise it is refused with 403. By default only the Owner and Administrator roles hold that permission; other members need it granted individually. The Apple Ads role of the campaign’s organization must also allow changes; see How do campaign changes work on the change endpoint?.
How do I request the Apple Ads report?
GET /v4/analytics/apple-ads/report accepts level, from, to, environment, sort, sort_dir, q, min_spend, min_spend_scope, limit, offset, export, windows, maturation_buffer_days, windows_mode, revenue_type, currency, filter[...] / filter_not[...] and metric_filters[...].
- Spend threshold.
min_spendkeeps only rows whose Apple spend is at least that amount, in the report’s currency (thecurrencyparameter, USD by default).min_spend_scopechooses what is compared: the row’s own spend (the default, the requestlevel), or, for a coarser level, the spend summed over the report’s rows that share the row’s campaign or ad group; a scope finer thanlevelis refused. Hidden rows without spend data are counted inpagination.rows_without_spend_hidden;totalandunallocatedare not affected.min_spend_scopehas no effect withoutmin_spend.
- Single-value state filters.
filter[status]andfilter[delivery]are single-value report-level filters; passing more than one value is an error. There is nostateparameter over REST (the MCP report tool has one); usefilter[status]orfilter[delivery]. - Exclusions.
filter_not(exclusion) is refused forcountry,campaign_nameandad_set_name, because Apple’s spend cannot be excluded the same way and ROAS/CAC would be wrong;statusanddeliveryhave no exclusion form either. Usefilter[...]to narrow by those instead. - Media source. A
media_source_namefilter narrows only the Qonversion users side of the Apple Ads report; Apple spend is not split by media source. - Windows.
windows_modeandmaturation_buffer_dayssent withoutwindowsare accepted and have no effect. The defaultwindows_modeis chosen by the server and may change, so sendwindows_modeexplicitly when it matters;meta.windows.modestates the reading actually served. - Unknown parameters. An unknown or unsupported query parameter is refused with 400
invalid_requestanderror.details[].reasonunsupported_parameter, instead of being silently ignored.
How do I filter report rows by metric values?
The REST report acceptsmetric_filters[<metric>][gte|lte]=<number> on the sort metric vocabulary. window_roas_<code> and window_cac_<code> are allowed only when that window is requested in windows. At most 12 distinct metrics are accepted per request. The MCP report tool does not expose metric_filters.
What is in the report response?
A report response haslevel, currency, revenue_type, status_data_available, rows, total, unallocated, pagination, partial_sources and meta. Check these markers before quoting numbers:
Values for campaign changes in the report rows:
- Status. In the report, each entity’s status is an object
{state, serving, display, reasons}; the value to pass asbefore_statusisstatus.state(ENABLED/ACTIVE/PAUSED). - Keywords. On the keywords level each row’s keyword block carries
id,name(the keyword text),status,match_type,bidanddelivery. - Daily budget. On the campaigns level the campaign block carries
daily_budgetas{amount, currency}ornull, in the advertising account’s currency. - Bid.
bidis reported as{amount, currency}only on thead_groupblock of groups-level rows and thekeywordblock of keywords-level rows. It is in the advertising account’s own currency, never converted, andamountis a decimal string. It is not a live read and may not yet reflect a change you just made.nullmeans the bid is not available in this response, not a zero bid.
How do I request a daily Apple Ads series?
GET /v4/analytics/apple-ads/report/series accepts metric (one) or metrics (1–4 distinct, comma-separated) from this list:
fromandto(Unix seconds, UTC) are required.environmentdefaults to1(production) when omitted;0selects sandbox.- Daily only. The public series is daily only: a
unitparameter is not accepted (400unsupported_parameter), while the dashboard chart can also group by week or month. - At most 366 points. A series returns at most 366 daily points; for longer periods the oldest days are dropped and
truncatedistrue. - Ignored filters. On the series,
filter[status]andfilter[delivery](and any filter the metric’s source cannot honour) are accepted but not applied, and are listed infilters_ignored. - The MCP tool
get_apple_ads_seriesplots one metric per call from a narrower list of 12 metrics.
How do I check the Apple Ads connection?
GET /v4/integrations/apple-ads/connection takes no parameters and returns state, connection_method, granted_at, last_verified_at, reporting, campaign_management, orgs[], next_action and dashboard_url.
The API and MCP never start or complete Apple sign-in. The connection status never returns credential material (private key, client secret, tokens, authorization code, OAuth state). Read
campaign_management.can_write before attempting changes.
How do campaign changes work on the change endpoint?
POST /v4/analytics/apple-ads/entity/update is the endpoint behind the Qonversion MCP change tools (set_apple_ads_status, set_apple_ads_bid, set_apple_ads_daily_budget). Without Qonversion MCP authorization it returns 403 control_forbidden; see Apple Ads via MCP for the tools and their confirmation rules.
Request body. The endpoint accepts no query parameters (400 invalid_request); every field, including dry_run, goes in the JSON body (max 64 KB). Accepted keys are level, org_id, campaign_id, ad_group_id, keyword_id, keyword_text, keyword_match_type, idempotency_key, dry_run, status, before_status, bid, before_bid, daily_budget, before_daily_budget. Unknown fields in a change request body (including unknown keys inside a money object) are refused with 400 invalid_request (reason unsupported_parameter), not 422, before anything is sent to Apple.
Money fields. On this endpoint, bid and daily_budget must be JSON objects {"amount": "<decimal string>", "currency": "<three-letter code>"}. A plain number or string in bid or daily_budget is not recognised as an action, and the request is refused with 422. before_bid and before_daily_budget are accepted either as the same {amount, currency} object or as a plain decimal string. The Qonversion MCP change tools send all four fields to this endpoint as {amount, currency} objects.
Retries. Resending the same change with the same
idempotency_key returns the original result with replayed: true instead of changing anything twice. Reusing a key for a different change returns 409 idempotency_key_reuse; a still-running attempt returns 409 in_progress.
Success response. A successful change returns 200 with confirmed (the value Apple confirmed, or null), applied, dry_run and action_id (identifier of the change — quote it to support), plus baseline_unverified and, for dry runs, would_send when applicable. Verify a change from this response, not by re-reading the report.
What limits apply to campaign changes?
Limits are counted per Qonversion project, not per user, and changes made in the dashboard and through the Qonversion MCP server count toward the same limits. Pauses and bid/budget decreases do not count toward the daily increase caps (they still count toward the per-minute and per-hour limits); a bid or budget change on an entity Qonversion has never changed before is always counted as an increase. Dry runs, validation refusals and changes Apple rejected do not count toward any campaign-change limit.
How does the REST API differ from MCP and from the dashboard?
REST API v4 compared with the Qonversion MCP server:
REST API v4 compared with the Qonversion dashboard:
What errors and rate limits do the Apple Ads endpoints return?
Server-side errors on the change endpoint. Every server-side (5xx) response of the change endpoint is returned with its status but a generic body (code
storage_error, or network_error on 504); the specific reason and action_id are not included. A 502 or 504 is never retried automatically. Do not resend it with a new idempotency_key: retry only with the same idempotency_key, which cannot apply the change twice, and check the entity’s current value before making any new change. If changes are refused with 503 because Apple’s confirmation of the connection’s permissions is out of date, the connection status shows campaign_management.state unknown with reason_code permission_data_stale; a person reopens Apple Ads settings in the dashboard to refresh, then you retry.
Related pages
- Apple Ads via MCP — the six Apple Ads MCP tools, the confirmation flow for campaign changes and how errors look through MCP.
- Authentication — how to send the project Secret Key with REST API v4 requests.
- Handling errors — the v4 error envelope and HTTP status codes.
- Manage Apple Ads campaigns — pausing, bids and daily budgets in the Qonversion dashboard, and who can make changes.
- Apple Ads report — the same report in the Qonversion dashboard, including CSV export and currency.