{
  "openapi": "3.1.0",
  "info": {
    "title": "Tallyworks XRechnung API",
    "version": "1.0.0",
    "summary": "JSON in, valid German e-invoice out: XRechnung 3.0 (UBL XML) or ZUGFeRD 2 / Factur-X (PDF/A-3).",
    "description": "Free: 25 invoices per month per IP address, no key. Only successful conversions count. Paid plans with API keys are coming soon. Invoice data is not stored. Docs: https://xrechnung.tallyworks.dev/docs",
    "contact": {
      "name": "Tallyworks",
      "email": "tallyworks.ops@gmail.com",
      "url": "https://xrechnung.tallyworks.dev"
    }
  },
  "externalDocs": {
    "description": "Developer docs with examples",
    "url": "https://xrechnung.tallyworks.dev/docs"
  },
  "servers": [
    {
      "url": "https://xrechnung.tallyworks.dev"
    }
  ],
  "paths": {
    "/v1/xrechnung": {
      "post": {
        "summary": "Create an XRechnung (UBL XML)",
        "description": "Returns an XRechnung 3.0 invoice in UBL 2.1 syntax, the format German public-sector portals expect. buyerReference is required (Leitweg-ID for public buyers).",
        "operationId": "createXRechnung",
        "security": [
          {},
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invoice"
              },
              "example": {
                "number": "RE-2026-0042",
                "issueDate": "2026-10-11",
                "dueDate": "2026-10-25",
                "deliveryDate": "2026-10-09",
                "buyerReference": "PO-2026-118",
                "seller": {
                  "name": "Muster Webdesign GmbH",
                  "electronicAddress": "rechnung@muster.example",
                  "address": {
                    "street": "Hauptstraße 1",
                    "city": "Berlin",
                    "postalCode": "10115",
                    "country": "DE"
                  },
                  "vatId": "DE123456789",
                  "contact": {
                    "name": "Erika Muster",
                    "phone": "+49 30 1234567",
                    "email": "erika@muster.example"
                  }
                },
                "buyer": {
                  "name": "Beispiel AG",
                  "electronicAddress": "invoices@beispiel-ag.example",
                  "address": {
                    "street": "Industrieweg 7",
                    "city": "Köln",
                    "postalCode": "50667",
                    "country": "DE"
                  }
                },
                "payment": {
                  "iban": "DE02120300000000202051"
                },
                "lines": [
                  {
                    "name": "Webdesign",
                    "quantity": "12.5",
                    "unit": "HUR",
                    "unitPrice": "95.00",
                    "vatRate": 19
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The invoice file. Sent as an attachment named after the invoice number.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              },
              "content-disposition": {
                "schema": {
                  "type": "string"
                },
                "example": "attachment; filename=\"RE-2026-0042.xml\""
              }
            },
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "request body must be valid JSON"
                }
              }
            }
          },
          "401": {
            "description": "The API key is unknown, expired or disabled (paid plans).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API key is invalid, expired or disabled"
                }
              }
            }
          },
          "403": {
            "description": "The API key belongs to another product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API key is not for a Tallyworks API plan"
                }
              }
            }
          },
          "405": {
            "description": "Anything other than POST on a /v1 endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "use POST"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than 256 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "request body too large"
                }
              }
            }
          },
          "422": {
            "description": "The invoice data is incomplete or inconsistent. Lists every problem at once.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "invalid invoice",
                  "details": [
                    {
                      "path": "deliveryDate",
                      "message": "is required unless period is given (date of supply, § 14 UStG)"
                    },
                    {
                      "path": "payment.iban",
                      "message": "is not a valid IBAN"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "The monthly quota is used up. Resets on the 1st of the month (UTC).",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "free limit of 25 invoices per month reached; paid plans are coming soon at https://xrechnung.tallyworks.dev"
                }
              }
            }
          },
          "503": {
            "description": "An API key was sent but paid plans are not open yet, or the key could not be checked. Retry later or leave the key out.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "paid plans are not available yet"
                }
              }
            }
          }
        }
      }
    },
    "/v1/zugferd": {
      "post": {
        "summary": "Create a ZUGFeRD / Factur-X PDF",
        "description": "Returns a PDF/A-3 invoice (German layout) with the CII XML embedded, profile EN 16931. Readable by people, machine-readable by accounting software.",
        "operationId": "createZUGFeRD",
        "security": [
          {},
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invoice"
              },
              "example": {
                "number": "RE-2026-0042",
                "issueDate": "2026-10-11",
                "dueDate": "2026-10-25",
                "deliveryDate": "2026-10-09",
                "buyerReference": "PO-2026-118",
                "seller": {
                  "name": "Muster Webdesign GmbH",
                  "electronicAddress": "rechnung@muster.example",
                  "address": {
                    "street": "Hauptstraße 1",
                    "city": "Berlin",
                    "postalCode": "10115",
                    "country": "DE"
                  },
                  "vatId": "DE123456789",
                  "contact": {
                    "name": "Erika Muster",
                    "phone": "+49 30 1234567",
                    "email": "erika@muster.example"
                  }
                },
                "buyer": {
                  "name": "Beispiel AG",
                  "electronicAddress": "invoices@beispiel-ag.example",
                  "address": {
                    "street": "Industrieweg 7",
                    "city": "Köln",
                    "postalCode": "50667",
                    "country": "DE"
                  }
                },
                "payment": {
                  "iban": "DE02120300000000202051"
                },
                "lines": [
                  {
                    "name": "Webdesign",
                    "quantity": "12.5",
                    "unit": "HUR",
                    "unitPrice": "95.00",
                    "vatRate": 19
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The invoice file. Sent as an attachment named after the invoice number.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              },
              "content-disposition": {
                "schema": {
                  "type": "string"
                },
                "example": "attachment; filename=\"RE-2026-0042.pdf\""
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "request body must be valid JSON"
                }
              }
            }
          },
          "401": {
            "description": "The API key is unknown, expired or disabled (paid plans).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API key is invalid, expired or disabled"
                }
              }
            }
          },
          "403": {
            "description": "The API key belongs to another product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API key is not for a Tallyworks API plan"
                }
              }
            }
          },
          "405": {
            "description": "Anything other than POST on a /v1 endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "use POST"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than 256 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "request body too large"
                }
              }
            }
          },
          "422": {
            "description": "The invoice data is incomplete or inconsistent. Lists every problem at once.",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "invalid invoice",
                  "details": [
                    {
                      "path": "deliveryDate",
                      "message": "is required unless period is given (date of supply, § 14 UStG)"
                    },
                    {
                      "path": "payment.iban",
                      "message": "is not a valid IBAN"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "The monthly quota is used up. Resets on the 1st of the month (UTC).",
            "headers": {
              "x-plan": {
                "description": "Plan used for this request: free, starter or pro.",
                "schema": {
                  "type": "string"
                }
              },
              "x-usage-limit": {
                "description": "Invoices included per month.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-usage-remaining": {
                "description": "Invoices left this month, after this request.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "free limit of 25 invoices per month reached; paid plans are coming soon at https://xrechnung.tallyworks.dev"
                }
              }
            }
          },
          "503": {
            "description": "An API key was sent but paid plans are not open yet, or the key could not be checked. Retry later or leave the key out.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "paid plans are not available yet"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Health check",
        "operationId": "health",
        "security": [],
        "responses": {
          "200": {
            "description": "The service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from a paid plan (coming soon). Leave out for the free tier."
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Alternative to the Authorization header."
      }
    },
    "schemas": {
      "Invoice": {
        "type": "object",
        "description": "One invoice. Also required: deliveryDate or period (§ 14 UStG). The seller needs vatId or taxNumber, and vatId, identifier or registrationNumber (EN 16931 BR-CO-26).",
        "required": [
          "number",
          "issueDate",
          "seller",
          "buyer",
          "payment",
          "lines"
        ],
        "properties": {
          "number": {
            "type": "string",
            "description": "Invoice number. Also used as the file name of the result."
          },
          "issueDate": {
            "type": "string",
            "description": "Invoice date, YYYY-MM-DD.",
            "format": "date",
            "examples": [
              "2026-10-11"
            ]
          },
          "dueDate": {
            "type": "string",
            "description": "Payment due date, YYYY-MM-DD.",
            "format": "date",
            "examples": [
              "2026-10-11"
            ]
          },
          "deliveryDate": {
            "type": "string",
            "description": "Date of supply or service. Required unless period is given.",
            "format": "date",
            "examples": [
              "2026-10-11"
            ]
          },
          "period": {
            "type": "object",
            "description": "Service period, instead of deliveryDate.",
            "required": [
              "start",
              "end"
            ],
            "properties": {
              "start": {
                "type": "string",
                "description": "First day.",
                "format": "date",
                "examples": [
                  "2026-10-11"
                ]
              },
              "end": {
                "type": "string",
                "description": "Last day; not before start.",
                "format": "date",
                "examples": [
                  "2026-10-11"
                ]
              }
            }
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code.",
            "pattern": "^[A-Z]{3}$",
            "default": "EUR"
          },
          "buyerReference": {
            "type": "string",
            "description": "Leitweg-ID for public-sector buyers, otherwise any reference the buyer gave you, such as a purchase order number. Required for /v1/xrechnung, optional for /v1/zugferd."
          },
          "note": {
            "type": "string",
            "description": "Free text printed on the invoice."
          },
          "vatExemptionReason": {
            "type": "string",
            "description": "Required when any line has category E, e.g. \"Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.\" For category AE it defaults to \"Steuerschuldnerschaft des Leistungsempfängers\"."
          },
          "seller": {
            "$ref": "#/components/schemas/Seller"
          },
          "buyer": {
            "$ref": "#/components/schemas/Party"
          },
          "payment": {
            "type": "object",
            "description": "SEPA credit transfer details.",
            "required": [
              "iban"
            ],
            "properties": {
              "iban": {
                "type": "string",
                "description": "IBAN; spaces allowed, the checksum is verified.",
                "examples": [
                  "DE02120300000000202051"
                ]
              },
              "bic": {
                "type": "string",
                "description": "BIC."
              },
              "accountName": {
                "type": "string",
                "description": "Account holder, if different from the seller name."
              },
              "terms": {
                "type": "string",
                "description": "Payment terms in words, e.g. \"Zahlbar innerhalb von 14 Tagen ohne Abzug.\""
              },
              "reference": {
                "type": "string",
                "description": "Remittance information the buyer should use."
              }
            }
          },
          "lines": {
            "type": "array",
            "minItems": 1,
            "maxItems": 250,
            "items": {
              "$ref": "#/components/schemas/Line"
            }
          }
        }
      },
      "Seller": {
        "type": "object",
        "required": [
          "name",
          "electronicAddress",
          "address",
          "contact"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Legal or trading name."
          },
          "electronicAddress": {
            "type": "string",
            "description": "Email address where this party receives e-invoices (BT-34 / BT-49). Only email addresses are supported, no Peppol IDs yet.",
            "format": "email"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "vatId": {
            "type": "string",
            "description": "VAT ID (USt-IdNr.), e.g. DE123456789. Required on both sides for reverse charge (category AE)."
          },
          "taxNumber": {
            "type": "string",
            "description": "Steuernummer; needed when there is no vatId."
          },
          "identifier": {
            "type": "string",
            "description": "Any identifier the buyer knows you by (BT-29), e.g. a customer or supplier number."
          },
          "registrationNumber": {
            "type": "string",
            "description": "Commercial register number (BT-30), e.g. HRB 12345."
          },
          "contact": {
            "type": "object",
            "description": "Contact person for questions about the invoice (required by XRechnung).",
            "required": [
              "name",
              "phone",
              "email"
            ],
            "properties": {
              "name": {
                "type": "string",
                "description": "Name."
              },
              "phone": {
                "type": "string",
                "description": "Phone number."
              },
              "email": {
                "type": "string",
                "description": "Email address.",
                "format": "email"
              }
            }
          }
        }
      },
      "Party": {
        "type": "object",
        "required": [
          "name",
          "electronicAddress",
          "address"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Legal or trading name."
          },
          "electronicAddress": {
            "type": "string",
            "description": "Email address where this party receives e-invoices (BT-34 / BT-49). Only email addresses are supported, no Peppol IDs yet.",
            "format": "email"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "vatId": {
            "type": "string",
            "description": "VAT ID (USt-IdNr.), e.g. DE123456789. Required on both sides for reverse charge (category AE)."
          }
        }
      },
      "Address": {
        "type": "object",
        "required": [
          "city",
          "postalCode",
          "country"
        ],
        "properties": {
          "street": {
            "type": "string",
            "description": "Street and house number."
          },
          "city": {
            "type": "string",
            "description": "City."
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code."
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code.",
            "pattern": "^[A-Z]{2}$",
            "examples": [
              "DE"
            ]
          }
        }
      },
      "Line": {
        "type": "object",
        "required": [
          "name",
          "quantity",
          "unitPrice",
          "vatRate"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Item name."
          },
          "description": {
            "type": "string",
            "description": "Longer description."
          },
          "quantity": {
            "description": "Quantity, up to 4 decimal places. Negative for returns or corrections.",
            "oneOf": [
              {
                "type": "number"
              },
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d{1,4})?$"
              }
            ],
            "examples": [
              "12.5"
            ]
          },
          "unit": {
            "type": "string",
            "description": "UN/ECE Recommendation 20 unit code: C62 piece, HUR hour, DAY day, MON month, KGM kilogram.",
            "pattern": "^[A-Z0-9]{2,3}$",
            "default": "C62"
          },
          "unitPrice": {
            "description": "Net price per unit, up to 6 decimal places, not negative.",
            "oneOf": [
              {
                "type": "number",
                "minimum": 0
              },
              {
                "type": "string",
                "pattern": "^\\d+(\\.\\d{1,6})?$"
              }
            ],
            "examples": [
              "95.00"
            ]
          },
          "vatRate": {
            "description": "VAT rate in percent, up to 2 decimal places, e.g. 19 or 7. 0 for categories Z, E and AE.",
            "oneOf": [
              {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              {
                "type": "string",
                "pattern": "^\\d+(\\.\\d{1,2})?$"
              }
            ],
            "examples": [
              19
            ]
          },
          "vatCategory": {
            "type": "string",
            "enum": [
              "S",
              "Z",
              "E",
              "AE"
            ],
            "description": "S standard rate (default when vatRate > 0), Z zero-rated, E exempt (e.g. § 19 UStG), AE reverse charge. Required when vatRate is 0."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "details": {
            "type": "array",
            "description": "Present on 422: one entry per problem.",
            "items": {
              "type": "object",
              "required": [
                "path",
                "message"
              ],
              "properties": {
                "path": {
                  "type": "string",
                  "description": "JSON path of the field, e.g. lines[0].vatRate. Empty for the whole body."
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}