POST /v1/actions/store/delete-store
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Store ID to delete (Short ID format STO_xxx) |
Example Request
const { store } = await client.stores.delete({
id: "STO_2aUyqjCzEIiEcYMKj7TZtw",
});
console.log(store.deletedAt); // => "2026-01-15T12:00:00.000Z"
// 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"
// 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);
# 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"
// 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))
// 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);
/* 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);
// 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;
MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP=$(date +%s)
BODY='{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"}'
BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 | tr -d '\n')
CANONICAL_REQUEST="POST
/v1/actions/store/delete-store
$TIMESTAMP
$BODY_HASH"
SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 | tr -d '\n')
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"
MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP=$(date +%s)
BODY='{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw"}'
BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 | tr -d '\n')
CANONICAL_REQUEST="POST
/v1/actions/store/delete-store
$TIMESTAMP
$BODY_HASH"
SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 | tr -d '\n')
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"
Success Response (200)
{
"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, withdeletedAt 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 carriesreason (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.
{
"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.
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.