ComplianceCheck, including evaluations that found nothing. Work that fails or is
cancelled never produces a check.
409 conflict until you supply
agreement_ids. New work returns 202 with workflow_run_id and a Location header. Starting, retrying
and cancelling require Write access. Reading checks, findings and workflow status requires Read.
What is eligible
The invoice must be completed, not a credit note, not covered by an active credit-note match, and have a primary document. The agreement must be matched to the invoice, active, and ready: it has a supplier, a title, usable content, and every terms document has finished processing. Matching is a separate command and is not run by a check. No claim may hold the pair: an invoice and agreement pair is not checked again while a claim that is not cancelled holds one of its alerts that is not dismissed. A check replaces all of a pair’s alerts, so this keeps claimed alerts, and the rest of that evaluation, as they were claimed.Idempotency-Key is optional. A replay returns 200 with the original run. Without a key, the
in-progress guard still prevents two checks of the same pair from running at once.
Follow the work
One workflow run groups the request. One item evaluates one invoice and agreement pair. The selected agreements, the agreement version and the invoice fingerprint are captured at admission.result contains compliance_check_id, finding_count and completeness. A
failed item carries one of these codes:
Cancel with
POST /v1/workflow-runs/{id}/cancel. Cancelled work never replaces current findings.
Retry
item_ids. Eligibility is verified again and current inputs are captured. Completed items
are never rerun by retry. To reevaluate a completed pair, submit a new check.
Read results
GET /v1/compliance-checks lists completed checks, newest first. Filter with invoice_id,
agreement_id, completed_from and completed_through. GET /v1/compliance-checks/{id}/findings
returns the findings in their original order. Each finding has its own stable id.
GET /v1/compliance-checks/{id}/transcript shows how the check reached its result: the display
form of each tool call, in order, followed by its final summary when it fits the transcript size
limit. Prompts and reasoning are not retained. completed_from and completed_through are calendar dates in your organization’s
timezone.
A check records what it read: the agreement version, the invoice fingerprint, and the identity and
checksum of each source document. Each finding carries the invoice line values, the expected values,
the cited excerpts and the referenced price item values as they were at publication. None of this
changes when the invoice is edited, a price is deleted, a document is unlinked, or the resulting
alert is edited or dismissed.
freshness is derived when you read a check. outdated means the invoice evidence or the agreement
version has changed since. The check itself is unchanged. The newest check for a pair is first in the
list.
Check an agreement
GET /v1/invoices?agreement_ids=$AGREEMENT_ID&alert_scope=selected_agreements&alert_checked=false&alert_checkable=true
lists, apart from invoices already being checked, invoices without a primary document and pairs
a claim holds. Send {"invoice_ids": [...]} (up to 20) to check
a sample of them. Completed checks are kept, including outdated ones; check the invoice to
re-evaluate one. The response is 202 with workflow_run_id, invoice_count and has_more: one
request takes at most 5000 invoices, newest first, so repeat it after the run when has_more is
true. The agreement must be active and ready (409 agreement_not_checkable); with nothing to check
the response is 409 nothing_to_check and nothing starts.
POST /v1/agreements/check does the same for every active, ready agreement and returns
workflow_run_ids, one agreement check each, and has_more. The 5000-invoice limit applies to the
request in total, filled agreement by agreement in ID order, newest invoices first. Every admitted
run is returned: one whose dispatch failed fails, its items with dispatch_failed, and one whose
acceptance was not confirmed either starts or, if it has not started five minutes after admission,
fails with admission_expired items. Either way its invoices are unchecked again.
With nothing to check it returns 200 with an empty list.
An invoice check captures its inputs at admission; an agreement check’s item reads them when it
starts, so stale_input means they changed after that. /check/retry applies to invoice checks
only: to retry an agreement check, request it again, since failed and cancelled pairs count as
unchecked.
Items otherwise behave like invoice check items, with the same failure codes. A pair whose agreement is deactivated,
or that a claim comes to hold, while the check waits fails not_eligible without replacing its
alerts (a pair a claim holds keeps its last result), so agreements can be edited or deactivated during a check.
Recheck a topic
POST /v1/alert-topics/{id}/recheck checks the topic’s agreement again against every invoice
behind the topic’s alerts, completed checks included, as one agreement check. Each invoice’s check
replaces all of that invoice’s alerts for the agreement, including alerts in other topics; dismissed
or credited alerts come back as new pending alerts if the check finds them again. Invoices a claim
holds, invoices already being checked and invoices that cannot be checked are left as they are and
counted in skipped_count. The response is 202 with workflow_run_id, invoice_count and
skipped_count; with nothing to recheck it is 409 nothing_to_check. A pair whose check fails
keeps its alerts and counts as unchecked, so the next agreement check retries it. A recheck is not
idempotent: once its run finishes, the same request starts a new one.
Reset checks
POST /v1/invoices/{id}/check/reset and POST /v1/agreements/{id}/check/reset start an invoice’s or
an agreement’s evaluation over: unfinished checks are cancelled, the pairs’ alerts are deleted, and
every pair is marked unchecked so an agreement check picks it up again. A pair a claim holds keeps
its alerts and its result. Completed checks are kept. The response reports deleted_alert_count,
kept_alert_count and cancelled_check_count.
When matching removes an invoice’s match to an agreement, that pair is reset the same way, so only
a pair a claim holds keeps its alerts after losing its match.
How checks relate to alerts
Publishing a check replaces all of the pair’s previous alerts with its findings, including dismissed or credited ones, which come back as new pending alerts if the check finds them again. A pair a claim holds is never checked, so its alerts stay as they were claimed. A finding’salert_id names
the alert it became. A later check may replace that alert, and the finding
keeps the original id. An alert’s
provenance.retained_check links back to the check that produced it. The invoice alert_summary
reports running, failed, cancelled and outdated checks from the same work.