quotastack Docs
Docs / API / Audit log

Audit log

QuotaStack writes every change to a log. No one can edit it.

The audit log answers one question: who changed this, and when.

QuotaStack writes an entry as each change happens. Nobody can edit an entry afterwards, and nobody can delete one. That is what makes the log worth reading.

Each entry holds a verb and a thing. action is the bare verb, such as granted. entity_type is what it happened to, such as credit_transaction. Read the two together.

The verb is not the dotted name a webhook uses. Do not match credit.granted here.

Every filter matches the whole value, exactly. Nothing partial, and case matters.

The log is a record you read later. A webhook reaches you at the time. Use the log for a question about the past.

Which call do I want?

  • You need to know who changed something, and whenGET /v1/audit-log
  • You want to be told about changes as they happenlistWebhookEvents
    The audit log is a record you read later. A webhook reaches you at the time. Use the log to answer a question about the past.
1 of 1 operations documented in full.

List audit log entries

GET/v1/audit-log
Idempotency-KeyNot used. This is a read.
EnvironmentSandbox and Live
AuthTenant API key
WritesNothing. A read has no side effects.
Fires No webhooks.

This call returns what changed, newest first. QuotaStack writes an entry for a change and never edits it afterwards. Read action together with entity_type. action holds a bare verb, such as created or granted. The two together make the sentence: granted plus credit_transaction. The verb is not the dotted name a webhook uses. Every filter matches the whole value exactly. There is no partial match, and case matters. from takes in the moment you name. to stops one tick before it. A timestamp QuotaStack cannot read returns 400, and so does a bad cursor.

Query parameters
FieldTypeMeaning
actionoptionalstring

Keep only entries with this verb, such as created or granted.

If you leave it out: You get every verb.

entity_typeoptionalstring

Keep only entries about this kind of thing, such as customer or subscription.

If you leave it out: You get every kind.

actor_typeoptionalstring

Keep only entries made by this kind of actor.

If you leave it out: You get them all.

  • apiSomebody called the API with one of your keys.
  • systemA QuotaStack job did it. Renewals and expiry sweeps land here.
  • adminA person did it from the dashboard.
fromoptionalstring (date-time)

Return entries made at this moment or later. An RFC 3339 timestamp.

If you leave it out: You start at the oldest entry.

tooptionalstring (date-time)

Return entries made before this moment. The moment itself is left out.

If you leave it out: You run up to the newest entry.

cursoroptionalstring

Opaque pagination cursor from the previous page's pagination.next_cursor. Omit to start at the first page.

limitoptionalinteger

Page size. Default 20, max 100.

Response 200
{
  "data": [
    {
      "id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a81",
      "environment": "live",
      "actor_id": "system",
      "actor_type": "system",
      "action": "granted",
      "entity_type": "credit_transaction",
      "entity_id": "0192f5a4-7c31-7b8e-9a2d-4f6c8e1b3a32",
      "before_state": null,
      "after_state": {
        "delta": 500000,
        "type": "adjustment"
      },
      "created_at": "2026-07-28T09:00:00Z"
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}
Response fields
FieldTypeMeaning
datarequiredarray
data.actor_idrequiredstring

Who did it. The value is an API key ID, the name of a QuotaStack job, or a dashboard user ID. Read actor_type to know which of the three you are holding.

data.actor_typerequiredstring

What kind of actor made the change.

  • apiSomebody called the API with one of your keys.
  • systemA QuotaStack job did it. Renewals and expiry sweeps land here.
  • adminA person did it from the dashboard.
data.actionrequiredstring

The verb, on its own. created, updated, deleted, granted, adjusted, and imported are the ones you will see. Pair it with entity_type to know what happened.

data.entity_typerequiredstring

What kind of thing changed, such as customer, subscription, or credit_transaction.

data.entity_idrequiredstring (uuid)

Which one changed. Look it up with the matching read call for that kind.

data.before_stateoptionalobject

What the thing looked like beforehand.

If you leave it out: A create has nothing to show here, so the field reads null.

data.after_stateoptionalobject

What the thing looked like afterwards.

If you leave it out: A delete has nothing to show here, so the field reads null.

paginationrequiredobject

Cursor-based pagination envelope. Returned on every list endpoint. No total — cursor-only.

Errors

  • 400Malformed request.
  • 401Missing or invalid authentication.
  • 429Rate limit exceeded.
  • 500Unexpected server error.