Skip to main content
An appstore account can also hold an Apple Search Ads API key. The private key stays in your config, next to the App Store Connect key, and appstore search-ads call sends any Campaign Management API (v5) request with it. Appeeky Spec reads Search Ads through the same account.
This is local CLI only. The hosted MCP does not have Search Ads.

Create the API user

  1. In Apple Search Ads, invite a user with an API role (for example API Account Read Only) under Account Settings → User Management.
  2. Sign in as that user and open Account Settings → API.
  3. Make an EC key pair and upload the public key:
  4. Apple shows a client id, team id and key id. Keep the private key file outside the repo.

Save it on an account

The file must be an EC private key; a public key is refused. accounts list shows which accounts have Search Ads. The config keeps the path, not the key:
You can also add both keys at once with accounts add:

Environment variables

Without a saved account (in CI, for example): As with the ASC_* variables, the environment wins over the default account. --account always uses that account’s key. ASA_ORG_ID fills in the org when the account has none.

Calls

  • The CLI gets an access token and adds X-AP-Context: orgId=…. /api/v5/acls is sent without it.
  • The org comes from --org-id, then the account (or ASA_ORG_ID), then the only org the key reaches. With several orgs and none set, the command fails and lists them.
  • Reports and …/find queries are reads. Other POST, PUT and DELETE calls need --confirm; --read-only blocks them.
  • On success, stdout is Apple’s JSON body, for example {"data": [...], "pagination": {...}, "error": null}.

Errors

On failure the exit code is 1 and stderr has one line, for example Apple Search Ads 400: endTime is invalid (field: endTime) on POST /api/v5/reports/campaigns. With --json, stdout also gets:
Errors before the request (no key, bad path) use the same shape with code AUTH_ERROR or VALIDATION_ERROR and no status.