curl --request GET \
--url http://localhost:3500/v1/alerts/metrics \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('http://localhost:3500/v1/alerts/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "http://localhost:3500/v1/alerts/metrics"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"total_count": 123,
"invoice_count": 123,
"counts": {
"pending": 1,
"claimed": 1,
"dismissed": 1,
"credited": 1
},
"currencies": [
{
"currency_code": "<string>",
"alert_count": 123,
"missing_amount_count": 123,
"impact_amount": "<string>"
}
],
"organization_currency": {
"currency_code": "<string>",
"impact_amount": "<string>",
"missing_amount_count": 123,
"impact_by_status": {
"pending": "<string>",
"claimed": "<string>",
"credited": "<string>",
"dismissed": "<string>"
}
}
}{
"error": {
"code": "validation_error",
"message": "Invalid request format, parameters, or body. Details contain up to 20 actionable field errors; the complete encoded request body must be at most 2 MiB (2,097,152 bytes).",
"request_id": "req_example"
}
}{
"error": {
"code": "invalid_token",
"message": "Missing or invalid bearer credential.",
"request_id": "req_example"
}
}{
"error": {
"code": "forbidden",
"message": "Access denied: forbidden, token_disabled, organization_required, insufficient_role, or mfa_required. Check the error code and effective permissions.",
"request_id": "req_example"
}
}{
"error": {
"code": "not_found",
"message": "The resource does not exist in the current organization.",
"request_id": "req_example"
}
}{
"error": {
"code": "conflict",
"message": "One or more selected teams have invalid saved filter rules. Update the team filters before retrying.",
"request_id": "req_example"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "The IP or authenticated credential exceeded its request limit.",
"request_id": "req_example"
}
}{
"error": {
"code": "internal_error",
"message": "Unexpected server failure. Include the request ID when contacting support.",
"request_id": "req_example"
}
}{
"error": {
"code": "service_unavailable",
"message": "Authentication infrastructure is unavailable or rate limited. Honor Retry-After when provided.",
"request_id": "req_example"
}
}Get alert totals
curl --request GET \
--url http://localhost:3500/v1/alerts/metrics \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('http://localhost:3500/v1/alerts/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "http://localhost:3500/v1/alerts/metrics"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"total_count": 123,
"invoice_count": 123,
"counts": {
"pending": 1,
"claimed": 1,
"dismissed": 1,
"credited": 1
},
"currencies": [
{
"currency_code": "<string>",
"alert_count": 123,
"missing_amount_count": 123,
"impact_amount": "<string>"
}
],
"organization_currency": {
"currency_code": "<string>",
"impact_amount": "<string>",
"missing_amount_count": 123,
"impact_by_status": {
"pending": "<string>",
"claimed": "<string>",
"credited": "<string>",
"dismissed": "<string>"
}
}
}{
"error": {
"code": "validation_error",
"message": "Invalid request format, parameters, or body. Details contain up to 20 actionable field errors; the complete encoded request body must be at most 2 MiB (2,097,152 bytes).",
"request_id": "req_example"
}
}{
"error": {
"code": "invalid_token",
"message": "Missing or invalid bearer credential.",
"request_id": "req_example"
}
}{
"error": {
"code": "forbidden",
"message": "Access denied: forbidden, token_disabled, organization_required, insufficient_role, or mfa_required. Check the error code and effective permissions.",
"request_id": "req_example"
}
}{
"error": {
"code": "not_found",
"message": "The resource does not exist in the current organization.",
"request_id": "req_example"
}
}{
"error": {
"code": "conflict",
"message": "One or more selected teams have invalid saved filter rules. Update the team filters before retrying.",
"request_id": "req_example"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "The IP or authenticated credential exceeded its request limit.",
"request_id": "req_example"
}
}{
"error": {
"code": "internal_error",
"message": "Unexpected server failure. Include the request ID when contacting support.",
"request_id": "req_example"
}
}{
"error": {
"code": "service_unavailable",
"message": "Authentication infrastructure is unavailable or rate limited. Honor Retry-After when provided.",
"request_id": "req_example"
}
}Authorizations
Personal API key. Send X-Organization-Id. The required cumulative level is listed in x-watchdog-permission.
Headers
Required for personal API keys. Target one organization you have access to. Migrated keys may omit it to use their original organization. For Clerk sessions, it must match the active organization.
Query Parameters
Match the shared teams the authenticated user belongs to in this organization. Teams combine with OR; other filters combine with AND. No memberships or saved rules means no matches. Cannot be combined with team_ids when true.
true, false Shared team IDs (maximum 50; comma-separated in a query string, a JSON array in a command body). Teams combine with OR. Missing, foreign, or personal teams return 404; invalid saved rules return 409.
Match alerts currently attached to any selected claim; null matches alerts in no claim. Removed or transferred attachments are excluded. Claim status does not restrict matches; use claim_statuses.
Use false to select alerts that are not currently attached to any claim.
true, false Match alerts whose current claim has any of these statuses.
Leave out alerts on any of these invoices.
Leave out alerts for any of these agreements.
Leave out alerts for any of these suppliers.
Leave out alerts on invoices for any of these recipients. Alerts on invoices without a recipient still match.
Match alerts in any selected topic; null matches uncategorized alerts.
Leave out alerts in any of these topics. Uncategorized alerts still match.
Use false to select uncategorized alerts.
true, false Match any listed confidence level; null matches alerts without one.
current, outdated, unknown Minimum impact in the organization currency, inclusive. Alerts without an impact never match.
100^-?\d+(?:\.\d+)?$Maximum impact in the organization currency, inclusive. Alerts without an impact never match.
100^-?\d+(?:\.\d+)?$Invoice issued on or after this date.
^\d{4}-\d{2}-\d{2}$Invoice issued on or before this date.
^\d{4}-\d{2}-\d{2}$Created on or after this calendar date in the organization's timezone.
^\d{4}-\d{2}-\d{2}$Created on or before this calendar date in the organization's timezone.
^\d{4}-\d{2}-\d{2}$Matches, ignoring case, the alert title, explanation and expected line; the supplier; the invoice number, title and line; the agreement title; or the topic title and description. A UUID also matches the alert, invoice, supplier or agreement ID.
1 - 200Response
Counts, distinct invoices, and amounts per currency and in the organization currency, using the same filters as the alert list.
Distinct invoices among the matching alerts.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Impact converted with the rate stored on each alert. Alerts without a converted impact contribute zero and are counted in missing_amount_count.
Show child attributes
Show child attributes