---
title: "Cancel a scheduled review reply"
method: POST
path: "/api/v1/review-replies/{id}/cancel"
tags: ["Write"]
---

# Cancel a scheduled review reply

`POST /api/v1/review-replies/{id}/cancel`

## Request

- Base URL: `https://api.trysonar.app`
- URL: `https://api.trysonar.app/api/v1/review-replies/{id}/cancel`
- Auth: HTTP bearer

Moves a scheduled reply (manual or auto) back to draft before it posts. 409 conflict when nothing is scheduled. Requires an Indie or Agency plan and a write-scope API key.

## Path parameters

- `id` string, uuid, required

## Response `200`

The updated review

- object
  - `data` ReviewReply, required: An own iOS app's App Store review (synced from App Store Connect) with its reply workflow state.
    - `id` string, uuid: Sonar review id (use with /api/v1/review-replies/{id})
    - `app_id` string, uuid
    - `asc_review_id` string: Apple's App Store Connect review id
    - `rating` integer
    - `title` string, nullable
    - `body` string, nullable
    - `reviewer_nickname` string, nullable
    - `country` string, nullable: Storefront, ISO 3166-1 alpha-2
    - `territory` string: Apple territory code (alpha-3, e.g. USA)
    - `created_at` string, date-time
    - `language` string, nullable: Review language, ISO 639-1 (null until drafted)
    - `title_en` string, nullable: English translation; null for English reviews
    - `body_en` string, nullable: English translation; null for English reviews
    - `reply` object
      - `status` 'backlog' | 'pending' | 'draft' | 'held' | 'scheduled' | 'posting' | 'pending_publish' | 'published' | 'failed' | 'dismissed' | 'answered': backlog = existed before the responder was switched on; pending = waiting for the AI draft; held = auto mode didn't post it (see hold_reason); pending_publish = sent, Apple takes up to 24h; answered = a response Sonar didn't write exists
      - `body` string, nullable
      - `language` string, nullable
      - `body_en` string, nullable: English copy of a non-English reply
      - `source` 'ai' | 'user' | 'api' | 'null', nullable
      - `hold_reason` string, nullable: needs_human (may carry a note after a colon), quota or daily_cap
      - `scheduled_for` string, date-time, nullable
      - `posted_at` string, date-time, nullable
      - `posted_by` string, nullable
      - `error` string, nullable
    - `app_store_response` object, nullable: The live developer response App Store Connect reports, whoever wrote it
      - `body` string
      - `state` string, nullable: PENDING_PUBLISH or PUBLISHED
      - `updated_at` string, date-time, nullable

## Other responses

- `400`: Missing or invalid request parameters
- `401`: Missing or invalid API key
- `403`: Plan or scope insufficient (workspace endpoints need an Indie or Agency plan; writes also need a write-scope key)
- `404`: Resource not found or not tracked by your organization
- `409`: conflict — the reply isn't scheduled
- `429`: Rate limited — see `error.reason`: daily_limit (Indie 1,000, Agency 5,000, trial 150 requests/day, resets 00:00 UTC; see `reset_at`), anonymous_daily_limit / batch_too_large (keyless free tier), store_rate_limited or concurrency_limit (transient, honor `retry_after_seconds`)
- `500`: Unexpected server error

---

[API](https://skmtc.dev/trysonar/apis/sonar-api.md) · [All operations](https://skmtc.dev/trysonar/apis/sonar-api/llms.txt) · [OpenAPI document](https://skmtc.dev/trysonar/apis/sonar-api/revisions/bf1d31dadd5f?raw)
