Filekin for Business API

Create XRechnung, ZUGFeRD and Factur-X invoices from your own software, and check any e-invoice against the official rules, with plain-language explanations of every error. Every account can use it: the free Developer plan includes 20 invoices and 100 calls a month, no card needed, and the Business + API and API Plus plans include thousands.

Getting started

  1. Fill in your company details: they go on every invoice the API makes.
  2. Create an API key on your account page. It's shown once: keep it secret, like a password.
  3. Send it with every call: Authorization: Bearer fk_…

Create an invoice

POST https://app.filekin.io/api/v1/invoices with a JSON body. Your company, bank and invoice defaults come from your company details; a saved customer number or product code fills in the rest, just like in a spreadsheet.

curl https://app.filekin.io/api/v1/invoices \
  -H "Authorization: Bearer $FILEKIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "RE-2026-0042",
    "issue_date": "2026-11-02",
    "customer": {"name": "Beispiel GmbH", "street": "Marktplatz 3", "postcode": "80331",
                 "city": "München", "country": "DE", "vat_id": "DE987654321"},
    "buyer_reference": "04011000-12345-03",
    "lines": [{"description": "Webdesign", "quantity": 12, "unit": "HUR", "price": 85, "vat_rate": 19}]
  }'

The answer (201) is JSON with the file in base64:

{"number": "RE-2026-0042", "file_name": "Rechnung RE-2026-0042.pdf", "content_type": "application/pdf",
 "file": "JVBERi0xLjcK…", "invoices_left": 1999}

Add ?download=1 to get the file itself instead. Every invoice is checked against the official rules before it's returned.

Fields

FieldWhat it is
numberInvoice number. Leave it out to use your automatic numbering. A number can be used once; send "replace": true to make it again.
issue_date, due_date, delivery_dateDates as YYYY-MM-DD. Issue date defaults to today; the due date to your usual payment terms.
customercode (a saved customer number), or name, street, postcode, city, country (2 letters), vat_id, email.
buyer_referenceLeitweg-ID for German public authorities, or the buyer's reference.
order_reference, notesPurchase order number, and a note printed on the invoice.
linesUp to 200 lines: product_code (a saved product), or description, quantity, unit (HUR, DAY, MON, C62…), price (net), vat_rate, and an optional discount in percent.
discountA discount on the whole invoice: {"percent": 5} or {"amount": 50}, with an optional reason. It's split across the VAT rates as EN 16931 requires.
chargesUp to 5 surcharges, such as shipping: [{"reason": "Versand", "amount": 4.90, "vat_rate": 19}] (net; the rate defaults to the invoice's highest).
skontoEarly-payment discounts, up to two: [{"percent": 2, "days": 10}]. Printed with the date and amount, and coded for German software (#SKONTO#). Send [] for none when your account has a default.
document, prepayments"partial" for a down-payment invoice (type 326), or "final" for a final invoice with the down payments it deducts: [{"number": "AR-1", "date": "2026-09-01", "net": 1000, "vat": 190}].
paid_amount, payment_method, card_digitsWhat's paid already, and how it's paid: transfer (the default, to your IBAN), card, online or cash. A fully paid invoice shows nothing left to pay.
format, language, currencyOptional, to override your defaults: zugferd, xrechnung or simple; de, fr or en; a currency code like EUR.

Validate an e-invoice

POST https://app.filekin.io/api/v1/validate with the file as the body: an XRechnung or UBL XML, or a ZUGFeRD / Factur-X PDF. Add ?lang=de or ?lang=fr for messages in German or French.

curl https://app.filekin.io/api/v1/validate?lang=de \
  -H "Authorization: Bearer $FILEKIN_KEY" \
  --data-binary @rechnung.xml

The answer is a report: the format found, whether it passes, whether it counts as an e-invoice in Germany and France, and every error and warning with where it is, how to fix it, and a link to a full explanation.

{"format": "XRechnung 3.0 (CII)", "valid": false, "germany": "…", "france": "…",
 "errors": [{"rule": "BR-DE-15", "message": "…", "where": "…", "help": "…",
             "explanation_url": "https://filekin.io/de/e-rechnung-fehler/br-de-15"}], "warnings": []}

Python

import base64, os, requests

key = os.environ["FILEKIN_KEY"]
r = requests.post("https://app.filekin.io/api/v1/invoices", timeout=60,
                  headers={"Authorization": f"Bearer {key}"},
                  json={"customer": {"code": "K-1001"}, "lines": [{"product_code": "WEB", "quantity": 3}]})
r.raise_for_status()
invoice = r.json()
open(invoice["file_name"], "wb").write(base64.b64decode(invoice["file"]))

Usage

GET https://app.filekin.io/api/v1/usage returns your plan, this month's use and your allowance.

Limits

Errors

Errors come back as JSON: {"error": "code", "message": "what happened"}.

StatusCodeMeaning
400bad_json, emptyThe request body isn't what the endpoint expects.
401unauthorizedThe API key is missing, wrong or revoked.
403no_planThe account's plan has no API access.
409duplicate, no_companyThe invoice number was used before, or the company details aren't filled in.
413too_many_lines, too_largeOver a size limit.
422invalid, not_an_invoiceThe invoice can't be made as given (the message says why), or the file isn't an e-invoice.
429slow_down, busy, limitToo fast, a call is still running, or the month's allowance is used up.