---
title: "List rule runs"
description: "What your rules have actually done, one row per rule per message."
url: "https://openemail.uk/docs/api/rules/runs"
area: "API"
category: "Mailbox"
---

# List rule runs

What your rules have actually done, one row per rule per message.

`GET /rules/runs`

## GET /rules/runs

What your rules have actually done, one row per rule per message.

## Example

Needs `rules:read`. Newest first. `ruleId` narrows to one rule and `threadId` answers "why did this message end up here".

**curl**

```
curl "$OE/rules/runs?threadId=thr_5d31c2a8…&limit=25" -H "$AUTH"
```

**Response**

```
{
  "object": "list",
  "data": [
    {
      "object": "rule_run",
      "id": "rrun_9c1f0a4b7e05d3862c1f0a44",
      "ruleId": "rul_7f3a1c94e05d3862c1f0a44b",
      "ruleName": "Receipts to their own label",
      "threadId": "thr_5d31c2a8…",
      "messageId": "msg_c5f21cc6…",
      "sender": "receipts@stripe.com",
      "subject": "Your receipt",
      "actions": ["label", "archive"],
      "failures": [],
      "createdAt": "2026-08-29T11:04:12.000Z"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
```

> `actions` holds what was APPLIED and `failures` holds what was refused, as `type: reason`. They are separate lists rather than one annotated list because "the rule archived it" and "the rule tried to archive it" are different facts, and a log that conflates them cannot answer either question. These are bare action types. The values live on the rule, and `wouldApply` on a test is the one place they are spelled out.

> A suppressed auto-reply appears here, as `reply: auto-reply suppressed because the message carries List-Id`, and it is the only place it does. Nothing else surfaces a reply that deliberately did not go, and "why did my out-of-office not answer that" is otherwise unanswerable.

> `ruleName` is stored on the row rather than joined at read time, so the log still reads correctly after a rule is renamed or deleted. A row naming a rule that no longer exists is the normal case, not a dangling reference.

> The one-auto-reply-per-sender-per-day limit is enforced by a claim row in the same table, which this log does not return: it is why a second out-of-office to the same sender inside a day never fires.
