Skip to main content
This contract belongs to the Worker development preview. It is not served by the public API yet.

Create a claim

The response is a pending claim with a Location header. Creation requires an active or archived agreement. Titles are limited to 200 characters and need not be unique. Creation is not idempotent; inspect the list after an uncertain response before creating again. Send alerts to add alerts in the same transaction. It takes the same selection and rules as POST /v1/claims/{id}/alerts (see Review and curate alerts). If the request fails, for example because an alert in alert_ids is already in another claim, no claim is created. A filter skips alerts that do not qualify; read the created claim for its counts.

Review and curate alerts

Lists use cursor pagination. The filtered alerts endpoint returns canonical alert summaries for currently attached alerts, including dismissed alerts. Removed and transferred alerts are excluded. Follow GET /v1/alerts/{id} for retained evidence and invoice references. Add/remove/transfer commands take an alert selection: up to 5000 distinct alert_ids, or a filter that uses the alert list filters as JSON, such as {"filter":{"topic_ids":["TOPIC_ID"]}} to claim a whole topic. Each command is one transaction and returns changed_count and skipped_count. With alert_ids, adding an alert already in another claim conflicts; with a filter it is skipped. Use /alerts/transfer with a selection and target_claim_id to move alerts explicitly. Use /alerts/remove to detach an alert. Claimed alerts return to pending; pending, dismissed, and credited alerts retain their status. Adding or transferring an alert preserves dismissed and credited verdicts; pending alerts become claimed. To pursue a dismissed or credited member, reopen it with POST /v1/alerts/reopen (select credited alerts by alert_ids; a filter skips them). It stays attached to a pending or in-progress claim, and adding it again claims it. summary groups aggregates into total, pending, claimed, credited, and dismissed. Each contains alert_count, invoice_count, topic_count, and impact_by_currency entries with currency_code and an exact decimal-string amount. Use summary.claimed for the amounts being pursued; pending, credited, and dismissed alerts remain attached but are excluded from that group. The app claim amount is claimed plus credited impact; summary.total includes all attached statuses. Credited impact is independent of recorded credits and refunds. Null alert impacts contribute zero. An empty population has zero counts and an empty currency array. Invoice and topic counts are distinct within each population. Alerts without a topic do not contribute to topic_count. Topics represented in multiple statuses count in each group but only once in total. An invoice with both claimed and dismissed alerts appears in both status groups but only once in total, so status invoice counts are not necessarily additive. Removed or transferred alerts do not contribute. For example, the same invoice can contain claimed and dismissed alerts:
Claim responses expose the agreement through agreement: { id, title }; creation still accepts agreement_id. Empty claims have zero counts and an empty currency array. There is no currency conversion or refund subtraction. Use GET /v1/alerts/metrics?claim_ids=CLAIM_ID&statuses=claimed for amounts restricted to claimed alerts.

Change lifecycle

Cancellation dismisses attached pending and claimed alerts while retaining membership and evidence. Dismissed and credited alerts keep their verdicts and earlier dismissal feedback. Reopening to pending or in_progress changes only claim status. A completed claim must be reopened before cancellation. Only pending/in-progress claims receive alerts; completed claims lock membership changes, while cancelled claims may remove or transfer alerts. PATCH /v1/claims/{id} edits only the title. To permanently delete a claim, use POST /v1/claims/{id}/delete with an explicit alert_outcome of pending or dismissed. Deletion removes the claim and its dependent records; alerts, dismissal snapshots, and activity remain. The deleted claim is no longer retrievable. Queries require Read permission and commands require Write. These commands do not start checks. Deleting with alert_outcome=dismissed and a category or note starts a dismissal-context suggestion run, as dismissing an alert does; cancellation does not, because its Claim cancelled note is not feedback about the agreement. Exports remain a separate workflow.

Errors and retries

Repeating an unchanged title or status is a no-op. Repeating an already-satisfied add creates no membership or activity; adding a dismissed or credited member preserves its verdict. Creation can produce another claim when retried and has no idempotency receipt. Removing a dismissed or credited member, or deleting its claim with alert_outcome=pending, preserves its verdict. Claimed members return to pending. Dismissal snapshots remain available as evidence. Dismissal feedback is accepted only with alert_outcome=dismissed.

Filter alerts by claim

Use claim_ids with alert lists, metrics, or groups to select alerts currently attached to one or more claims. Comma-separated IDs combine with OR; other filters combine with AND. Missing or foreign claim IDs match no alerts. Removed attachments are excluded, while dismissed alerts on cancelled claims remain included unless filtered out by alert status.
Topic groups contain counts and currency totals for the matching alerts only. Add topic_ids=null (or has_topic=false) for matching alerts without a topic, and use claim_ids=null for alerts in no claim. Keep claim_ids unchanged when following a cursor. Explicit alert dismissal keeps the alert attached to its claim. Returning an alert to pending also retains its attachment to a pending or in-progress claim. Use the claim remove command to detach it. Reopening an alert on a cancelled claim releases that attachment.

Refunds and credit-note evidence

A refund records money credited or paid back, excluding VAT. Credit-note attachments are supporting evidence: they never add to refunded totals unless a refund record is created explicitly. Refunds can be recorded and edited on completed or cancelled claims without changing claim status. All paths below follow /v1/claims/{id}: Both lists use the standard cursor pagination (50 by default, maximum 100). Refunds sort by creation time and ID descending; credit notes sort by invoice creation time and ID descending. Cursors are bound to the organization and parent claim. Find candidate credit notes with the invoice list, scoped to the claim’s suppliers: GET /v1/invoices?categories=credit_note&supplier_ids=SUPPLIER_IDS&search=TERM&sort=issued_date. It returns the completed, nondeleted credit notes of those suppliers, which is what attachment checks; a note already attached to this claim returns 409. A claim without suppliers has no candidates.

Record and edit a refund

Creation returns 201, Location, and ETag. Amounts are positive decimal strings (up to 100 characters), stored without rounding. Currency is required and normalized to three uppercase letters. Neither amount nor currency is inferred from the linked note or organization. Links may cross currencies: linking evidence never changes an existing refund’s amount or currency. Each refund is its own resource; there is no batch command. To record refunds and complete a claim, write each refund, then call the transition command. The refund resource contains id, amount, currency_code, nullable comment, nullable credit_note_id, nullable created_by_user_id, created_at, and updated_at.
PATCH preserves omitted fields. Null clears the comment or link; amount and currency cannot be null. An unchanged edit is a no-op. Optional If-Match protects edits and deletion against stale amount, currency, comment, or link state. Unlinking or deleting a refund preserves the direct note attachment. Legacy refunds without currency retain the existing organization-currency fallback (NOK if unset); an edit persists that currency explicitly. New writes always supply currency.

Attach and remove evidence

create_refund defaults to false. When true, attachment and refund creation are atomic: the refund uses the absolute net credit-note amount and the note’s currency. Missing/zero amounts or missing currency reject automatic refund creation; evidence-only attachment remains available. Supplier and credit-note eligibility rules still apply. An attachment can link one refund, and a refund can link one note; the API does not allocate a note globally across claims. Evidence contains a canonical credit_note invoice summary, matched_invoices, and nullable direct_attachment. matched_invoices lists the claim invoices the note is matched to as {id, title} references, where title is the invoice number, ordered by invoice number (missing numbers last) and ID. The attachment contains attached_at, refund_created_by_attachment, and the nullable linked refund. A note can have both direct and invoice-derived evidence and appears once.
Use keep to preserve any linked refund. delete_generated may delete only the refund generated by that attachment and requires a current strong ETag from the relationship GET. Missing, weak, or wildcard preconditions return 428; a stale ETag returns 412. Removing direct evidence never changes invoice matches, so the note may remain visible as invoice-derived evidence. Removal returns 204. Duplicate attachment or conflicting links return 409. Repeated refund deletion or direct-attachment removal returns 404. Creation is non-idempotent; inspect the current state after an uncertain response before retrying. There is no idempotency receipt or automatic currency conversion.

Refund totals

Claim list/detail responses and claim metrics include a separate refund_summary:
Totals aggregate refund records independently of alerts and credit-note joins, using the same claim filters. Empty results have count zero and an empty array. The existing summary.total, summary.pending, summary.claimed, summary.credited, and summary.dismissed describe alerts and remain unchanged. No outstanding balance, conversion, or allocation is calculated.

Claim list presentation

suppliers contains {id, name} references for the agreement’s suppliers, sorted by name and ID. Legacy claims without agreement suppliers fall back to suppliers of currently attached alerts on nondeleted, nonduplicate invoices. Supplier filters and supplier-name search use this same population, including empty claims with agreement suppliers. Multiple suppliers never duplicate a claim or its totals.
For status sections, use the metrics status counts and fetch each section with statuses and its own cursor. Grouping loaded rows is also possible, but a single page does not represent every status’s complete contents. creator_user_ids selects creators. Use mine=true to select the current user’s shared teams, or team_ids to select teams explicitly; claims match through their agreement.

Claim documents

Lists the source documents of the completed, nondeleted invoices whose alerts are attached to the claim, one item per invoice: {"invoice":{"id":"…","title":"10442"},"documents":[…]}. title is the invoice number, and documents are InvoiceDocument entries, primary first, as in GET /v1/invoices/{id}/documents. Invoices without documents are omitted. Items are ordered by invoice number (missing numbers last) and ID, with standard cursor pagination. A missing or foreign claim returns 404. Credit-note evidence is listed by GET /v1/claims/{id}/credit-notes; read a note’s files with GET /v1/invoices/{id}/documents. Download a file with GET /v1/documents/{id}/download.

Claim exports

Download CSV, XLSX or PDF with one authenticated request. Every format uses the same endpoint and returns file bytes directly with a download filename. Read permission is sufficient.
The response is 200, with Content-Disposition: attachment and the appropriate content type. There is no export resource, workflow, polling, or saved artifact. Repeating the request generates a fresh file from a consistent database snapshot.
  • format is required: csv, xlsx, or pdf.
  • Claimed findings are always included; dismissed findings are never exported.
  • include_pending and include_credited accept true or false and default to false. Pending findings join claimed findings in the outstanding bucket; credited findings appear separately.
  • Only currently attached alerts are included; removed/transferred alerts stay excluded. Invoice eligibility and claim lifecycle status do not hide the selected attached findings.
  • CSV contains alert rows with topic, invoice, status, currency, exact decimal amounts, explanation, and citations. Formula-like user-authored cells are prefixed with an apostrophe.
  • XLSX contains those alert rows and a separate refund-summary sheet. Amounts and invoice numbers use text cells to preserve precision and leading zeros. Spreadsheet software may round imported CSV numbers automatically; use XLSX when exact spreadsheet values matter.
  • PDF summarizes each topic once using stored descriptions and key questions, with up to two invoice examples per topic and up to two selected sources per topic/example. Examples represent selected statuses and prefer different invoices. Counts and amounts cover the entire selected population; examples do not change totals. Links lead to the full supporting detail in the app. Use CSV/XLSX for every alert row. Refunds stay separate. Headings are English; source text retains its language.
  • Missing alert impacts contribute zero. Amounts keep their original currencies. Only refund records contribute to refunded totals; credit-note evidence never adds money.
For example, save the file directly using your usual bearer credential and organization header:
Invalid format/flag values return 400; missing, deleted or inaccessible claims return 404. Exporting never changes the claim. Source invoice and credit-note files remain available through GET /v1/documents/ID/download; the claim export does not combine them into a ZIP. PDF amounts use currency-specific decimal places and round half up for display, after aggregation. API, CSV, and XLSX amounts retain their exact precision.

My records and teams

Use mine=true or explicit team_ids to filter by shared team rules. See My records and teams for matching rules, empty results, errors, and pagination.