POST / PUT / DELETE /v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywords
Apple Search Ads bulk keyword operations. Array body, max 200 per call.
POST
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywordsPhase 1stable
- Auth
- Bearer
- Scope
- ads:write:creative
PUT
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywordsPhase 1stable
- Auth
- Bearer
- Scope
- ads:write:creative
DELETE
/v1/projects/:projectId/ads/apple/adgroups/:adgroupId/keywordsPhase 1stable
- 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)
{
"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.
{
"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. |