> ## Documentation Index
> Fetch the complete documentation index at: https://docs.watchdog.no/llms.txt
> Use this file to discover all available pages before exploring further.

# Import prices from several Documents

> Admits up to 200 distinct linked Documents as items of one agreement price-import run. Each file has its own worksheets, instructions and default currency; one mode applies across the selection. Files settle independently, so a failed file does not undo successful siblings. replace_all removes existing prices once, when the first file with valid prices commits. An add of identical bytes and settings may reuse an active or completed import instead of starting new work. Poll the returned run and per-file imports for outcomes.



## OpenAPI

````yaml /openapi-preview.json post /v1/agreements/{id}/price-imports/batch
openapi: 3.1.0
info:
  title: Watchdog API (preview)
  version: 1.0.0
  description: >-
    Development preview for agreements, price items, document relationships,
    canonical invoices, alerts and alert topics, claims and attached alerts,
    shared entity activity and comments, Document uploads, invoice imports,
    explicit invoice-agreement matching, and workflow runs. This contract is
    under development and is not served by api.watchdog.no. Request bodies are
    limited to 2 MiB (2,097,152 bytes), including all JSON fields and line data,
    except POST /v1/support/contact which permits 32 MiB for base64 attachments.
    File bytes are uploaded directly to storage. The existing public REST
    service retains its separate contract.
servers:
  - url: http://localhost:3500
    description: Local development Worker
security: []
paths:
  /v1/agreements/{id}/price-imports/batch:
    post:
      tags:
        - Agreement price imports
      summary: Import prices from several Documents
      description: >-
        Admits up to 200 distinct linked Documents as items of one agreement
        price-import run. Each file has its own worksheets, instructions and
        default currency; one mode applies across the selection. Files settle
        independently, so a failed file does not undo successful siblings.
        replace_all removes existing prices once, when the first file with valid
        prices commits. An add of identical bytes and settings may reuse an
        active or completed import instead of starting new work. Poll the
        returned run and per-file imports for outcomes.
      operationId: createAgreementPriceImportBatch
      parameters:
        - name: X-Organization-Id
          in: header
          required: false
          schema:
            type: string
          description: >-
            Required for personal API keys. Target one organization you have
            access to. Migrated keys may omit it to use their original
            organization. For Clerk sessions, it must match the active
            organization.
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                files:
                  type: array
                  items:
                    type: object
                    properties:
                      document_id:
                        type: string
                        format: uuid
                        description: A Document linked to this agreement.
                      worksheets:
                        type:
                          - array
                          - 'null'
                        items:
                          type: string
                          minLength: 1
                          maxLength: 31
                        minItems: 1
                        maxItems: 500
                        default: null
                        description: >-
                          Excel worksheets to read, by exact name. Only for XLSX
                          and XLS Documents; null reads every worksheet.
                      instructions:
                        type:
                          - string
                          - 'null'
                        maxLength: 20000
                        default: null
                        description: >-
                          Guidance for reading this document, e.g. which table
                          or price column applies.
                      default_currency:
                        type:
                          - string
                          - 'null'
                        pattern: ^[A-Z]{3}$
                        default: null
                        description: >-
                          ISO 4217 currency for created amount prices whose
                          source states none. Rows keep the source currency.
                    required:
                      - document_id
                    additionalProperties: false
                  minItems: 1
                  maxItems: 200
                mode:
                  type: string
                  enum:
                    - add
                    - replace_document
                    - replace_all
                  default: add
              required:
                - files
              additionalProperties: false
      responses:
        '200':
          description: >-
            Every selected file reused an existing import; no new run was
            created.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                type: object
                properties:
                  workflow_run_id:
                    type:
                      - string
                      - 'null'
                    format: uuid
                  entries:
                    type: array
                    items:
                      type: object
                      properties:
                        document_id:
                          type: string
                          format: uuid
                        admission:
                          type: string
                          enum:
                            - created
                            - reused
                        price_import:
                          $ref: '#/components/schemas/AgreementPriceImport'
                      required:
                        - document_id
                        - admission
                        - price_import
                required:
                  - workflow_run_id
                  - entries
        '202':
          description: At least one file was admitted to a new run.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
            Location:
              schema:
                type: string
              required: false
              description: >-
                Relative URL of the workflow run that admitted the new files.
                Absent when every file reused an existing import.
          content:
            application/json:
              schema:
                type: object
                properties:
                  workflow_run_id:
                    type:
                      - string
                      - 'null'
                    format: uuid
                  entries:
                    type: array
                    items:
                      type: object
                      properties:
                        document_id:
                          type: string
                          format: uuid
                        admission:
                          type: string
                          enum:
                            - created
                            - reused
                        price_import:
                          $ref: '#/components/schemas/AgreementPriceImport'
                      required:
                        - document_id
                        - admission
                        - price_import
                required:
                  - workflow_run_id
                  - entries
        '400':
          description: >-
            Invalid request format, parameters, or body. Details contain up to
            20 actionable field errors; the complete encoded request body must
            be at most 2 MiB (2,097,152 bytes).
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_validation_error'
              example:
                error:
                  code: validation_error
                  message: >-
                    Invalid request format, parameters, or body. Details contain
                    up to 20 actionable field errors; the complete encoded
                    request body must be at most 2 MiB (2,097,152 bytes).
                  request_id: req_example
        '401':
          description: Missing or invalid bearer credential.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
            WWW-Authenticate:
              schema:
                type: string
              required: false
              description: Bearer authentication challenge, when supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_invalid_token'
              example:
                error:
                  code: invalid_token
                  message: Missing or invalid bearer credential.
                  request_id: req_example
        '403':
          description: >-
            Access denied: forbidden, token_disabled, organization_required,
            insufficient_role, or mfa_required. Check the error code and
            effective permissions.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/Error_forbidden_token_disabled_organization_required_insufficient_role_mfa_required
              example:
                error:
                  code: forbidden
                  message: >-
                    Access denied: forbidden, token_disabled,
                    organization_required, insufficient_role, or mfa_required.
                    Check the error code and effective permissions.
                  request_id: req_example
        '404':
          description: The resource does not exist in the current organization.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_not_found'
              example:
                error:
                  code: not_found
                  message: The resource does not exist in the current organization.
                  request_id: req_example
        '409':
          description: A Document source is missing or changed during admission.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_conflict_source_unavailable'
              example:
                error:
                  code: conflict
                  message: A Document source is missing or changed during admission.
                  request_id: req_example
        '429':
          description: The IP or authenticated credential exceeded its request limit.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
            Retry-After:
              schema:
                type: string
                example: '60'
              required: true
              description: Seconds to wait before retrying the request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_rate_limit_exceeded'
              example:
                error:
                  code: rate_limit_exceeded
                  message: >-
                    The IP or authenticated credential exceeded its request
                    limit.
                  request_id: req_example
        '500':
          description: >-
            Unexpected server failure. Include the request ID when contacting
            support.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_internal_error'
              example:
                error:
                  code: internal_error
                  message: >-
                    Unexpected server failure. Include the request ID when
                    contacting support.
                  request_id: req_example
        '503':
          description: >-
            No new file was confirmed as started. Location identifies the
            admitted run for checking before retrying.
          headers:
            X-Request-Id:
              schema:
                type: string
              required: true
              description: >-
                Request identifier for support and diagnostics; also included in
                error bodies.
            Cache-Control:
              schema:
                type: string
                enum:
                  - private, no-store
                  - private, no-store, no-transform
              required: false
              description: >-
                Organization-scoped API responses must not be cached. Responses
                with an ETag also prohibit transformations to preserve its
                strong validator. May be absent for requests rejected before
                routing.
            X-RateLimit-Limit:
              schema:
                type: string
                example: '120'
              required: false
              description: >-
                Requests per minute for the applicable limiter, when evaluated.
                Authenticated requests use the credential limit; an IP rejection
                uses the IP limit.
            Location:
              schema:
                type: string
              required: false
              description: >-
                Relative URL of the workflow run that admitted the new files.
                Absent when every file reused an existing import.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error_service_unavailable'
              example:
                error:
                  code: service_unavailable
                  message: >-
                    No new file was confirmed as started. Location identifies
                    the admitted run for checking before retrying.
                  request_id: req_example
      security:
        - ApiKeyBearer: []
        - ClerkSessionBearer: []
components:
  schemas:
    AgreementPriceImport:
      type: object
      properties:
        id:
          type: string
          format: uuid
        agreement_id:
          type: string
          format: uuid
        document_id:
          type: string
          format: uuid
          description: The Document the prices were extracted from.
        origin:
          type: string
          enum:
            - workflow
            - legacy
          description: >-
            Historical legacy imports have no workflow run or downloadable price
            table.
        worksheets:
          type:
            - array
            - 'null'
          items:
            type: string
        instructions:
          type:
            - string
            - 'null'
        default_currency:
          type:
            - string
            - 'null'
        mode:
          type: string
          enum:
            - add
            - replace_document
            - replace_all
          description: >-
            Which prices the import deletes before adding: none (add), those
            earlier imports of this Document created (replace_document), or
            every price on the agreement (replace_all). Historical imports are
            add.
        status:
          type: string
          enum:
            - queued
            - running
            - completed
            - failed
            - cancelled
          description: >-
            For workflow imports, completed means prices were appended and the
            price table was written in one transaction. Historical imports are
            completed without a stored price table. Failed and cancelled imports
            append nothing.
        counts:
          type:
            - object
            - 'null'
          properties:
            created:
              type: integer
              minimum: 0
              description: Rows appended as new prices.
            duplicate:
              type: integer
              minimum: 0
              description: >-
                Rows with the same product and price as an existing price or an
                earlier row, and not appended.
            invalid:
              type: integer
              minimum: 0
              description: >-
                Rows that fail the price rules, recorded with their errors and
                not appended.
            replaced:
              type: integer
              minimum: 0
              description: >-
                Existing prices the import deleted before appending, as its mode
                selected.
          required:
            - created
            - duplicate
            - invalid
            - replaced
          description: >-
            Row outcomes; null before completion, on failure, and for historical
            imports.
        failure:
          type:
            - object
            - 'null'
          properties:
            code:
              type: string
              minLength: 1
              maxLength: 100
            message:
              type: string
              minLength: 1
              maxLength: 2000
          required:
            - code
            - message
          description: >-
            extraction_incomplete, extraction_failed, agreement_busy,
            agreement_deleted or document_unlinked (the file was removed from
            the agreement). dispatch_failed or admission_expired: processing
            never started. execution_incomplete: processing ended without a
            result. Import again in every case.
        workflow_run_id:
          type:
            - string
            - 'null'
          format: uuid
        workflow_run_item_id:
          type:
            - string
            - 'null'
          format: uuid
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - agreement_id
        - document_id
        - origin
        - worksheets
        - instructions
        - default_currency
        - mode
        - status
        - counts
        - failure
        - workflow_run_id
        - workflow_run_item_id
        - created_at
        - updated_at
    Error_validation_error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - validation_error
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_invalid_token:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - invalid_token
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_forbidden_token_disabled_organization_required_insufficient_role_mfa_required:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - forbidden
                - token_disabled
                - organization_required
                - insufficient_role
                - mfa_required
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_not_found:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - not_found
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_conflict_source_unavailable:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - conflict
                - source_unavailable
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_rate_limit_exceeded:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - rate_limit_exceeded
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_internal_error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - internal_error
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
    Error_service_unavailable:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - service_unavailable
            message:
              type: string
            request_id:
              type: string
            description:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                required:
                  - code
                  - field
                  - message
              maxItems: 20
            workflow_run_id:
              type: string
              format: uuid
            import_id:
              type: string
              format: uuid
            existing_party:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - supplier
                    - recipient
                id:
                  type: string
                  format: uuid
              required:
                - type
                - id
          required:
            - code
            - message
            - request_id
      required:
        - error
  securitySchemes:
    ApiKeyBearer:
      type: http
      scheme: bearer
      description: >-
        Personal API key. Send X-Organization-Id. The required cumulative level
        is listed in x-watchdog-permission.
    ClerkSessionBearer:
      type: http
      scheme: bearer
      description: Clerk session with an active organization.

````