invowerk Validation API

The Validation API from invowerk — 1 operation(s) for validation.

GitHub OpenAPI

Operations 1

POST /v1/validate Check an e-invoice #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/invowerk-dev:invowerk-dev-validation-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

invowerk-dev-validation-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: invowerk Validation API
  description: 'German e-invoices: create ZUGFeRD PDFs and XRechnung, check ZUGFeRD/Factur-X, XRechnung (KoSIT) and Peppol BIS. Free tool, API, MCP.


    Base URL: `https://api.invowerk.dev`.


    ### Authentication

    Send your key in the `X-API-Key` header. Calls without a key run anonymously at

    a lower rate limit per IP address.


    ### Rate limits

    Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and

    `X-RateLimit-Reset` (seconds until the window resets). Over-budget calls return

    `429` with a `Retry-After` header. Check your live budget at `GET /v1/me`.


    ### Pagination

    List endpoints return a keyset envelope: `{"items": [...], "next_cursor": "..."}`.

    Pass `next_cursor` back as the `?cursor=` query param for the next page; it is

    `null` on the last page.


    ### Errors

    Errors are RFC 9457 `problem+json` with a

    stable machine-readable **`code`** (e.g. `rate_limited`, `credits_exhausted`,

    `validation_error`). Branch on `code`. The `title` and `detail` text may change.


    ### Quickstart

    ```sh

    curl -H "X-API-Key: $API_KEY" https://api.invowerk.dev/v1/me

    ```'
  version: '1'
servers:
- url: https://api.invowerk.dev
tags:
- name: Validation
paths:
  /v1/validate:
    post:
      tags:
      - Validation
      summary: Check an e-invoice
      description: 'Check an e-invoice against EN 16931 and the German rules.


        Send an XML invoice (UBL or CII, e.g. XRechnung) or a ZUGFeRD / Factur-X PDF as

        the raw request body or as a multipart file part, at most 20 MB. A PDF may have

        at most 500 pages and 16 attachments. invowerk detects the format from the

        bytes, not from the Content-Type. A larger body gets HTTP 413. Otherwise the

        answer is always HTTP 200, because a failed check is a result, not an error.

        `valid` is the result, `findings` lists each problem, `e_rechnung_de` maps the

        result onto the BMF categories and `evidence` identifies the checked file.

        `hints` are extra observations that never change `valid`. For XRechnung the

        KoSIT validator decides `valid`. If it is unreachable, invowerk''s own check

        with the same rules decides, `verdict_source` is `local` and the

        `X-EInvoice-Degraded` header is set (`official-lane-unavailable`;

        `pdfa-lane-unavailable` when the PDF/A check did not answer; comma-separated).

        `disagreement` is true when both checks ran and differ. For a PDF,

        `pdfa_verdict` is the PDF/A check with veraPDF. `?explain=true` adds the

        explanation for rules that have one, in `lang` (`de` or `en`). An XML file

        with more than 100,000 elements gets HTTP 413. HTTP 429 means every check

        slot is busy (callers without an API key share one), HTTP 504 that the check

        ran longer than 20 s. Costs 1 credit.


        **Credits:** 1 per call.'
      operationId: validate_invoice
      security:
      - APIKeyHeader: []
      parameters:
      - name: explain
        in: query
        required: false
        schema:
          type: boolean
          default: false
          title: Explain
      - name: lang
        in: query
        required: false
        schema:
          type: string
          default: de
          title: Lang
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationResponse'
        '422':
          description: Validation Error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
      requestBody:
        required: true
        description: 'The invoice: XML (UBL or CII, e.g. XRechnung) or a ZUGFeRD / Factur-X PDF, as the raw body or as a multipart file part. At most 20 MB.'
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  contentMediaType: application/octet-stream
                  description: The invoice file (XML or PDF).
              required:
              - file
          application/xml:
            schema:
              type: string
          application/pdf:
            schema:
              type: string
              contentMediaType: application/pdf
      x-connector:
        kind: action
        sample_file: /app-static/demo/beispiel-xrechnung.xml
      x-credits-cost: 1
components:
  schemas:
    Problem:
      description: The RFC 9457 error body. Every error response uses it.
      properties:
        type:
          default: about:blank
          description: Problem type URI (RFC 9457).
          title: Type
          type: string
        title:
          description: Short human-readable summary of the status.
          title: Title
          type: string
        status:
          description: The HTTP status code, repeated in the body.
          title: Status
          type: integer
        detail:
          description: What went wrong with this request.
          title: Detail
          type: string
        instance:
          description: The request path that produced the error.
          title: Instance
          type: string
        code:
          description: Stable machine-readable error code. Branch on this, not on the text.
          title: Code
          type: string
        request_id:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Correlation id for this request; quote it when asking for support.
          title: Request Id
        errors:
          anyOf:
          - items:
              additionalProperties: true
              type: object
            type: array
          - type: 'null'
          default: null
          description: Per-field validation failures. Present on 422 only.
          title: Errors
        upgrade_url:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Where to add credits or move to a larger plan. Present on 402/403/429.
          title: Upgrade Url
      required:
      - title
      - status
      - detail
      - instance
      - code
      title: Problem
      type: object
    ErrorClasses:
      properties:
        format:
          items:
            $ref: '#/components/schemas/Finding'
          type: array
          title: Format
          description: 'Problems with the file or XML structure: unknown format, malformed XML, a forbidden DOCTYPE, XML schema (XSD) errors.'
        business_rules:
          items:
            $ref: '#/components/schemas/Finding'
          type: array
          title: Business Rules
          description: Failed rules of the applied rule set (EN 16931, XRechnung, ZUGFeRD / Factur-X or Peppol BIS).
        carrier:
          items:
            $ref: '#/components/schemas/Finding'
          type: array
          title: Carrier
          description: 'Problems with the PDF of a ZUGFeRD / Factur-X invoice: PDF/A conformance and how the XML is embedded (BR-HYBRID-* rules). Always empty for an XML file.'
        content:
          $ref: '#/components/schemas/ContentClass'
          description: Always the not_machine_checkable reminder. Never contains findings.
      type: object
      required:
      - content
      title: ErrorClasses
      description: 'The findings grouped by where the problem is. ``findings`` has the same

        findings as one list.'
    ContentClass:
      properties:
        status:
          type: string
          title: Status
          description: Always 'not_machine_checkable'.
          default: not_machine_checkable
        note:
          type: string
          title: Note
          description: 'Fixed note: a format check cannot judge whether the content is correct.'
      type: object
      required:
      - note
      title: ContentClass
      description: 'Reminder that the content of an invoice cannot be checked by machine.


        It never contains findings. A clean result means the invoice is well-formed

        and follows the rules. It does not mean that prices, amounts or the

        delivered service are correct.'
    Finding:
      properties:
        rule_id:
          type: string
          title: Rule Id
          description: Code of the rule that failed, e.g. 'BR-DE-21', or 'XSD' for a schema error.
        error_class:
          type: string
          title: Error Class
          description: 'Where the problem is: ''format'' (file or XML structure), ''business_rules'' (a rule of the applied rule set) or ''carrier'' (the PDF around the XML).'
        severity:
          type: string
          title: Severity
          description: '''fatal'' (the invoice fails the check), ''warning'' or ''information''.'
        xpath:
          anyOf:
          - type: string
          - type: 'null'
          title: Xpath
          description: Where the problem is in the XML (an XPath or a schema line), if known.
        message:
          type: string
          title: Message
          description: The message of the failed rule or check.
        explain_url:
          anyOf:
          - type: string
          - type: 'null'
          title: Explain Url
          description: Path of the explanation page /codes/<CODE> (/en/codes/<CODE> in English), if invowerk has one.
        explain:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Explain
          description: Explanation of the rule (meaning, causes, fixes) in the requested language. Set only with ?explain=true and if invowerk has an entry for the code.
        printed_by:
          anyOf:
          - type: string
          - type: 'null'
          title: Printed By
          description: 'Set only on ''no_embedded_xml'': the browser or printer that saved the PDF through a print function, for example ''Firefox'', ''Chrome'' or ''Microsoft Print to PDF''. Printing drops the embedded invoice XML, so the original file may still be an e-invoice.'
      type: object
      required:
      - rule_id
      - error_class
      - severity
      - message
      title: Finding
      description: 'One problem found in the invoice.


        ``error_class`` says where the problem is: in the file or XML structure

        (``format``), in a rule of the applied rule set (``business_rules``) or in

        the PDF around the invoice data (``carrier``). ``explain_url`` links the

        explanation page for the code, in ``lang``. ``explain`` holds the explanation

        itself when you call with ``?explain=true``. ``printed_by`` names the

        browser or printer when a ``no_embedded_xml`` PDF was saved through a print

        function.'
    ERechnungDe:
      properties:
        status:
          type: string
          title: Status
          description: '''e_rechnung'' (no errors), ''e_rechnung_mit_fehlern'' (rule errors), ''keine_e_rechnung'' (not a structured e-invoice) or ''nicht_pruefbar'' (the file could not be checked).'
        reason:
          type: string
          title: Reason
          description: Why this status applies, in German, naming the finding.
        basis:
          anyOf:
          - type: string
          - type: 'null'
          title: Basis
          description: The BMF letter or UStAE passage for the category; null for 'nicht_pruefbar'.
        note:
          type: string
          title: Note
          description: 'Fixed German note, the same on every answer: invowerk checks the technical format, not whether content and amounts are correct or what tax consequences an error has.'
      type: object
      required:
      - status
      - reason
      - note
      title: ERechnungDe
      description: 'The result mapped onto the categories of the BMF letter of 15.10.2025

        (Germany).


        It describes the format check only. It is not a tax assessment (see

        ``note``).'
    ScenarioInfo:
      properties:
        config:
          type: string
          title: Config
          description: '''kosit-xrechnung'' (the KoSIT configuration for XRechnung and EN 16931) or ''zugferd'' (the FeRD rules for ZUGFeRD / Factur-X).'
        name:
          type: string
          title: Name
          description: The scenario name as the configuration states it.
      type: object
      required:
      - config
      - name
      title: ScenarioInfo
      description: 'The rule set that was applied: its configuration and scenario.'
    Evidence:
      properties:
        document_sha256:
          type: string
          title: Document Sha256
          description: Hex SHA-256 of the exact bytes you sent (compare with `sha256sum <file>`).
        document_bytes:
          type: integer
          title: Document Bytes
          description: Size in bytes of what you sent.
        checked_at:
          type: string
          title: Checked At
          description: UTC time of the check, ISO 8601 to the second, e.g. '2026-09-24T10:15:00Z'.
        validator:
          $ref: '#/components/schemas/ValidatorVersions'
          description: The software versions.
      type: object
      required:
      - document_sha256
      - document_bytes
      - checked_at
      - validator
      title: Evidence
      description: 'Which file was checked, when, and with which software. Keep it with a

        saved report: the SHA-256 ties the report to one file.'
    HintInfo:
      properties:
        code:
          type: string
          title: Code
          description: The hint code, e.g. 'IW-IBAN'.
        severity:
          type: string
          title: Severity
          description: '''warning'' or ''information''. A hint is never fatal.'
        message:
          type: string
          title: Message
          description: The observation, in the requested language.
        bt_refs:
          items:
            type: string
          type: array
          title: Bt Refs
          description: The EN 16931 Business Terms the hint is about.
        explain_url:
          anyOf:
          - type: string
          - type: 'null'
          title: Explain Url
          description: Path of the page /codes/<CODE> (/en/… in English) that explains the hint.
      type: object
      required:
      - code
      - severity
      - message
      title: HintInfo
      description: 'One hint: an extra observation by invowerk. Hints never change the result.'
    ValidationResponse:
      properties:
        valid:
          type: boolean
          title: Valid
          description: The overall result. For the XML, the KoSIT validator decides when it answered (verdict_source 'official'); otherwise invowerk's own check decides (no fatal finding). A fatal problem with the PDF of a ZUGFeRD / Factur-X invoice always makes it false.
        verdict_source:
          type: string
          title: Verdict Source
          description: '''official'' when the KoSIT validator decided the XML result, ''local'' when invowerk''s own check did (ZUGFeRD or Peppol rules, or KoSIT did not answer).'
        local_verdict:
          type: string
          title: Local Verdict
          description: 'invowerk''s own result, ''valid'' or ''invalid'': ''invalid'' when any format, business rule or PDF finding is fatal.'
        disagreement:
          type: boolean
          title: Disagreement
          description: True when the KoSIT validator and invowerk's own check reach different results for the XML. The KoSIT result decides; the findings explain the difference.
        lane:
          type: string
          title: Lane
          description: '''official'' when invowerk asked the KoSIT validator (even if it did not answer), else ''local''.'
        official_verdict:
          anyOf:
          - type: string
          - type: 'null'
          title: Official Verdict
          description: 'The KoSIT validator''s result: ''valid'', ''invalid'' or ''unavailable'' (it did not answer). Null when it was not asked, e.g. for ZUGFeRD or Peppol.'
        scenario:
          anyOf:
          - $ref: '#/components/schemas/ScenarioInfo'
          - type: 'null'
          description: The rule set that was applied, or null when no rule set matched.
        pdfa_verdict:
          anyOf:
          - type: string
          - type: 'null'
          title: Pdfa Verdict
          description: 'PDF/A check of a ZUGFeRD / Factur-X PDF with veraPDF: ''valid'', ''invalid'' or ''unavailable''. Null when not checked (always for XML). Null does not mean the PDF is fine.'
        detection:
          additionalProperties: true
          type: object
          title: Detection
          description: 'What invowerk detected from the bytes: kind, syntax, flavor, customization_id, is_hybrid_pdf. For a PDF it describes the embedded XML.'
        errors:
          $ref: '#/components/schemas/ErrorClasses'
          description: The findings grouped by where the problem is.
        findings:
          items:
            $ref: '#/components/schemas/Finding'
          type: array
          title: Findings
          description: All format, business rule and PDF findings as one ordered list.
        rulesets:
          additionalProperties:
            type: string
          type: object
          title: Rulesets
          description: 'The rule set versions used for this check, as {name: version}.'
        evidence:
          $ref: '#/components/schemas/Evidence'
          description: SHA-256 and size of the file, time of the check, software versions.
        e_rechnung_de:
          $ref: '#/components/schemas/ERechnungDe'
          description: The result mapped onto the e-invoice categories of the German BMF. Describes the format only, not a tax assessment.
        hints:
          items:
            $ref: '#/components/schemas/HintInfo'
          type: array
          title: Hints
          description: Extra observations by invowerk (IW-* codes), e.g. a wrong IBAN check digit. They never change valid, verdict_source or e_rechnung_de.
      type: object
      required:
      - valid
      - verdict_source
      - local_verdict
      - disagreement
      - lane
      - detection
      - errors
      - evidence
      - e_rechnung_de
      title: ValidationResponse
      description: 'The result of POST /v1/validate. Always HTTP 200: a failed check is data,

        not an error.'
    ValidatorVersions:
      properties:
        invowerk:
          type: string
          title: Invowerk
          description: The invowerk version, or 'unknown'.
        appkit:
          type: string
          title: Appkit
          description: The version of the platform invowerk runs on, or 'unknown'.
      type: object
      required:
      - invowerk
      - appkit
      title: ValidatorVersions
      description: The software versions that produced the result.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key