Skip to main content
An agreement tells Watchdog what a supplier has agreed to: who it covers, when it applies, what things cost, and the contract documents behind it. Watchdog matches invoices to your agreements and checks them against the terms and prices. Reading needs an API key with Read access; everything else on this page needs Write.

Create an agreement

Look up the supplier and recipient IDs with GET /v1/suppliers and GET /v1/recipients, then create the agreement:
A few things to know:
  • Choose at least one supplier. An agreement without suppliers matches no invoices. No recipients means any recipient.
  • Status is draft unless you say otherwise. An active agreement needs a title. You can edit an agreement, its prices and its documents in every status, including archived.
  • Applicability narrows which invoices the agreement covers, for example only invoices with a certain buyer reference or delivered to a certain country.
  • Instructions give the checks extra context in plain language, such as which schedule to use when the documents disagree.

Edit an agreement

PATCH /v1/agreements/{id} changes only the fields you send. Lists such as supplier_ids and tag_ids, and objects such as applicability, replace the whole value, so send the complete list or object. To avoid overwriting someone else’s change, send the ETag from GET /v1/agreements/{id} as If-Match. A 412 means the agreement changed in the meantime: read it again and reapply your edit. Saving never re-matches invoices or re-runs checks. After changing suppliers, recipients, dates or applicability, refresh the matched invoices.

Add prices

Send one or more prices as an array. A price is either a fixed amount or a rate, such as a fee of 7.5% of the invoice subtotal:
Amounts are decimal strings, and rates are fractions: "0.075" means 7.5%. PATCH on the same path changes up to 100 prices at once, sent the same way as entries with each price’s id. Each request succeeds or fails as a whole. GET …/price-items lists the prices. Narrow it with search, or with filters, a JSON array of conditions that must all match, and order it with sort and direction:
The same parameters work for GET …/price-items/export, which downloads the prices as CSV, and as a JSON body for POST …/price-items/delete, which removes every matching price however many there are. To remove specific prices, send {"ids": [...]}.

Upload and import a source

Contract documents and price lists are added in two steps. First upload the file as described in Upload invoices. Then add it to the agreement with the document_id you got back:
The optional Idempotency-Key prevents duplicate admission, so a retry never adds the file twice. Watchdog prepares the file in the background and works out whether it holds the terms or a price list. You can change that with PATCH /v1/agreements/{id}/documents/{document_id}. Checks read the terms documents. Prices from a price list are only added when you import them.

Import prices from a document

Watchdog can read the prices from one or more price lists for you:
Each document gets its own price import, and they run together in one workflow run. This usually takes a few minutes. Follow the run, or read GET …/price-imports/{import_id} until each import has finished; one document failing doesn’t stop the others.
  • Adding or replacing. By default the new prices are added to the ones already there. Set mode to replace_document to replace the prices from earlier imports of the same document, or to replace_all to replace every price. If the import fails, nothing is removed.
  • Checking the result. GET …/price-imports/{import_id}/download gives you every row Watchdog found and whether it was added, skipped as a duplicate or rejected.
  • Importing again. Importing a document again with the same file and settings returns its existing import, marked reused.
  • Incomplete extraction. If the import fails with extraction_incomplete, try again with instructions that say where the prices are, or with the worksheets that hold them.

Handle renewals

Each agreement has a renewal_action that tells you what’s due next, for example that it must be cancelled by a certain date. List the agreements with a deadline coming up:
To record your decision, edit the agreement with renewal_action: {"type": "cancel", "expiration_date": "…"} ends it on that date, and {"type": "extend"} extends it by one renewal period. Like any edit, send the agreement’s ETag in If-Match.

Organize with tags

Create tags with POST /v1/agreements/tags and list them with GET /v1/agreements/tags. Assign them with tag_ids when you create or edit an agreement, and filter agreements with tag_ids.

Review suggested instruction edits

When someone dismisses an alert and says why, Watchdog may suggest a change to the agreement’s instructions so the same alert isn’t raised again. List the suggestions with GET /v1/agreements/{id}/context-suggestions, then accept or reject each one with POST …/context-suggestions/{suggestion_id}/accept or /reject. Accepting edits the instructions; rejecting makes sure the same edit isn’t suggested again.

See matched invoices and spend

Use the invoice endpoints with agreement_ids:
  • GET /v1/invoices?agreement_ids=$AGREEMENT_ID lists the invoices matched to the agreement.
  • GET /v1/invoices/metrics?agreement_ids=$AGREEMENT_ID counts them and totals the spend. Add issued_from and issued_through for a period.
Totals are given per currency. Don’t add different currencies together.

Delete an agreement

DELETE /v1/agreements/{id} removes the agreement. There is no undo. While Watchdog is still working on the agreement, deletion returns 409: wait a little, and try again.