---
title: Audit Log
description: Every mutation, who did it, and what the record looked like before and after — plus the dashboard stats endpoint.
order: 17
---

# Audit Log

Every change QuotaStack makes to your data is written to the audit log. Who did it, what they did, and what the record looked like before and after. The log is append-only: nothing in it is ever updated or deleted.

Old rows are thin. Before 2026-07-31, the log held our own jobs and nothing else. The [changelog](/docs/changelog/2026-07-31-audit-log-records-api-and-admin) says why.

> **Mental Model:** The audit log is **the ship's logbook**. Every change is written down as it happens, with who made it and what the entry looked like before and after. Pages are never torn out — the log is append-only.

## Quick Take

- Every mutation is recorded, including ones the scheduler makes
- `action` is a bare verb and `entity_type` is a noun — **not** a dotted `subscription.created`
- `before_state` and `after_state` are full snapshots; before is null for creates
- `actor_type` is `api`, `admin`, or `system`
- Filter by action, entity type, actor type, and a time window

## Diagram

Audit entries pair a verb with a noun. The same change appears in the webhook catalog under a dotted event name, which is a separate vocabulary.

| Change | Audit `action` | Audit `entity_type` |
|---|---|---|
| A subscription was created | `created` | `subscription` |
| A subscription was cancelled | `canceled` | `subscription` |
| Credits were granted | `granted` | `credit_transaction` |
| A metering rule was added | `created` | `pricing_rule` |
| An API key was revoked | `revoked` | `api_key` |

## Reading it

```bash
curl https://api.quotastack.io/v1/audit-log \
  -H "X-API-Key: qs_live_..."
```

Filters, all optional:

| Parameter | Values |
|---|---|
| `action` | A verb — `created`, `updated`, `granted`, and so on. See the list below. |
| `entity_type` | A noun — `subscription`, `customer`, `plan`. See the list below. |
| `actor_type` | `api`, `admin`, or `system`. |
| `from` / `to` | Timestamps bounding the search. |
| `limit` | How many entries to return. |
| `cursor` | The `pagination.next_cursor` from the previous page. |

## What an entry holds

| Field | Meaning |
|---|---|
| `actor_id` | Who did it. An API key ID, an admin user ID, or the name of a system job. |
| `actor_type` | `api` for an API key, `admin` for the dashboard, `system` for a scheduler job. |
| `action` | The verb. |
| `entity_type` | The kind of thing that changed. |
| `entity_id` | Which one. |
| `before_state` | The record before the change. **Null for creates** — there was nothing before. |
| `after_state` | The record after the change. |
| `environment` | `live` or `sandbox`. |
| `created_at` | When. |

## Action is a verb, entity_type is a noun

This trips people up, so it is worth being blunt. An action is **not** a dotted name like `subscription.created`. Those are webhook event types, and they are a different vocabulary.

In the audit log, the two are separate fields. A created subscription is `action: "created"` with `entity_type: "subscription"`.

To find every subscription that was cancelled:

```bash
curl "https://api.quotastack.io/v1/audit-log?action=canceled&entity_type=subscription" \
  -H "X-API-Key: qs_live_..."
```

**Actions in use:** `adjusted`, `canceled`, `committed`, `created`, `deleted`, `downgraded`, `granted`, `imported`, `paused`, `released`, `renewed`, `reserved`, `resumed`, `revoked`, `updated`, `upgraded`.

**Entity types in use:** `api_key`, `billable_metric`, `credit_transaction`, `customer`, `plan`, `plan_credit_grant`, `plan_variant`, `plan_variant_entitlement`, `pricing_rule`, `reservation`, `subscription`, `subscription_entitlement_override`, `tenant`, `tenant_config`, `topup`, `topup_package`.

Note `pricing_rule` — that is what a metering rule is called in the audit log.

## What it is good for

**Answering "who changed this?"** — the most common use. Filter by `entity_type` and `entity_id` and read the trail.

**Proving what a record used to be.** `before_state` and `after_state` are full snapshots. You see the old and new values, not only that something changed.

**Watching automated changes.** Renewals, expiries, and grants come from the scheduler. Those rows carry `actor_type: "system"`. Filter to those to see what the engine did on its own.

**Separating environments.** Each entry records its environment. A sandbox test never muddies your live trail.

## The dashboard stats endpoint

Related, and much smaller: a single call that returns the counters behind the dashboard home page.

```bash
curl https://api.quotastack.io/v1/stats/dashboard \
  -H "X-API-Key: qs_live_..."
```

| Field | Meaning |
|---|---|
| `customer_count` | How many customers you have. |
| `total_balance` | Every customer's balance added together, in millicredits. |
| `active_subscriptions` | How many subscriptions are active. |
| `credits_consumed_today` | Millicredits consumed since midnight UTC. |
| `credits_consumed_week` | Millicredits consumed over a rolling 7 days. |
| `credits_granted_week` | Millicredits granted over a rolling 7 days. |

Both week figures are **rolling 7 days**, not calendar weeks, and the field names have no `this` in them. Amounts are millicredits, like everywhere else in the API.

## Common Mistakes

**✗ Don't filter with `action=subscription.created`**

Dotted names are webhook event types. In the audit log the verb and the noun are separate fields: `action=created&entity_type=subscription`.

**✗ Don't look for a metering rule under `entity_type=metering_rule`**

It is recorded as `pricing_rule`.

**✗ Don't expect `before_state` on a create**

It is null, because nothing existed before. Only updates and deletes carry a before snapshot.

## Related

- [API Conventions](/docs/concepts/conventions) — Pagination and the cursor rules this endpoint follows.
- [Webhooks](/docs/concepts/webhooks) — The other event vocabulary — dotted names, pushed to your URL.
- [Subscription Overrides](/docs/concepts/subscription-overrides) — One of the things worth auditing.
- [Environments & the Shared Catalog](/docs/concepts/environments) — Each entry records the environment it happened in.
