# Run bank rules

Operation ID: `runBankRules`

Group: Banking › Bank Rules

[Open in the interactive reference](https://docs.api.lensing.ai/lensing/v1/endpoints/runBankRules)

`POST /banking/bank-rules/run`

Retry-safe: A write that accepts Idempotency-Key: repeating a request with the same key replays the stored answer instead of executing twice.

Runs all active bank rules and matches bank transactions. Rules run one at a time, lowest `priority` first. For each unmatched bank transaction on its bank accounts that meets its criteria, a rule creates the bank entry or credit card entry its action object describes, with its journal entry, and matches the transaction to it with the status `autoMatched`. A transaction matched by one rule is no longer available to the rules after it. When every rule has run, match suggestions are refreshed for the transactions that are still unmatched.

The run finishes before the response is returned. The request takes no body.

A rule that cannot run is skipped and listed in `skippedBankRules`, and the other rules still run. A bank transaction for which a rule could not create its bank entry or credit card entry, or that entry's journal entry, is not reported. It is left out of `matchedBankTransactionIds` and stays unmatched. This happens, for example, when the transaction's accounting period is closed or the journal entry for the bank entry or credit card entry could not be created. A `matchedCount` of 0 still means the run succeeded.

Only one bank rule run can happen at a time in a tenant, including runs started in Lensing or on a schedule. A request made during another run returns `RUN_ALREADY_IN_PROGRESS` and changes nothing. It does not wait for the other run to finish.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | string · v1 | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |
| `Idempotency-Key` | header | string | no | An opaque caller-chosen string (1-255 characters) that makes this request safe to retry. Repeating the same key with an identical request body replays the original response instead of re-executing - but only once that original request succeeded; a failed attempt re-executes on retry. Repeating the key with a different body is answered with 422. A key still in flight is answered with 409 - as is a key whose original request was interrupted before it finished, for a few minutes afterwards, until that attempt is presumed dead. A completed response stays replayable for 24 hours. The key is scoped to the caller, not to the action: reusing it for a different action is answered with 409 or 422 rather than treated independently. On read actions this header is ignored. On write actions that cannot offer the guarantee it is answered with `400 IDEMPOTENCY_NOT_SUPPORTED` rather than silently ignored. |

## Response

`200` Success

Under `data` (runBankRulesOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `matchedCount` | number | yes | The number of bank transactions this run matched, across all rules. Example: `2`. |
| `matchedBankTransactionIds` | array<string> | yes | The unique identifiers for the bank transactions this run matched. Lists at most 500, so use matchedCount for the total. Example: `["6b87606e-ab22-479b-8b0b-3d79b1c0c611","2683e61d-f4ed-45bf-a3d8-63d81d138edd"]`. |
| `skippedBankRules` | array<object> | yes | The active rules that could not run. The other rules still ran. Example: `[{"bankRuleId":"9f2c6a10-7d34-4c8e-9b21-5a0f3e6d81b7","reason":"RULE_INCOMPLETE","message":"Bank rule BR-00042 cannot be run because it is missing criteria."}]`. |
| `skippedBankRules[].bankRuleId` | string | yes | The unique identifier for the skipped bank rule. |
| `skippedBankRules[].reason` | string | yes | Why the rule was skipped. Possible values: 'NO_ACCOUNTS_MAPPED' (the rule applies to no bank accounts), 'RULE_INCOMPLETE' (the rule has no criteria, or does not have exactly one action object), 'RUN_FAILED' (the rule failed while running, for example because every bank account it applies to is deleted or not ready), 'RULE_NOT_ACTIVE' or 'NOT_FOUND' (the rule was deactivated or deleted while the run was in progress). |
| `skippedBankRules[].message` | string | yes | A readable explanation of why the rule was skipped. |

```json
{
  "data": {
    "matchedCount": 2,
    "matchedBankTransactionIds": [
      "6b87606e-ab22-479b-8b0b-3d79b1c0c611",
      "2683e61d-f4ed-45bf-a3d8-63d81d138edd"
    ],
    "skippedBankRules": [
      {
        "bankRuleId": "9f2c6a10-7d34-4c8e-9b21-5a0f3e6d81b7",
        "reason": "RULE_INCOMPLETE",
        "message": "Bank rule BR-00042 cannot be run because it is missing criteria."
      }
    ]
  },
  "diagnostics": [
    {
      "code": "<code>",
      "message": "<message>",
      "severity": "error",
      "path": [
        "<path>"
      ],
      "details": "<details>"
    }
  ]
}
```

## Response headers

- `Idempotency-Replayed` — Present and `true` only when this response replays a previously stored one for the same Idempotency-Key, rather than reflecting a live execution. Absent on a live response - never sent as `false`.

## Errors

| Code | Status |
| --- | --- |
| `RUN_ALREADY_IN_PROGRESS` | 400 |
| `IDEMPOTENCY_KEY_CONFLICT` | 409 |
| `IDEMPOTENCY_PAYLOAD_MISMATCH` | 422 |

## Statuses

- `400` — Invalid request or business failure. Codes: RUN_ALREADY_IN_PROGRESS
- `401` — The request carries no valid access token.
- `403` — Not authorized
- `404` — Not found
- `409` — The Idempotency-Key is still being processed by another request.
- `422` — The Idempotency-Key was already used with a different request payload.
- `429` — Too many requests from this client address. The response has no body and no `Retry-After` header.
- `500` — Internal server error
