POST / PUT / DELETE /v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywords
Apple Search Ads bulk keyword operations. Array body, max 200 per call.
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywords- Auth
- Bearer
- Scope
- ads:write:creative
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywords- Auth
- Bearer
- Scope
- ads:write:creative
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywords- Auth
- Bearer
- Scope
- ads:write:creative
Apple Search Ads is structurally different from Meta / TikTok — its tier-3 entity is the keyword, not the ad. Partner contract uses keywords directly (D36). Bulk operations only — Apple's API is bulk-native; per-keyword endpoints would multiply rate-limit cost ~10× and force partners to re-implement bulk semantics.
Body — POST (add keywords)
{
"keywords": [
{ "text": "cold brew coffee", "matchType": "exact", "bidAmountCents": 200, "status": "active" },
{ "text": "iced coffee delivery", "matchType": "broad", "bidAmountCents": 150, "status": "active" }
]
}Max 200 per call. matchType: exact | broad. bidAmountCents: integer, cents.
Body — PUT (update bids / status)
Only status and bidAmountCents are modifiable — Apple's keyword update permits exactly those two fields. Items carrying text or matchType are rejected with 422 VALIDATION; to change a keyword's text or match type, DELETE it and re-add.
{
"keywords": [
{ "keywordId": "kw_01HZX9...", "bidAmountCents": 250 },
{ "keywordId": "kw_01HZXA...", "status": "paused" }
]
}Body — DELETE (remove keywords)
{
"keywordIds": ["kw_01HZX9...", "kw_01HZXA..."]
}Response
202 with the typical {jobId, verdictId, status} envelope. status: "completed" reports per-keyword success/fail.
Settlement is per keyword: Apple's bulk endpoints can return partial failures inside an HTTP 200 (e.g. duplicate keywords), so each keyword settles with its own ads.write.executed or ads.write.denied webhook — a batch where 3 of 10 keywords fail emits 7 executed + 3 denied events, never a single all-executed event.
{
"jobId": "job_01HZX9...",
"verdictId": "ver_01HZX9...",
"results": [
{ "keywordId": "kw_01HZX9...", "status": "added" },
{ "keywordId": "kw_01HZXA...", "status": "added" }
]
}Errors
| Code | When |
|---|---|
VALIDATION | Empty array, > 200 keywords, missing required field. |
AUTHORITY_DENIED | creative axis is off on the parent campaign. |
PLATFORM_REJECTED | Apple refused (duplicate keyword, blacklisted text, etc.). Per-keyword reason in results[].error. |