Skip to main content
Uploading an invoice takes two steps: upload the file and start the import. Watchdog does the rest on its own. If you want to follow the invoice until it has been checked, add the two optional steps. The Python example at the bottom does all four and can be used as it is.

Before you start

You need an API key with Write access, from Settings → Personal → API keys in Watchdog, and your organization ID, which is the org_… part of the address when your organization is open in Watchdog. Send both with every request:
Use api-canary.watchdog.no until api.watchdog.no moves over to the new API. After that, you only need to change the address.

1. Upload the file

Register the file, then send it to the upload address you get back, with exactly the headers you get back and without your API key.

2. Start the import

Attachments are uploaded the same way and listed in attachment_document_ids. That’s it: the invoice is on its way into Watchdog.

3. Wait for the import (optional)

Only needed if you want the invoice ID or the result of the check. Read the import every few seconds until it’s no longer queued or running:
When it’s completed with the outcome imported, invoice_id is your invoice. With duplicate, it points to the invoice Watchdog already had. With not_invoice, the file wasn’t an invoice and there’s nothing to follow.

4. Wait for the check (optional)

Read the invoice every few seconds until workflows.settled is true. Then alerts has the result of checking it against your agreements.

Good to know

  • The invoice must be a PDF or XML file (Peppol BIS Billing 3.0 or EHF 2.0). Attachments can be any file type.
  • Sending the same invoice twice is safe: you get the existing invoice back.
  • Send an Idempotency-Key header when starting an import. If the request times out, send it again with the same key and you get the same import back instead of a new one.
  • Include error.request_id when you contact us about an error.

Python example

The script uploads an invoice with any attachments, waits for the import and the check, and prints the result. It retries temporary errors on its own. It needs Python 3.9 or newer and requests.
watchdog_upload_example.py