> ## Documentation Index
> Fetch the complete documentation index at: https://docs.watchdog.no/llms.txt
> Use this file to discover all available pages before exploring further.

# Alerts

> Find, review and resolve the problems Watchdog finds on invoices.

An alert is something on an invoice that doesn't follow the agreement, such as a price that is
higher than agreed. [Compliance checks](/api-reference/compliance-checks) create most alerts, and you
can [record your own](#record-your-own-alert). You review them and decide what to do.

Every alert has a status:

* **Pending**: new, waiting for someone to look at it.
* **Claimed**: part of a [claim](/api-reference/claims) you are raising with the supplier.
* **Credited**: the supplier has credited the amount.
* **Dismissed**: not something you will act on.

## Find alerts

```bash theme={null}
curl --get "$API_URL/v1/alerts" \
  -H "Authorization: Bearer $API_KEY" -H "X-Organization-Id: $ORGANIZATION_ID" \
  --data-urlencode "agreement_ids=$AGREEMENT_ID" \
  --data-urlencode 'statuses=pending' \
  --data-urlencode 'sort=impact_amount'
```

Filter by invoice, agreement, supplier, topic, claim, status and more. Each alert includes its
impact, the invoice line, and what Watchdog expected instead.

The same filters work across related endpoints, so what you count is what you act on:

* `GET /v1/alerts/metrics` returns counts and totals.
* `GET /v1/alerts/groups` groups them, for example by agreement or topic.
* `GET /v1/alerts/export?format=xlsx` downloads them as a spreadsheet (or `format=csv`).

To select alerts without a topic or claim, use the value `null`, as in `topic_ids=null`.

## Record your own alert

When you or your agent find a problem the check missed, record it with `POST /v1/alerts`. It then
counts and can be claimed like any other alert. Send `topic_id` to put it in a topic; without one it
stays uncategorized until Watchdog next sorts the agreement's alerts, after a check. To sort them
now, call `POST /v1/agreements/{id}/alert-topics/reconcile` and follow the returned workflow run.

```bash theme={null}
curl "$API_URL/v1/alerts" \
  -H "Authorization: Bearer $API_KEY" -H "X-Organization-Id: $ORGANIZATION_ID" \
  -H "Idempotency-Key: $(uuidgen)" -H 'Content-Type: application/json' \
  -d '{
    "invoice_id": "<invoice ID>",
    "agreement_id": "<agreement ID>",
    "title": "Order size discount not applied",
    "explanation": "Orders above USD 25,000 get a 5% discount [1].",
    "impact_amount": "966.00",
    "confidence": { "level": "certain" },
    "citations": [{
      "source_ref": 1,
      "citation": {
        "source": { "source_type": "document", "document_id": "<agreement document ID>" },
        "quote": "Orders above USD 25,000 receive a 5% discount."
      }
    }]
  }'
```

* The invoice must be matched to the agreement.
* `impact_amount` is in the invoice's currency, positive when the invoice charges more than
  agreed. For a line or a missing line you can leave it out and send `expected` prices instead,
  and Watchdog calculates it. An alert on the whole invoice needs `impact_amount`.
* To flag one invoice line, send its `invoice_item_id` with `correction_type: "modify_item"`. For a
  missing line use `add_item`; for the invoice as a whole, the default, `modify_invoice`.
* Send `topic_id` to put the alert in a topic. Without it, the alert stays uncategorized until
  Watchdog next sorts the agreement's alerts.
* Citations take the same sources as [editing](#edit-an-alert): a document quote, agreement prices,
  a web page or text you supply. Markers such as `[1]` in the text refer to them.

`provenance.origin` on every alert says who created it: `check`, `user` or `api_key`. A new check
or a check reset replaces alerts you created like any other, unless the alert is accepted in a claim
that is not cancelled.

## Resolve an alert

* `POST /v1/alerts/dismiss` with its ID in `alert_ids` dismisses it. Add a `category` and `note` to say why. Watchdog
  learns from this and may [suggest a change to the agreement's instructions](/api-reference/agreements#review-suggested-instruction-edits).
  Send `"suggest_instructions": false` when the note only explains a cleanup. The alert shows the
  reason as `dismissal`. To change it, dismiss the alert again with the new category and note; other
  alerts dismissed with it keep theirs.
* `POST /v1/alerts/credit` records that the supplier has credited it; `POST /v1/alerts/uncredit`
  removes a credit you recorded.
* `POST /v1/alerts/reopen` sets it back to pending. Credit is kept.

Repeating a command does nothing, so retries are safe. Alerts in a completed claim can't be changed.

## Resolve many alerts at once

`POST /v1/alerts/dismiss`, `/credit` and `/reopen` also work on many alerts at once. Send either a
list of `alert_ids`, or a `filter` that uses the same filters as the list:

```json theme={null}
{ "filter": { "topic_ids": ["<topic ID>"], "statuses": ["pending"] }, "category": "wrong_alert" }
```

A filter must name at least one agreement, invoice, topic or claim, so you can't change every alert
by accident. Use `GET /v1/alerts/metrics` with the same filter to see how many alerts you are about
to change.

## Delete alerts

`DELETE /v1/alerts/{id}` deletes an alert, and `POST /v1/alerts/delete` deletes many with the same
`alert_ids` or `filter`. An alert in a claim can't be deleted until you remove it from the claim.

To reject a wrong finding, dismiss it instead: the dismissal is kept, Watchdog learns from it, and a
new check could otherwise find the same problem again.

## Edit an alert

If an alert is almost right, correct it with `PATCH /v1/alerts/{id}`, sending only the fields you
change, including its `confidence` and `impact_amount`. Send the `ETag` from `GET /v1/alerts/{id}` as `If-Match`. A `412`
means someone else changed the alert: read it again before retrying. Editing doesn't re-run the
check.

## Topics

Watchdog groups similar alerts on an agreement into topics, such as "Freight charged above the agreed
rate", so you can review them together. Topics are updated automatically after each check.

* `GET /v1/alert-topics` lists them, and `topic_ids` filters alerts by topic. Topics without alerts
  are left out unless you add `include_empty=true`.
* `POST /v1/alert-topics` creates a topic on an agreement, optionally with `alert_ids` to move in.
* `PATCH /v1/alert-topics/{id}` renames or describes a topic.
* `DELETE /v1/alert-topics/{id}` deletes a topic. Its alerts stay, without a topic.
* `PATCH /v1/alert-topics/{id}` with `is_locked: true` keeps a topic's text as it is, so Watchdog
  doesn't rewrite it. You can still move alerts in and out.
* `POST /v1/alert-topics/{id}/alerts` moves alerts into a topic.

Watchdog puts new alerts into topics that already have alerts, and never merges or splits yours
on its own.
When a topic's last alerts are deleted, by you, a reset or a new check, the topic is removed too,
unless it's locked. A topic you emptied by moving its alerts out stays until you delete it.

## See which invoices have been checked

Zero alerts doesn't always mean an invoice is fine: it may not have been checked yet. Every invoice
has an `alert_summary` with its alert counts and whether all its checks are done. Filter invoices
with `check_statuses=not_checked,incomplete` to find the ones still waiting.

## When alerts disappear

If an invoice stops matching an agreement, its alerts for that agreement are set aside rather than
deleted. They drop out of lists and totals, keep their decisions and claims, and come back if the
invoice matches again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.