# Quotas

The `/v1/quotas` endpoint shows three things:

1. The base **tier limits** (the API is Enterprise-only, so the tier is always `enterprise`).
2. Any per-store **overrides** support has set (custom deals, partner integrations).
3. The **effective limits** — overrides win, falling back to tier defaults.

API access with the keys you create requires an **active Enterprise plan**. Leaving Enterprise, by downgrade or expiry, doesn't change the reported limits; it removes access entirely (`403 forbidden` on every call, including this one) until the store is back on Enterprise. You never need to re-issue a key.

API limits only

These quotas count API calls made with a key against `https://api.dzbuild.app/v1`. Your storefront, checkout and dashboard are never throttled by them and never consume them. See [Rate limits](https://dzbuild.com/api-docs/rate-limits.md).

## Tier limits

| Tier         | Requests / month | Signups / month | Webhooks / month | Requests / minute |
| ------------ | ---------------- | --------------- | ---------------- | ----------------- |
| `enterprise` | `-1`             | `-1`            | `-1`             | 600               |

The legacy Free / Pro / Unlimited tiers were retired in August 2026 when the API became Enterprise-only. The value reported under `effective` is the one enforced, with one exception: calls to `https://api.dzbuild.app/v1` never go above 600 requests per minute per store, even when an override sets `requests_per_minute` higher.

## `GET /v1/quotas`

**Auth:** platform key with `usage:read` (this scope really is enforced here).

### Request

```
curl https://api.dzbuild.app/v1/quotas \

  -H "Authorization: Bearer $DZ_KEY"
```

### Response 200

```
{

  "data": {

    "tier": "enterprise",

    "tier_limits": {

      "requests_per_month":  -1,

      "signups_per_month":   -1,

      "webhooks_per_month":  -1,

      "requests_per_minute": 600

    },

    "overrides": null,

    "effective": {

      "requests_per_month":  -1,

      "signups_per_month":   -1,

      "webhooks_per_month":  -1,

      "requests_per_minute": 600

    }

  }

}
```

When an override is in place:

```
{

  "data": {

    "tier": "enterprise",

    "tier_limits": {

      "requests_per_month":  -1,

      "signups_per_month":   -1,

      "webhooks_per_month":  -1,

      "requests_per_minute": 600

    },

    "overrides": {

      "store_id":            13,

      "requests_per_month":  null,       // not overridden, falls back to tier

      "signups_per_month":   null,

      "webhooks_per_month":  null,

      "requests_per_minute": 1200,       // override

      "notes": "Partner integration — Q2 2026",

      "set_by_user_id":      1,

      "updated_at":          "2026-04-30 19:27:55"

    },

    "effective": {

      "requests_per_month":  -1,         // from tier

      "signups_per_month":   -1,

      "webhooks_per_month":  -1,

      "requests_per_minute": 1200        // from override

    }

  }

}
```

## When you'd want an override

* **Seasonal spike** without upgrading the whole month (Aïd, Black Friday).
* **Partner integration** — a Zapier-like service connects on your behalf and needs higher RPS than your tier.
* **Custom contract** — Enterprise deals.

Contact support with your store id to set one up. An override **replaces** the tier value for whichever fields are set; `null` fields fall through to the tier default. An override can also be *lower* than the tier default — in practice support only raises them, but treat `effective` as authoritative rather than assuming it is at or above `tier_limits`.

`overrides` is returned as-is, so additional fields may appear over time. It is `null` when no override exists for the store.

## `-1` = unlimited

Any field set to `-1` means no limit. The `enterprise` tier defaults the three **monthly** fields to `-1`; `requests_per_minute` is always a real value (never `-1`) so that no single integration can overwhelm the servers that also serve merchant storefronts. See [Rate limits](https://dzbuild.com/api-docs/rate-limits.md).

## When you'd hit a quota

* **Per-minute burst** → `429` with `Retry-After`. Enforced **per store**: all of the store's keys share the budget, including the keys used by Copilot, a connected AI assistant (Claude or ChatGPT) or an installed app. The counters are eventually consistent, so under a sharp burst you may be briefly over-allowed, or see a `429` slightly sooner than your own tally predicts.
* **Monthly request quota** → `402 quota_exceeded` until the 1st of next month. Enforced **per store**, summed across all its keys, and rejected before the request is processed.
* **Signup quota** — reported but **not enforced** at v1. Exceeding `signups_per_month` does not block `/v1/signups`; the counter is informational (`GET /v1/usage`) until metered billing ships.
* **Webhook delivery quota**: **not enforced and not metered** at v1. Deliveries are never counted and never paused for quota; the only automatic backstop is per *delivery*: a failure that is not retried (any 4xx other than `408` and `429`, or a 3xx) gives that delivery up at the first attempt, and a retryable failure (a timeout or network error, a 5xx, `408` or `429`) stops after the 5th failed attempt. The webhook endpoint itself is never paused: new events keep being queued for it.

See [Errors](https://dzbuild.com/api-docs/errors.md) and [Rate limits](https://dzbuild.com/api-docs/rate-limits.md) for retry strategies.
