curl --request POST \
--url https://api-canary.watchdog.no/v1/agreements/{id}/price-imports \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"entries": [
{
"document_id": "11111111-1111-4111-8111-111111111111",
"worksheets": [
"Prices 2026"
],
"default_currency": "NOK"
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
entries: [
{
document_id: '11111111-1111-4111-8111-111111111111',
worksheets: ['Prices 2026'],
default_currency: 'NOK'
}
]
})
};
fetch('https://api-canary.watchdog.no/v1/agreements/{id}/price-imports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api-canary.watchdog.no/v1/agreements/{id}/price-imports"
payload = { "entries": [
{
"document_id": "11111111-1111-4111-8111-111111111111",
"worksheets": ["Prices 2026"],
"default_currency": "NOK"
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entries": [
{
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"admission": "created",
"price_import": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agreement_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"origin": "workflow",
"worksheets": [
"<string>"
],
"instructions": "<string>",
"default_currency": "<string>",
"mode": "add",
"status": "queued",
"counts": {
"created": 1,
"duplicate": 1,
"invalid": 1,
"replaced": 1
},
"failure": {
"code": "<string>",
"message": "<string>"
},
"extraction_source_import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_item_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
]
}{
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entries": [
{
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"admission": "created",
"price_import": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agreement_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"origin": "workflow",
"worksheets": [
"<string>"
],
"instructions": "<string>",
"default_currency": "<string>",
"mode": "add",
"status": "queued",
"counts": {
"created": 1,
"duplicate": 1,
"invalid": 1,
"replaced": 1
},
"failure": {
"code": "<string>",
"message": "<string>"
},
"extraction_source_import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_item_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
]
}{
"error": {
"code": "validation_error",
"message": "The request is invalid. details lists up to 20 field errors. Request bodies are limited to 2 MiB.",
"request_id": "req_example"
}
}{
"error": {
"code": "invalid_token",
"message": "The bearer token is missing or invalid.",
"request_id": "req_example"
}
}{
"error": {
"code": "forbidden",
"message": "Access denied. The error code says why: forbidden, token_disabled, organization_required, insufficient_role or mfa_required.",
"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": "A document file is missing or changed. Upload it again.",
"request_id": "req_example"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Wait for the Retry-After delay before retrying.",
"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": "The import could not be confirmed as started. Check the workflow run at Location before retrying.",
"request_id": "req_example"
}
}Import prices from Documents
Reads the prices in 1–200 documents linked to this agreement and adds them, in one workflow run. Each document has its own worksheets, instructions and default currency, and succeeds or fails on its own. Duplicates and rows that break the price rules are skipped; mode decides whether existing prices are replaced. Importing a document again with the same file and settings returns its existing import (reused) and starts nothing. Repeating a request with the same Idempotency-Key returns its original result. Follow the run, and read each price import for its outcome; afterwards you can download every extracted row with its outcome.
curl --request POST \
--url https://api-canary.watchdog.no/v1/agreements/{id}/price-imports \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"entries": [
{
"document_id": "11111111-1111-4111-8111-111111111111",
"worksheets": [
"Prices 2026"
],
"default_currency": "NOK"
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
entries: [
{
document_id: '11111111-1111-4111-8111-111111111111',
worksheets: ['Prices 2026'],
default_currency: 'NOK'
}
]
})
};
fetch('https://api-canary.watchdog.no/v1/agreements/{id}/price-imports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api-canary.watchdog.no/v1/agreements/{id}/price-imports"
payload = { "entries": [
{
"document_id": "11111111-1111-4111-8111-111111111111",
"worksheets": ["Prices 2026"],
"default_currency": "NOK"
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entries": [
{
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"admission": "created",
"price_import": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agreement_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"origin": "workflow",
"worksheets": [
"<string>"
],
"instructions": "<string>",
"default_currency": "<string>",
"mode": "add",
"status": "queued",
"counts": {
"created": 1,
"duplicate": 1,
"invalid": 1,
"replaced": 1
},
"failure": {
"code": "<string>",
"message": "<string>"
},
"extraction_source_import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_item_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
]
}{
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entries": [
{
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"admission": "created",
"price_import": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agreement_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"origin": "workflow",
"worksheets": [
"<string>"
],
"instructions": "<string>",
"default_currency": "<string>",
"mode": "add",
"status": "queued",
"counts": {
"created": 1,
"duplicate": 1,
"invalid": 1,
"replaced": 1
},
"failure": {
"code": "<string>",
"message": "<string>"
},
"extraction_source_import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_run_item_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
]
}{
"error": {
"code": "validation_error",
"message": "The request is invalid. details lists up to 20 field errors. Request bodies are limited to 2 MiB.",
"request_id": "req_example"
}
}{
"error": {
"code": "invalid_token",
"message": "The bearer token is missing or invalid.",
"request_id": "req_example"
}
}{
"error": {
"code": "forbidden",
"message": "Access denied. The error code says why: forbidden, token_disabled, organization_required, insufficient_role or mfa_required.",
"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": "A document file is missing or changed. Upload it again.",
"request_id": "req_example"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Wait for the Retry-After delay before retrying.",
"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": "The import could not be confirmed as started. Check the workflow run at Location before retrying.",
"request_id": "req_example"
}
}Authorizations
Personal API key sent as a bearer token, together with X-Organization-Id. The key must have at least the access level the endpoint requires (read, write or admin).
Headers
The organization to act in. Required for personal API keys; list the organizations you can access with GET /v1/organizations.
Optional protection for safely retrying a request after a timeout or lost response. Choose a unique value (for example, a UUID) for each action and reuse it with the same input when retrying. Omit it for a normal request.
1 - 200^[\x21-\x7e]+$Path Parameters
Body
1–200 distinct documents linked to this agreement, each with its own settings.
1 - 200 elementsShow child attributes
Show child attributes
add keeps existing prices; replace_document replaces the prices earlier imports of each document created; replace_all replaces every price on the agreement, once. Nothing is deleted unless an import finds valid prices.
add, replace_document, replace_all Read the file again instead of reusing the rows from an earlier import of the same file and settings.