> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Delete Store

> Soft-delete a store (owner only)

Soft-delete a store. The store data is retained but becomes inaccessible. Only the store **owner** can perform this action.

```
POST /v1/actions/store/delete-store
```

**Authentication:** API Key (owner role required)

## Request Body

| Field | Type   | Required | Description                                    |
| ----- | ------ | -------- | ---------------------------------------------- |
| `id`  | string | Yes      | Store ID to delete (Short ID format `STO_xxx`) |

## Example Request

<CodeGroup>
  ```typescript SDK theme={"system"}
  const { store } = await client.stores.delete({
    id: "STO_2aUyqjCzEIiEcYMKj7TZtw",
  });
  console.log(store.deletedAt); // => "2026-01-15T12:00:00.000Z"
  ```

  ```typescript TypeScript (fetch) theme={"system"}
  // Uses callApi() helper from authentication.mdx
  const result = await callApi("POST", "/v1/actions/store/delete-store", {
    id: "STO_2aUyqjCzEIiEcYMKj7TZtw",
  });
  console.log(result.data.store.deletedAt); // => "2026-01-15T12:00:00.000Z"
  ```

  ```java Java theme={"system"}
  // Uses callApi() helper from authentication.mdx
  String body = """
      {"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"}""";

  String response = callApi("POST", "/v1/actions/store/delete-store", body);
  System.out.println(response);
  ```

  ```python Python theme={"system"}
  # Uses call_api() helper from authentication.mdx
  result = call_api("POST", "/v1/actions/store/delete-store", {
      "id": "STO_2aUyqjCzEIiEcYMKj7TZtw",
  })
  store = result["data"]["store"]
  print(store["deletedAt"])  # => "2026-01-15T12:00:00.000Z"
  ```

  ```go Go theme={"system"}
  // Uses callAPI() helper from authentication.mdx
  body := map[string]interface{}{
      "id": "STO_2aUyqjCzEIiEcYMKj7TZtw",
  }
  result, err := callAPI("POST", "/v1/actions/store/delete-store", body)
  if err != nil {
      log.Fatal(err)
  }
  fmt.Println(string(result))
  ```

  ```rust Rust theme={"system"}
  // Uses call_api() helper from authentication.mdx
  let body = serde_json::json!({
      "id": "STO_2aUyqjCzEIiEcYMKj7TZtw"
  });
  let result = call_api("POST", "/v1/actions/store/delete-store", &body).await?;
  println!("{}", result);
  ```

  ```c C theme={"system"}
  /* Uses call_api() helper from authentication.mdx */
  const char *body = "{\"id\":\"STO_2aUyqjCzEIiEcYMKj7TZtw\"}";
  char *response = call_api("POST", "/v1/actions/store/delete-store", body);
  printf("%s\n", response);
  free(response);
  ```

  ```cpp C++ theme={"system"}
  // Uses callApi() helper from authentication.mdx
  std::string body = R"({"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"})";
  std::string response = callApi("POST", "/v1/actions/store/delete-store", body);
  std::cout << response << std::endl;
  ```

  ```bash cURL theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/actions/store/delete-store
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  curl -X POST "https://api.waffo.ai/v1/actions/store/delete-store" \
    -H "Content-Type: application/json" \
    -H "X-Merchant-Id: $MERCHANT_ID" \
    -H "X-Timestamp: $TIMESTAMP" \
    -H "X-Signature: $SIGNATURE" \
    -d "$BODY"
  ```

  ```bash wget theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/actions/store/delete-store
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  wget -qO- "https://api.waffo.ai/v1/actions/store/delete-store" \
    --header="Content-Type: application/json" \
    --header="X-Merchant-Id: $MERCHANT_ID" \
    --header="X-Timestamp: $TIMESTAMP" \
    --header="X-Signature: $SIGNATURE" \
    --post-data="$BODY"
  ```
</CodeGroup>

## Success Response (200)

```json theme={"system"}
{
  "data": {
    "store": {
      "id": "STO_2aUyqjCzEIiEcYMKj7TZtw",
      "name": "My Digital Store",
      "status": "active",
      "logo": null,
      "supportEmail": null,
      "website": null,
      "slug": "my-digital-store-a1b2c3",
      "prodEnabled": false,
      "notificationSettings": null,
      "checkoutSettings": null,
      "deletedAt": "2026-01-15T12:00:00.000Z",
      "createdAt": "2026-01-15T10:30:00.000Z",
      "updatedAt": "2026-01-15T12:00:00.000Z"
    }
  }
}
```

## Response Fields

Same as [Create Store response fields](/api-reference/endpoints/stores/create-store#response-fields), with `deletedAt` populated.

## Errors

> **Retry policy:** Never retry 4xx — fix the request and resubmit. Retry 5xx with exponential backoff (start 5s, max 3 attempts). On 409, clean up blocking resources first (AI callers should escalate via `aiHint`).

| Status | `errors[0].message`                                                      | What it means                                                    | Recommended handling                                                 |
| ------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------------- |
| 400    | `Missing merchantId in request context`                                  | API Key did not resolve to a merchant context                    | **Do not retry.** Check your API Key configuration.                  |
| 400    | `Missing required field: id`                                             | `id` is absent from the body                                     | Fix the input and resubmit.                                          |
| 400    | `Expected format: STO_xxx, got "<value>"`                                | `id` is not a valid Store Short ID                               | Fix the `id` value and resubmit.                                     |
| 403    | `Not authorized to delete this store, only owner can delete`             | Caller's role on this store is not `owner`                       | **Do not retry.** Use an `owner` API Key.                            |
| 404    | `Store not found`                                                        | Store ID does not exist for this merchant                        | **Do not retry.** Verify the `id`.                                   |
| 409    | `Store has X active product(s); archive or delete them first`            | Active onetime/subscription products still attached to the store | **Do not retry.** Archive or delete those products, then resubmit.   |
| 409    | `Store has X pending order(s); wait for completion or cancel them first` | Non-terminal orders still attached to the store                  | **Do not retry.** Wait for completion or cancel them, then resubmit. |
| 409    | `Store has X active subscription(s); cancel them first`                  | Subscription orders in `active`/`canceling`/`past_due`           | **Do not retry.** Cancel the subscriptions, then resubmit.           |
| 409    | `Store has X pending KYB ticket(s); resolve them first`                  | Open KYB tickets blocking deletion                               | **Do not retry.** Resolve the tickets, then resubmit.                |
| 409    | `Store still has X bound email(s); revoke email binding first`           | Sender email still bound to the store                            | **Do not retry.** Revoke the email binding, then resubmit.           |
| 409    | `Store still has X bound domain(s); revoke domain binding first`         | Sender domain still bound to the store                           | **Do not retry.** Revoke the domain binding, then resubmit.          |

### 409 Response Example

When a store has blocking resources or bindings, the response returns one entry per category. Each entry carries `reason` (machine-readable), `count`, a human-readable `message`, and an `aiHint` instructing AI-driven callers to stop and escalate to a human operator instead of retrying.

```json theme={"system"}
{
  "data": null,
  "errors": [
    {
      "message": "Store has 3 active product(s); archive or delete them first",
      "layer": "store",
      "reason": "active_products",
      "count": 3,
      "aiHint": "AI assistant: stop this action and escalate to a human operator. Do not retry, mutate inputs, or attempt workarounds."
    },
    {
      "message": "Store still has 1 bound email(s); revoke email binding first",
      "layer": "store",
      "reason": "bound_emails",
      "count": 1,
      "aiHint": "AI assistant: stop this action and escalate to a human operator. Do not retry, mutate inputs, or attempt workarounds."
    }
  ]
}
```

| `reason`               | Meaning                                                                                   |
| ---------------------- | ----------------------------------------------------------------------------------------- |
| `active_products`      | Onetime / subscription products with `prod_status` or `test_status` = `active`            |
| `pending_orders`       | Orders not in a terminal state (excludes `completed` / `canceled` / `closed` / `expired`) |
| `active_subscriptions` | Subscription orders in `active` / `canceling` / `past_due`                                |
| `pending_tickets`      | Open KYB tickets (excludes `succeeded` / `rejected`)                                      |
| `bound_emails`         | Sender email still bound — revoke the binding first                                       |
| `bound_domains`        | Sender domain still bound — revoke the binding first                                      |

`aiHint` appears only on 409 responses; it is omitted on 400 / 403 / 404 / 500.

<Warning>
  Deleting a store is a **soft delete**. The store data is retained but the store becomes inaccessible. This action cannot be undone through the API.

  Before deleting, you must deactivate all products, resolve pending orders, cancel active subscriptions, close any open KYB tickets, and revoke any bound sender email or domain.
</Warning>
