openapi: 3.1.0
info:
  title: Komfortkasse API
  version: 2.0.0
  description: |-
    ![Komfortkasse Logo](https://komfortkasse.eu/images/logo_trans.png)

    The Komfortkasse API allows you to send orders to Komfortkasse and get their status back (for example, whether they have been paid).

    This is Version 2 of the API. Version 1 (deprecated, not available to new customers) can be found at <https://komfortkasse.eu/shopsysteme/item/34-api> (PDF only).

    ## Overview

    ### Process flow

    A normal process flow without any reminders or cancellations:

    1. Your customer places an order in your store using a payment method supported by Komfortkasse (prepayment, invoice, COD)
    2. The order is transmitted to Komfortkasse using `POST /orders` (or `POST /order/{orderNumber}` for a single order)
    3. Optional: Upload an invoice PDF for the order with `POST /order/{orderNumber}/invoice/{invoiceNumber}`
    4. The customer pays the order and Komfortkasse sets `paymentStatus` to `PAID`
    5. You read all orders periodically using e.g. `GET /orders?paymentStatus=PAID` and discover that the order has been paid
    6. Optional manual interventions:
       - `POST /order/{orderNumber}/setpaid` — mark an order as paid manually
       - `POST /order/{orderNumber}/setunpaid` — revert a manual `setpaid`
       - `POST /order/{orderNumber}/cancel` — cancel an order (sets `paymentStatus` to `CANCELLED`)
       - `POST /order/remove/{orderNumber}` — mark an order as removed externally (sets `paymentStatus` to `DISAPPEARED`); use this when the order vanished from your shop (e.g. cancelled by the customer or deleted by an admin) and should no longer be tracked by Komfortkasse; use `cancel` instead to record an explicit cancellation

    ### Callback / Webhook

    You can register a Callback URL in Komfortkasse's API access settings (menu Settings → Shop). If enabled, Komfortkasse will send a callback in the format of [Get Order Details](#operation/getOrder) for every payment status change. Answer with HTTP 200. If the callback is not successful, Komfortkasse will retry roughly every 15 minutes for up to 7 days.

    Komfortkasse will send the **Callback Access Code** available in the Komfortkasse merchant area as HTTP header `X-Komfortkasse-Access-Code`. Verify this header value. For extra security, allow callbacks only from [Komfortkasse's IP addresses](https://komfortkasse.freshdesk.com/support/solutions/articles/14000152603).

    ### Security

    For security purposes, use HTTPS requests only.

    ## Formats

    - **Date:** `dd-MM-yyyy`
    - **Decimal numbers:** `0.00`

    ## Error handling

    Errors are signalled with standard HTTP status codes:

    | Status | Meaning |
    |--------|---------|
    | `200`  | Success |
    | `400`  | Error |
    | `401`  | Authorization problem |
    | `404`  | Not found |
    | `500`  | Internal server error (unexpected; please retry or contact support if it persists) |

    In case of an error, the response body contains an `Error` object as defined in the [Error schema](#components/schemas/Error). Example:

    ```json
    { "error": "API Key missing" }
    ```

    ### Common error messages

    | Status | `error` message | Meaning |
    |--------|-----------------|---------|
    | `401`  | `Authentication header not present` | The `X-Komfortkasse-API-Key` header is missing. |
    | `401`  | `Invalid authentication header` | The API key is unknown or no longer valid. |
    | `401`  | `Replace '[your API key]' with the API key from the merchant area` | The literal placeholder string was sent instead of a real key. |
    | `400`  | `API not active, contact support` | API access is disabled for this shop. |
    | `400`  | `Update not allowed for non-API Shop` | Write operation attempted on a shop that only allows reads via the API. |
    | `400`  | `Shop not active` | The shop is not in an active status (e.g. paused, deleted). |
    | `400`  | `Missing body` | Request body is empty or could not be parsed. |
    | `400`  | `Missing parameter <name>` | A required field on the request body is missing or empty. |
    | `400`  | `Invalid date: <value>, format should be dd-MM-yyyy` | A date query parameter does not match the required format. |
    | `400`  | `Parameter date is not valid` / `Parameter dueDate is not valid` | The order's `date` or `dueDate` could not be parsed. |
    | `400`  | `Parameter date must not be in the future` | `date` is set to a future timestamp on a new order. |
    | `400`  | `Parameter dueDate must not be more than 6 months in the future` | `dueDate` is too far ahead. |
    | `400`  | `Parameter number and number in object do not match` | Path `orderNumber` and body `number` differ. |
    | `400`  | `Parameter initialDunningLevel can only be given when creating a new order` | `initialDunningLevel` was sent on an update. |
    | `400`  | `Could not acquire lock` | The same order is being updated concurrently — retry. |
    | `400`  | `Could not update order (<reason>)` | Update was rejected (e.g. status no longer allows changes). |
    | `400`  | `Refund already exists: <referenceNumber>` | A refund with the same `externalReference` already exists. |
    | `400`  | `Planned date must be in the future` | `plannedDate` on a refund must be in the future. |
    | `400`  | `Invalid JSON, comments not allowed in JSON body` | The body contains HTML comments / non-JSON content. |
    | `400`  | `File missing` / `File size 0` | Invoice upload missing or empty. |
    | `400`  | `Order already in paymentStatus PAID` | `setpaid` called on an already-paid order. |
    | `400`  | `Order must have paymentStatus PAID` / `Order must have manual paymentStatus` | Preconditions for `setunpaid` not met. |
    | `404`  | `Order '<n>' not found` / `Order not found` | Unknown order number for the authenticated shop. |

    > When using a malformed URL, you might not receive an error object but a blank page. When using a completely invalid URL (e.g. without `/api`) you might also be redirected to the Komfortkasse merchant area login page.

    ## Rate limits

    There is no hard rate limit. Please throttle bulk submits and split lists larger than 100 orders into multiple `POST /orders` calls to avoid timeouts.

    ## Timeouts

    Some operations (e.g. `Sync Orders`) may take a long time. Allow a timeout of **at least 10 minutes**.

    ## Example Implementation

    A sample implementation in PHP is available at <https://github.com/ltckomfortkasse/komfortkasse-apiv2-php>.
  contact:
    name: Komfortkasse Support
    url: https://komfortkasse.eu
    email: support@komfortkasse.eu
  license:
    name: Proprietary
    url: https://komfortkasse.eu
servers:
  - url: https://ssl.komfortkasse.eu/api/v2
    description: Production
paths:
  /order/{orderNumber}:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: submitOrder
      tags:
        - Single Order
      summary: Submit Order
      description: |-
        Submit an order to Komfortkasse after the order has been placed in your online shop.

        Only submit orders that are relevant to Komfortkasse, so don't send orders that will be paid by PayPal or creditcard. (You might submit orders with these payment methods as order type `OTHER` if you know what you are doing.)

        Re-submitting an order with the same `orderNumber` updates the existing order — for example, if the customer's email address or the order amount changed in your shop. The `initialDunningLevel` field is honoured **only on the first submission** of an order; on subsequent updates it must be omitted or `0`.
      parameters:
        - $ref: '#/components/parameters/IncludePostings'
        - $ref: '#/components/parameters/IncludeCollectionHistory'
        - $ref: '#/components/parameters/IncludePaymentReminders'
        - $ref: '#/components/parameters/IncludeRefunds'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderWrite'
            example:
              date: 25-04-2018
              customerEmail: max@example.org
              customerNumber: '7890'
              type: INVOICE
              paymentMethod: banktransfer
              paymentMethodDescription: Payment by Invoice
              statusDescription: shipped
              amount: 22.38
              currency: EUR
              exchangeRate: 1.0
              language: de
              items:
                - number: '1826353'
                  name: T-Shirt
                - number: 7633-black
                  name: Jeans black
              invoiceNumbers:
                - '100072533'
              shippingNumbers:
                - '897126743438923093287376'
              billing:
                gender: male
                firstName: Max
                lastName: Mustermann
                street: Bahnhofstr. 14
                postCode: '63073'
                city: Offenbach am Main
                countryCode: DE
                phone: +49 8033 603 9778
              shipping:
                gender: company
                company: Mustermann GmbH
                street: Industriestr. 33
                postCode: '63073'
                city: Offenbach am Main
                countryCode: DE
      responses:
        '200':
          description: Order successfully submitted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: &id001
                date: 25-04-2018
                customerEmail: max@example.org
                customerNumber: '7890'
                type: INVOICE
                paymentMethod: banktransfer
                paymentMethodDescription: Payment by Invoice
                statusDescription: shipped
                amount: 22.38
                currency: EUR
                exchangeRate: 1.0
                language: de
                items:
                  - number: '1826353'
                    name: T-Shirt
                  - number: 7633-black
                    name: Jeans black
                invoiceNumbers:
                  - '100072533'
                shippingNumbers:
                  - '897126743438923093287376'
                billing:
                  gender: male
                  firstName: Max
                  lastName: Mustermann
                  street: Bahnhofstr. 14
                  postCode: '63073'
                  city: Offenbach am Main
                  countryCode: DE
                  phone: +49 8033 603 9778
                shipping:
                  gender: company
                  company: Mustermann GmbH
                  street: Industriestr. 33
                  postCode: '63073'
                  city: Offenbach am Main
                  countryCode: DE
                number: '123456'
                referenceNumber: K1234A
                paymentStatus: UNPAID
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
    get:
      operationId: getOrder
      tags:
        - Single Order
      summary: Get Order Details
      description: |-
        Read details of a single order from Komfortkasse.

        The following fields in the response are read-only (set by Komfortkasse, not by the merchant):
        `paymentStatus`, `referenceNumber`, `bankAccount`, `dunningLevel`, `amountPaid`, `postings`,
        `collectionPartner`, `collectionFile`, `collectionStatus`, `collectionHistory`, `paymentReminders`,
        `refunds`, `hasBankDetailsForRefund`.
      parameters:
        - $ref: '#/components/parameters/IncludePostings'
        - $ref: '#/components/parameters/IncludeCollectionHistory'
        - $ref: '#/components/parameters/IncludePaymentReminders'
        - $ref: '#/components/parameters/IncludeRefunds'
      responses:
        '200':
          description: Order details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/remove/{orderNumber}:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: removeOrder
      tags:
        - Single Order
      summary: Remove Order
      description: |-
        Mark an order as `DISAPPEARED` (removed externally). Use this if the order was cancelled in your shop and should no longer be tracked by Komfortkasse.

        **Difference vs `cancel`:** `remove` means the order has vanished from your shop (sets `paymentStatus` to `DISAPPEARED`), while `cancel` means the order was explicitly cancelled (sets `paymentStatus` to `CANCELLED`). Both stop reminders, but they are distinct payment statuses.
      parameters:
        - $ref: '#/components/parameters/IncludePostings'
        - $ref: '#/components/parameters/IncludeCollectionHistory'
        - $ref: '#/components/parameters/IncludePaymentReminders'
        - $ref: '#/components/parameters/IncludeRefunds'
      responses:
        '200':
          description: Order marked as removed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /image/{orderNumber}:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    get:
      operationId: getImage
      tags:
        - Image
      summary: Get Image
      description: Get a payment-related image (QR code, payment slip) for an order.
      parameters:
        - name: type
          in: query
          schema:
            $ref: '#/components/schemas/ImageType'
          description: Image type to retrieve.
          example: QRCODE
      responses:
        '200':
          description: Image data.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Image'
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/{orderNumber}/setpaid:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: setOrderPaid
      tags:
        - Single Order
      summary: Set Order paid
      description: Manually mark an order as paid.
      responses:
        '200':
          description: Order marked as paid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/{orderNumber}/setunpaid:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: setOrderUnpaid
      tags:
        - Single Order
      summary: Set Order unpaid
      description: Manually mark an order as unpaid (revert a previous setpaid).
      responses:
        '200':
          description: Order marked as unpaid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/{orderNumber}/cancel:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: cancelOrder
      tags:
        - Single Order
      summary: Cancel Order
      description: |-
        Cancel an order (sets `paymentStatus` to `CANCELLED`).

        Use `cancel` to record an explicit cancellation in your shop. To indicate that the order has vanished/been removed externally, use [Remove Order](#operation/removeOrder) instead — that produces `DISAPPEARED`.
      responses:
        '200':
          description: Order cancelled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRead'
              example: *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/{orderNumber}/refund:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
    post:
      operationId: createRefund
      tags:
        - Single Order
      summary: Create a refund for an order
      description: |-
        Create a refund (bank transfer back to the customer) for an existing order.

        - `plannedDate` must be in the future (the date the bank transfer should be initiated).
        - If the customer's bank details are not yet known, the refund starts in status `BANKDETAILS_MISSING` and Komfortkasse asks the customer to provide their IBAN. Once received, it transitions to `NEW` and is executed at `plannedDate`.
        - `externalReference` is your own reference (e.g. RMA number) and must be unique per shop. Re-using a reference of an existing refund returns an error.

        See also [Refunds](https://komfortkasse.freshdesk.com/support/solutions/articles/14000152280).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Refund'
            example:
              externalReference: RMA-2024-001
              amount: 22.38
              currency: EUR
              plannedDate: 01-05-2018
      responses:
        '200':
          description: Refund created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RefundRead'
              example:
                externalReference: RMA-2024-001
                amount: 22.38
                currency: EUR
                plannedDate: 01-05-2018
                id: '12345'
                referenceNumber: KKBT00012345
                status: NEW
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /order/{orderNumber}/invoice/{invoiceNumber}:
    parameters:
      - name: orderNumber
        in: path
        required: true
        schema:
          type: string
        description: Order number (unique per shop).
        example: '123456'
      - name: invoiceNumber
        in: path
        required: true
        schema:
          type: string
        description: Invoice number.
        example: '100072533'
    post:
      operationId: submitInvoice
      tags:
        - Single Order
      summary: Submit an invoice file
      description: |-
        Upload an invoice PDF (or similar) for an order.

        If this is the **first** invoice submitted for the order and the shop is configured to send invoices by letter post, this call may also trigger Komfortkasse to send the invoice to the customer as a physical letter. Do not call this multiple times for the same `invoiceNumber` — repeat uploads of an existing invoice file are silently ignored, but you should still treat the call as non-idempotent for triggering side effects.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: Invoice file (PDF).
              required:
                - file
      responses:
        '200':
          description: Invoice file accepted.
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /orders:
    post:
      operationId: submitOrders
      tags:
        - Bulk Orders
      summary: Submit Orders
      description: "Submit multiple orders to Komfortkasse.\n\nIt is recommended to periodically (e.g. once per day) send all open orders to Komfortkasse in order to update any data that might have been changed (e.g., amount change, change of email address, etc.).\n\nIf you have a large amount of orders to send (more than 100), please split this call into multiple calls to avoid timeout errors."
      parameters:
        - $ref: '#/components/parameters/IncludePostings'
        - $ref: '#/components/parameters/IncludeCollectionHistory'
        - $ref: '#/components/parameters/IncludePaymentReminders'
        - $ref: '#/components/parameters/IncludeRefunds'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/OrderWriteWithNumber'
            example: &id002
              - date: 25-04-2018
                customerEmail: max@example.org
                customerNumber: '7890'
                type: INVOICE
                paymentMethod: banktransfer
                paymentMethodDescription: Payment by Invoice
                statusDescription: shipped
                amount: 22.38
                currency: EUR
                exchangeRate: 1.0
                language: de
                items:
                  - number: '1826353'
                    name: T-Shirt
                  - number: 7633-black
                    name: Jeans black
                invoiceNumbers:
                  - '100072533'
                shippingNumbers:
                  - '897126743438923093287376'
                billing:
                  gender: male
                  firstName: Max
                  lastName: Mustermann
                  street: Bahnhofstr. 14
                  postCode: '63073'
                  city: Offenbach am Main
                  countryCode: DE
                  phone: +49 8033 603 9778
                shipping:
                  gender: company
                  company: Mustermann GmbH
                  street: Industriestr. 33
                  postCode: '63073'
                  city: Offenbach am Main
                  countryCode: DE
                number: '123456'
                referenceNumber: K1234A
                paymentStatus: UNPAID
              - number: '123457'
                date: 26-04-2018
                customerEmail: anna@example.org
                type: PREPAYMENT
                amount: 49.9
                currency: EUR
                items:
                  - number: '9001'
                    name: Hoodie blue
                billing:
                  firstName: Anna
                  lastName: Schmidt
                  street: Hauptstr. 5
                  postCode: '10115'
                  city: Berlin
                  countryCode: DE
      responses:
        '200':
          description: Orders submitted. Returns the list of (re-)read orders.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/OrderRead'
              example:
                - *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
    get:
      operationId: readOrders
      tags:
        - Bulk Orders
      summary: Read Orders
      description: |-
        Read orders from Komfortkasse.
      parameters:
        - name: maxAge
          in: query
          schema:
            type: string
            default: '120'
          description: Maximum order age (in days).
        - name: paymentStatus
          in: query
          schema:
            type: string
          description: 'Comma-separated list of PaymentStatus values for filtering (example: `PAID,PAID_PARTIAL` or `UNPAID`).'
          example: PAID,PAID_PARTIAL
        - name: minPostingDate
          in: query
          schema:
            type: string
          description: Minimum date of last Posting. Note that when using this parameter, only orders will be returned that contain Postings (i.e. orders without Postings that have been set paid manually will not be returned).
        - $ref: '#/components/parameters/IncludePostings'
        - $ref: '#/components/parameters/IncludeCollectionHistory'
        - $ref: '#/components/parameters/IncludePaymentReminders'
        - $ref: '#/components/parameters/IncludeRefunds'
      responses:
        '200':
          description: List of orders.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/OrderRead'
              example:
                - *id001
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /ordersync:
    post:
      operationId: syncOrders
      tags:
        - Bulk Orders
      summary: Sync Orders
      description: |-
        Send the full list of currently-open order numbers from your shop. Komfortkasse marks any of its open orders for this shop that are NOT in the submitted list as `LEGACY` (i.e. no longer tracked) and updates `lastSeen` for the rest. Returns the number of orders that were marked `LEGACY`. Allow a timeout of at least 10 minutes for this operation.

        ⚠️ **Warning:** You must always send the **complete** list of currently-open orders in your shop. Any open order not present in the list will be marked `LEGACY` and stop being tracked by Komfortkasse — including reminder, collection and refund processing. Sending a partial list is destructive.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
              description: Order numbers of currently-open orders in your shop.
            example:
              - '123456'
              - '123457'
      responses:
        '200':
          description: Number of orders that were marked as `LEGACY`.
          content:
            application/json:
              schema:
                type: integer
                description: Number of orders marked as `LEGACY`.
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
  /postings:
    get:
      operationId: readPostings
      tags:
        - Postings
      summary: Read Postings
      description: |-
        Read bank postings (incoming payments) from Komfortkasse.
      parameters:
        - name: createdMin
          in: query
          schema:
            type: string
          description: 'Minimum creation date, inclusive. Format: `dd-MM-yyyy`.'
        - name: createdMax
          in: query
          schema:
            type: string
          description: 'Maximum creation date, exclusive. Format: `dd-MM-yyyy`.'
        - name: includeOrders
          in: query
          schema:
            type: boolean
            default: false
          description: Set to true to include the list of Orders in the response.
        - name: iban
          in: query
          schema:
            type: string
          description: IBAN of bank account. All bank accounts are used if no IBAN is given.
      responses:
        '200':
          description: List of postings.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PostingRead'
              example:
                - id: P-2024-001
                  amount: 22.38
                  currency: EUR
                  postingDate: 26-04-2018
                  valuationDate: 26-04-2018
                  originator: Max Mustermann
                  reference: K1234A
                  text: Order 123456 - K1234A
        '400':
          description: Invalid request — for example missing required fields or wrong format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Invalid request
        '401':
          description: Authentication failed — API key missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: API Key missing
        '404':
          description: Resource not found (e.g. unknown order number).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Order not found
components:
  parameters:
    IncludePostings:
      name: includePostings
      in: query
      schema:
        type: boolean
        default: false
      description: Set to true to include the list of Postings in the response.
    IncludeCollectionHistory:
      name: includeCollectionHistory
      in: query
      schema:
        type: boolean
        default: false
      description: Set to true to include the list of collection events in the response.
    IncludePaymentReminders:
      name: includePaymentReminders
      in: query
      schema:
        type: boolean
        default: false
      description: Set to true to include the list of payment reminders in the response.
    IncludeRefunds:
      name: includeRefunds
      in: query
      schema:
        type: boolean
        default: false
      description: Set to true to include the list of refunds in the response.
  schemas:
    OrderType:
      type: string
      enum:
        - INVOICE
        - PREPAYMENT
        - COD
        - OTHER
      description: "Order payment type:\n- `INVOICE` — invoice (German: Rechnung)\n- `PREPAYMENT` — prepayment (German: Vorkasse)\n- `COD` — cash on delivery (German: Nachnahme)\n- `OTHER` — other payment type (will not be managed by Komfortkasse) — normally not needed"
    OrderWrite:
      type: object
      description: Order data sent by the merchant when creating or updating an order.
      properties:
        date:
          type: string
          description: 'Order date, the date the customer placed the order. Format: `dd-MM-yyyy`.'
        dueDate:
          type: string
          description: 'Date on which the amount is due to pay (e.g., shipping date for INVOICE orders). Format: `dd-MM-yyyy`.'
        customerEmail:
          type: string
          description: Email address of customer. Optional, but obviously needed if you want Komfortkasse to send payment information or reminders.
        customerNumber:
          type: string
          description: Customer number (if the customer has a classic customer number plus a username from a marketplace such as eBay, concat these numbers/usernames with a '/').
        type:
          $ref: '#/components/schemas/OrderType'
        marketplaceNumber:
          type: string
          description: Additional order number from a 3rd party marketplace e.g. ebay.
        paymentMethod:
          type: string
          description: Technical string or id of the payment method in your shop. For information only.
        paymentMethodDescription:
          type: string
          description: Readable description or name of your payment method. For information only.
        statusDescription:
          type: string
          description: String or id representing the order status in your shop. For information only.
        amount:
          type: number
          description: 'Total order amount including all taxes, shipping, etc. This is the amount you expect to be paid. Format: `0.00`.'
        currency:
          type: string
          description: Currency of the order (ISO 4217).
        exchangeRate:
          type: number
          description: Exchange rate, only needed if the order is in a currency where you don't have a Komfortkasse account.
        language:
          type: string
          description: Customer's order language (ISO format). Komfortkasse will send out emails to your customer in this language (if supported).
        itemNumbers:
          type: array
          description: DEPRECATED, use `items`.
          deprecated: true
          items:
            type: string
        items:
          type: array
          description: List of item numbers and names. Item numbers will be used for payment matching.
          items:
            $ref: '#/components/schemas/OrderItem'
        invoiceNumbers:
          type: array
          description: List of invoice numbers. Will be used for payment matching.
          items:
            type: string
        shippingNumbers:
          type: array
          description: List of shipping (tracking) numbers. Will be used for payment matching. Highly recommended if using Komfortkasse for COD.
          items:
            type: string
        proformaNumbers:
          type: array
          description: List of proforma invoice numbers. Will be used for payment matching. Can also be used for other informational numbers like proposal numbers, confirmation numbers, etc.
          items:
            type: string
        billing:
          allOf:
            - $ref: '#/components/schemas/Address'
          description: Billing (invoice) address (primary address).
        shipping:
          allOf:
            - $ref: '#/components/schemas/Address'
          description: Shipping address (secondary address). Optional if same as billing address.
        initialDunningLevel:
          type: integer
          description: Initial dunning level when creating an order (can only be used when creating a new order).
        stopReminder:
          type: boolean
          description: True if no automatic payment reminders should be sent for this order.
      required:
        - date
        - type
        - amount
        - currency
        - billing
    Address:
      type: object
      description: |-
        Postal address used for billing or shipping.

        At least one of `lastName` or `company` must be set.
      properties:
        gender:
          type: string
          enum:
            - male
            - female
            - company
            - unknown
        firstName:
          type: string
          description: First name (given name).
        lastName:
          type: string
          description: Last name (surname). Required if `company` is not set.
        company:
          type: string
          description: Company name. Required if `lastName` is not set.
        street:
          type: string
          description: Street address.
        postCode:
          type: string
          description: Post code (zip code).
        city:
          type: string
          description: City name.
        countryCode:
          type: string
          description: 2-letter ISO country code.
        phone:
          type: string
          description: Optional phone number.
      required:
        - countryCode
      anyOf:
        - required:
            - lastName
        - required:
            - company
    OrderItem:
      type: object
      description: Single item in an order.
      properties:
        number:
          type: string
          description: Item number. Used for payment matching.
        name:
          type: string
          description: Item name.
      required:
        - number
    BankAccount:
      type: object
      description: Bank account details. Read-only.
      properties:
        accountNumber:
          type: string
          description: Account number (use only for non-SEPA payments, e.g. in Switzerland).
        bankCode:
          type: string
          description: Bank code (Bankleitzahl, Bankclearing-Nummer). Use only for non-SEPA payments, e.g. in Switzerland.
        iban:
          type: string
          description: IBAN.
        bic:
          type: string
          description: BIC.
        bankName:
          type: string
          description: Name of the Bank.
        remittee:
          type: string
          description: Remittee/beneficiary name.
    OrderWriteWithNumber:
      allOf:
        - $ref: '#/components/schemas/OrderWrite'
        - type: object
          properties:
            number:
              type: string
              description: Order number, must be unique per shop.
          required:
            - number
    Posting:
      type: object
      description: A bank posting / payment.
      properties:
        id:
          type: string
          description: Unique ID (given by Komfortkasse).
        amount:
          type: number
          description: 'Amount of the posting. Format: `0.00`.'
        currency:
          type: string
          description: Currency of the posting.
        postingDate:
          type: string
          description: Date (booking date) of the posting.
        valuationDate:
          type: string
          description: Valuation date of the posting.
        originator:
          type: string
          description: Originator/counterparty name.
        reference:
          type: string
          description: Reference number.
        text:
          type: string
          description: Text (payment reference).
    PostingRead:
      allOf:
        - $ref: '#/components/schemas/Posting'
        - type: object
          properties:
            orders:
              type: array
              description: List of Orders assigned to this posting (only if parameter `includeOrders` is given).
              items:
                $ref: '#/components/schemas/OrderWriteWithNumber'
    Refund:
      type: object
      description: Refund definition (request payload).
      properties:
        externalReference:
          type: string
          description: Reference given by you.
        amount:
          type: number
          description: 'Refund amount. Format: `0.00`.'
        currency:
          type: string
          description: Refund currency.
        plannedDate:
          type: string
          description: Planned date (date when the bank transfer should be initiated — can be delayed for technical or other reasons, e.g. waiting for bank details).
      required:
        - externalReference
        - plannedDate
        - amount
        - currency
    RefundRead:
      allOf:
        - $ref: '#/components/schemas/Refund'
        - type: object
          properties:
            id:
              type: string
              description: Unique ID (given by Komfortkasse).
            executionDate:
              type: string
              description: Date when bank transfer has been executed (`null` if not yet processed).
            referenceNumber:
              type: string
              description: Reference given by Komfortkasse (typically starts with 'KKBT').
            status:
              $ref: '#/components/schemas/RefundStatus'
              description: Refund status (read only).
    RefundStatus:
      type: string
      enum:
        - NEW
        - BANKDETAILS_MISSING
        - IN_PROCESS
        - PROCESSED
        - RETURNED
        - ERROR
        - CANCELLED
        - LEGACY
      description: "Refund status (read only):\n- `NEW` — will be transferred to bank if plannedDate is reached\n- `BANKDETAILS_MISSING` — waiting for bank details from customer\n- `IN_PROCESS` — being processed\n- `PROCESSED` — processed by bank\n- `RETURNED` — returned to original account\n- `ERROR` — error\n- `CANCELLED` — manually cancelled before executed\n- `LEGACY` — old bank transfer, will not be processed\n\nSee also [Detail view refunds](https://komfortkasse.freshdesk.com/support/solutions/articles/14000152539) for a longer explanation of each status."
    PaymentStatus:
      type: string
      enum:
        - UNPAID
        - PAID
        - PAID_PARTIAL
        - CANCELLED
        - REFUNDED
        - REFUNDED_PARTIAL
        - LEGACY
        - DISAPPEARED
        - COLLECTION
      description: "Payment status of an order:\n- `UNPAID` — not paid\n- `PAID` — fully paid (paid amount might not be equal to amount when using 'allowed deviation' settings)\n- `PAID_PARTIAL` — partially paid\n- `CANCELLED` — cancelled because no payment was made (for paymentType `INVOICE` or `COD`, translated with *overdue*)\n- `REFUNDED` — fully refunded (if refund was made through Komfortkasse)\n- `REFUNDED_PARTIAL` — partly refunded (if refund was made through Komfortkasse)\n- `LEGACY` — order that are older than the date you started using Komfortkasse\n- `DISAPPEARED` — *removed externally* by calling `/order/remove`\n- `COLLECTION` — in collection by debt collection agency"
    OrderCollectionHistory:
      type: object
      description: Single collection event entry.
      properties:
        timestamp:
          type: string
          description: Timestamp of the event.
        description:
          type: string
          description: Description of the event.
    OrderReminder:
      type: object
      description: Single payment reminder entry.
      properties:
        date:
          type: string
          description: Date the reminder was sent.
        dunningLevel:
          type: integer
          description: Dunning level for this payment reminder.
        reminderFee:
          type: number
          description: 'Reminder fee for this payment reminder (not cumulated). Format: `0.00`.'
        email:
          type: boolean
          description: True if reminder was sent by email.
        letter:
          type: boolean
          description: True if reminder was sent by letter.
        emailLink:
          type: string
          description: Link to view the email sent to the customer.
    OrderRead:
      allOf:
        - $ref: '#/components/schemas/OrderWriteWithNumber'
        - type: object
          properties:
            paymentStatus:
              allOf:
                - $ref: '#/components/schemas/PaymentStatus'
              description: Payment status. Read-only.
              readOnly: true
            referenceNumber:
              type: string
              description: Reference number used as payment reference (only available when payment information is sent by Komfortkasse). Read-only.
              readOnly: true
            bankAccount:
              allOf:
                - $ref: '#/components/schemas/BankAccount'
              description: Bank account which should be used for payment. Read-only.
              readOnly: true
            dunningLevel:
              type: integer
              description: Dunning level or number of payment reminders sent (0 when no payment reminder has been sent). Read-only.
              readOnly: true
            amountPaid:
              type: number
              description: 'Amount that has been paid (only set when paymentStatus is not `UNPAID`) — this is the total amount paid, i.e. the sum of all postings minus the sum of all refunds. Read-only. Format: `0.00`.'
              readOnly: true
            postings:
              type: array
              description: List of Postings assigned to this order (only if parameter `includePostings` is given). Read-only.
              items:
                $ref: '#/components/schemas/Posting'
              readOnly: true
            collectionPartner:
              type: string
              description: Name of the collection agency (only if collection is active). Read-only.
              readOnly: true
            collectionFile:
              type: string
              description: File number at the collection agency (only if collection is active). Read-only.
              readOnly: true
            collectionStatus:
              type: string
              description: Status of the collection (only if collection is active). Read-only.
              readOnly: true
            collectionHistory:
              type: array
              description: List of collection events (only if collection is active and parameter `includeCollectionHistory` is given). Read-only.
              items:
                $ref: '#/components/schemas/OrderCollectionHistory'
              readOnly: true
            paymentReminders:
              type: array
              description: List of payment reminders (only if parameter `includePaymentReminders` is given). Read-only.
              items:
                $ref: '#/components/schemas/OrderReminder'
              readOnly: true
            refunds:
              type: array
              description: List of refunds (only if parameter `includeRefunds` is given). Read-only.
              items:
                $ref: '#/components/schemas/RefundRead'
              readOnly: true
            hasBankDetailsForRefund:
              type: boolean
              description: True if bank details for a refund are available (only set when parameter `includePostings` is given). Read-only.
              readOnly: true
    ImageType:
      type: string
      enum:
        - QRCODE
        - PAYMENTSLIP
        - PAYMENTSLIPPRINT
      description: "Image type:\n- `QRCODE` — EPC QR Code (GiroCode)\n- `PAYMENTSLIP` — payment slip (Germany: \"Überweisungsträger\", Austria: \"Zahlschein\", Switzerland: \"Einzahlungsschein\")\n- `PAYMENTSLIPPRINT` — a payment slip that you can print yourself (currently only available for QR Invoice in Switzerland)"
    ImageFormat:
      type: string
      enum:
        - png
      description: Image format. Always `png`.
    Image:
      type: object
      description: Image (e.g. QR code or payment slip) for an order.
      properties:
        type:
          $ref: '#/components/schemas/ImageType'
        format:
          $ref: '#/components/schemas/ImageFormat'
        data:
          type: string
          description: Base64 encoded image data.
    Error:
      type: object
      description: Error response.
      properties:
        error:
          type: string
          description: Error message.
      required:
        - error
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-Komfortkasse-API-Key
      description: All requests must include the `X-Komfortkasse-API-Key` header. You can find your API Key in the Komfortkasse merchant area. For security purposes, use HTTPS only.
tags:
  - name: Single Order
    description: Operations on individual orders.
  - name: Bulk Orders
    description: Operations on multiple orders at once.
  - name: Postings
    description: Bank postings / incoming payments.
  - name: Image
    description: Payment-related images (QR codes, payment slips).
security:
  - apiKey: []
