---
title: "subscription.paused"
description: "QuotaStack sends this when you pause a [subscription](/docs/concepts/subscriptions)."
---

# subscription.paused

Fired when POST /v1/subscriptions/{id}/pause pauses a subscription.

## When it fires

QuotaStack sends this when you pause a [subscription](/docs/concepts/subscriptions).

## When it does not fire

QuotaStack does not send this for a [subscription](/docs/concepts/subscriptions) that is not active. The pause call works from `active` alone, so a trialing or overdue one is turned away with no event. Pausing does not send `subscription.canceled`, and the customer keeps their credits.

## Payload — `data`

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required |  |
| `tenant_id` | string (uuid) | required |  |
| `customer_id` | string (uuid) | required |  |
| `plan_variant_id` | string (uuid) | required |  |
| `environment` | string | required | Which environment this resource lives in. Determined by the API key prefix used (`qs_live_…` → live, `qs_test_…` → sandbox). `live` `sandbox` |
| `status` | string | required | `trialing` `active` `cancelling` `canceled` `expired` `paused` `overdue` `contract_ended` |
| `origin` | string | optional | How the subscription was created — `api` (normal create) or `import` (legacy cutover). `api` `import` |
| `started_at` | string (date-time) | required |  |
| `trial_ends_at` | string (date-time) | optional |  |
| `current_period_start` | string (date-time) | optional |  |
| `current_period_end` | string (date-time) | optional |  |
| `billing_anchor` | integer | optional | Day of month (1-28) for monthly renewals. |
| `cancel_at_period_end` | boolean | required |  |
| `scheduled_variant_id` | string (uuid) | optional |  |
| `external_subscription_id` | string | optional |  |
| `paused_at` | string (date-time) | optional |  |
| `resumed_at` | string (date-time) | optional |  |
| `expired_at` | string (date-time) | optional |  |
| `contract_start` | string (date-time) | optional |  |
| `contract_end` | string (date-time) | optional |  |
| `contract_ending_soon_days` | integer | required |  |
| `metadata` | object | required |  |
| `created_at` | string (date-time) | required |  |
| `updated_at` | string (date-time) | required |  |

### Example payload

```json
{
  "event_id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a51",
  "event_type": "subscription.paused",
  "tenant_id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a01",
  "environment": "live",
  "customer_id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a05",
  "external_customer_id": "user_42",
  "created_at": "2026-07-28T12:10:00Z",
  "idempotency_key": "sub-pause:0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a21",
  "data": {
    "id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a21",
    "plan_variant_id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a12",
    "status": "paused",
    "paused_at": "2026-07-28T12:10:00Z"
  }
}
```

## What to do

Hold the account, and stop billing. Wait for `subscription.resumed` to start again.

## Which calls fire this

- [`POST /v1/subscriptions/{id}/pause`](/docs/api/subscriptions#pauseSubscription)

## See also

- [Subscriptions](/docs/concepts/subscriptions)

## Delivery

QuotaStack guarantees **at-least-once** delivery. An event may be delivered more than once if your endpoint returns a non-2xx response, the connection fails, or the request exceeds the delivery timeout.

**Delivery timeout:** 5 seconds per attempt. If your endpoint does not return a 2xx within 5 seconds, the attempt is treated as a failure and retried. Not configurable today.

**One webhook URL per tenant.** Multiple URLs and per-event routing are not supported. Configure the URL via the tenant config endpoint.

### Retry schedule

If delivery fails (non-2xx response, timeout, or network error), QuotaStack retries with exponential backoff:

| Attempt | Delay after previous |
|---|---|
| 1 | Immediate |
| 2 | 30 seconds |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 hours |
| 7 | 24 hours |

After 7 failed attempts, the event is moved to a dead letter queue. Dead-lettered events are not lost — you can requeue them yourself, from the dashboard (Activity → Webhooks → Redeliver) or the API:

```bash
curl -X POST https://api.quotastack.io/v1/webhooks/events/{event_id}/redeliver \
  -H "X-API-Key: $QS_KEY" \
  -H "Idempotency-Key: redeliver:{event_id}"
```

Redelivery resets the event to `pending` with a fresh retry schedule (7 new attempts). The next attempt signs with your **current** secret — useful when the event dead-lettered because of a secret rotation or an endpoint outage you have since fixed. Only `dead_letter` events can be redelivered; the call returns `409` for events in any other status.

### Handling duplicates

Because delivery is at-least-once, your webhook handler should be idempotent. Use the `webhook-id` header for deduplication — if you have already processed an event with that ID, return 200 and skip processing.
