# Apple Ads Operator Playbooks > Practical Apple Ads workflows for safe setup, read-only checks, reporting, and guarded mutations Use these playbooks when you are operating Apple Ads from `asc` in a terminal, CI job, or agent run. The goal is to start read-only, confirm the org context, and only mutate resources after the target IDs and payload files are reviewed. ## Setup and Credential Safety Apple Ads credentials are separate from App Store Connect API credentials. `asc auth login` does not configure `asc ads`. Create a named Apple Ads profile and store the default org when you know it: ```bash theme={null} asc ads auth login \ --name "Marketing" \ --client-id "SEARCHADS_CLIENT_ID" \ --team-id "SEARCHADS_TEAM_ID" \ --key-id "KEY_ID" \ --private-key "$HOME/.asc/apple-ads-private-key.pem" \ --org "123456" \ --network ``` For CI, prefer secrets and environment variables over checked-in config: ```bash theme={null} export ASC_ADS_CLIENT_ID="SEARCHADS_CLIENT_ID" export ASC_ADS_TEAM_ID="SEARCHADS_TEAM_ID" export ASC_ADS_KEY_ID="KEY_ID" export ASC_ADS_PRIVATE_KEY_PATH="$HOME/.asc/apple-ads-private-key.pem" export ASC_ADS_ORG_ID="123456" export ASC_ADS_BYPASS_KEYCHAIN=1 asc ads campaigns list --org "$ASC_ADS_ORG_ID" --limit 1 --output json ``` Use a read-only API command for CI validation so the run resolves the exported `ASC_ADS_*` credentials and org context instead of only listing stored profiles. Use `ASC_ADS_PRIVATE_KEY_B64` when your CI secret store handles single-line values more reliably than PEM blocks. Keep `ASC_ADS_ACCESS_TOKEN` for cases where another trusted system already minted a short-lived token. ## Org Access Inspection Start outside an org context. These commands do not require `--org`: ```bash theme={null} asc ads acls list --output json ``` Use the ACL response to confirm the account and choose the org ID, then pin it explicitly for the rest of the session: ```bash theme={null} export ASC_ADS_ORG_ID="123456" asc ads campaigns list --org "$ASC_ADS_ORG_ID" --limit 1 --output json ``` When operating multiple Apple Ads accounts, avoid relying on the ambient default. Pass both profile and org: ```bash theme={null} asc ads campaigns list \ --ads-profile "Marketing" \ --org "123456" \ --limit 10 \ --output table ``` ## Safe Read-Only Smoke Test Use this sequence before an automation run or after rotating credentials: ```bash theme={null} asc ads acls list --output json asc ads campaigns list --org "123456" --limit 1 --output json ``` Expected result: every command exits successfully, and the campaign list returns either a `data` array or an empty `data` array. Treat auth failures, missing org errors, or unexpected account names as stop conditions. When using stored Ads profiles, add profile validation before the API smoke test: ```bash theme={null} asc ads auth status --validate --output json ``` ## Campaign and Ad Group Inventory List campaigns first, then inspect ad groups under one confirmed campaign ID: ```bash theme={null} asc ads campaigns list \ --org "123456" \ --limit 100 \ --output table asc ads ad-groups list \ --org "123456" \ --campaign 987654321 \ --limit 100 \ --output json ``` For full exports from query-parameter list endpoints, use pagination: ```bash theme={null} asc ads campaigns list --org "123456" --paginate --output json asc ads ad-groups list --org "123456" --campaign 987654321 --paginate --output json ``` Do not use report payloads as inventory replacements. Reports answer performance questions; list and find endpoints answer "what exists right now?" questions. ## Report Workflow Keep reporting requests in files so they can be reviewed and reused: ```json reporting-request.json { "startTime": "2026-05-01", "endTime": "2026-05-31", "returnRowTotals": true, "returnGrandTotals": true, "selector": { "pagination": { "offset": 0, "limit": 100 }, "orderBy": [ { "field": "impressions", "sortOrder": "DESCENDING" } ] } } ``` Run the campaign report with an explicit org and output format: ```bash theme={null} asc ads reports campaigns \ --org "123456" \ --file reporting-request.json \ --output json ``` For ad-group, keyword, search-term, or ad-level reports, first verify the parent campaign ID with `asc ads campaigns list`. Report pagination lives inside the Apple Ads request body, so update the file's selector pagination rather than adding `--paginate`. ## Raw API Safety Use `asc ads api request` for debugging, newly added Apple fields, or support captures. Prefer first-class commands for routine work. Read-only raw request: ```bash theme={null} asc ads api request \ --method GET \ --path v5/campaigns \ --org "123456" \ --output json ``` Selector request with a reviewed JSON file: ```bash theme={null} asc ads api request \ --method POST \ --path v5/campaigns/find \ --org "123456" \ --file selector.json \ --output json ``` Raw requests only accept Apple Ads v5 paths or Apple Ads API URLs. `DELETE` requests require `--confirm`; do not pass it until the command line includes the exact target path you intend to delete. ## Mutation Safety Checklist Before running create, update, delete, or bulk commands: 1. Run the matching `--help` command and confirm required flags. 2. Resolve account and org access with `asc ads acls list --output json`. 3. Run a read-only resource check: `asc ads campaigns list --org "123456" --limit 1 --output json`. 4. Pass `--ads-profile` and `--org` explicitly when more than one account or org is possible. 5. Store request bodies in reviewed JSON files; avoid shell-escaped inline JSON. 6. Create paused or clearly named test resources when validating workflow shape. 7. Print or log the target IDs before using `--confirm`. 8. Prefer deleting temporary parent campaigns only after confirming Apple allows the cleanup. Example guarded delete: ```bash theme={null} asc ads campaigns view --org "123456" --campaign 987654321 --output json asc ads campaigns delete --org "123456" --campaign 987654321 --confirm ``` ## Troubleshooting Auth and Source Precedence Use the auth doctor first: ```bash theme={null} asc ads auth doctor --output json asc ads auth status --verbose --output json ``` Common fixes: * Missing org: pass `--org`, export `ASC_ADS_ORG_ID`, or store `--org` during login. * Wrong profile: pass `--ads-profile "Marketing"` or export `ASC_ADS_PROFILE`. * Keychain prompts in CI: export `ASC_ADS_BYPASS_KEYCHAIN=1`. * Mixed sources: set `ASC_ADS_STRICT_AUTH=1` to fail when both profile and env token/key sources are present. * Token-only runs: `ASC_ADS_ACCESS_TOKEN` still needs `--org`, `ASC_ADS_ORG_ID`, or a stored profile org. When debugging API responses, use an explicit output format and redact tokens, client IDs, team IDs, key IDs, org IDs, and account names before sharing logs.