{"id":"dc0a068e-fc37-49f7-9173-0a66553f58e7","task":"Read App Store customer reviews and publish, replace or delete a developer response via the App Store Connect API","domain":"developer.apple.com/documentation/appstoreconnectapi","steps":["Authenticate with Authorization: Bearer <JWT>.","Get the app resource id via GET /v1/apps (filter[bundleId] if needed).","List reviews: GET https://api.appstoreconnect.apple.com/v1/apps/{id}/customerReviews, optionally with filter[territory] (array of ISO territory codes such as USA, GBR, JPN) and filter[rating] (array of integers 1-5).","Sort newest-first with sort=-createdDate. Valid sort values are createdDate, -createdDate, rating, -rating.","Paginate with limit (max 200) and follow links.next; meta.paging.total gives the full count.","Trim the payload with fields[customerReviews]=rating,title,body,reviewerNickname,createdDate,territory,response and use include=response to embed any existing reply in the same call.","Read each review's attributes: rating (int), title, body, reviewerNickname, createdDate (ISO 8601), territory.","Detect reviews that already have a reply using the exists[publishedResponse] filter, or follow GET /v1/customerReviews/{id}/response.","Publish a reply: POST https://api.appstoreconnect.apple.com/v1/customerReviewResponses with {\"data\":{\"type\":\"customerReviewResponses\",\"attributes\":{\"responseBody\":\"Thanks for the feedback! We fixed this in v2.1.\"},\"relationships\":{\"review\":{\"data\":{\"type\":\"customerReviews\",\"id\":\"00000028-b08c-0014-729e-fbd500000000\"}}}}}","A successful POST returns 201 with attributes.state of PENDING_PUBLISH or PUBLISHED, plus lastModifiedDate.","To CHANGE a reply, POST again to /v1/customerReviewResponses with the same review relationship. Apple documents this call as creating a new response or replacing the existing one — there is no PATCH endpoint.","To remove a reply entirely: DELETE https://api.appstoreconnect.apple.com/v1/customerReviewResponses/{id}","Verify publication with GET /v1/customerReviewResponses/{id} and check attributes.state == PUBLISHED before considering the task complete.","Official docs: https://developer.apple.com/documentation/appstoreconnectapi/get-v1-apps-_id_-customerreviews | https://developer.apple.com/documentation/appstoreconnectapi/customer-review-responses | https://developer.apple.com/documentation/appstoreconnectapi/post-v1-customerreviewresponses"],"gotchas":["There is NO PATCH for customerReviewResponses. Updating means re-POSTing with the same review relationship, which overwrites the previous reply.","Each review can hold at most one response. A second POST replaces rather than appends.","State starts at PENDING_PUBLISH and only later becomes PUBLISHED — a 201 does not mean the reply is live on the App Store.","filter[territory] and filter[rating] are array-valued (comma-separated), not single scalars.","limit caps at 200 while an app's total review count can run into the thousands — iterate links.next rather than assuming one page.","Apple's API reference publishes NO character limit for responseBody. Do not hard-code an assumed maximum; handle a 422 if the text is rejected.","409 Conflict or 422 Unprocessable Entity can occur on a racing double-response or an empty responseBody. Handle these distinctly from 401/403 auth errors.","Reading and responding requires a sufficient role (Customer Support, App Manager or Admin). A valid JWT on an under-privileged key still returns 403."],"contributor":"asc-api-route-factory","created":"2026-07-29T15:35:20.918Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-29T15:35:20.918Z"},"url":"https://mcp.waymark.network/r/dc0a068e-fc37-49f7-9173-0a66553f58e7"}