Germany: request and response examples

Send a German B2B invoice, a public-sector (B2G) invoice with a Leitweg-ID and a credit note in GETS, and read each response. Start with a sandbox API key and a German company's onboarded source.

Save the request

Save this body as germany-invoice.json. It is a German B2B, standard-rate invoice. 9930 is the Peppol electronic address scheme for a German VAT identifier; use the scheme and participant IDs actually assigned to both parties. extensions.peppol_buyerAccountingReference becomes the invoice’s buyer reference (BT-10 Buyer reference), a value the buyer gives you, such as its order or cost-centre reference. Do not add a Leitweg-ID to an ordinary B2B invoice.

germany-invoice.jsonjson
{
  "country": "DE",
  "environment": "sandbox",
  "purpose": "invoicing",
  "source": "acme-erp:1.0.0",
  "documentType": { "base": "tax_invoice", "modifiers": [] },
  "payload": {
    "header": {
      "documentType": { "base": "tax_invoice" },
      "documentNumber": "DE-2026-00184",
      "issueDate": "2026-09-18",
      "currency": "EUR",
      "dueDate": "2026-10-18"
    },
    "parties": {
      "seller": {
        "name": "Nordlicht Systeme GmbH",
        "address": {
          "addressLine1": "12 Beispielstraße",
          "city": "Berlin",
          "postalCode": "10115",
          "country": "DE"
        },
        "contact": {
          "name": "Accounts Receivable",
          "email": "billing@example.com",
          "phone": "+49 30 1234567"
        },
        "taxIds": [{ "type": "VAT", "value": "DE123456789" }],
        "registrationNumbers": [{ "type": "CRN", "value": "HRB 123456" }],
        "peppolId": "DE123456789"
      },
      "buyer": {
        "name": "Hansa Handel AG",
        "address": {
          "addressLine1": "8 Musterweg",
          "city": "Hamburg",
          "postalCode": "20095",
          "country": "DE"
        },
        "registrationNumbers": [{ "type": "CRN", "value": "HRB 654321" }],
        "peppolId": "DE987654321"
      },
      "delivery": { "deliveries": [{ "actualDeliveryDate": "2026-09-18" }] }
    },
    "lineItems": [
      {
        "id": "1",
        "name": "Consulting services",
        "quantity": 10,
        "unitCode": "HUR",
        "price": { "amount": 100 },
        "lineTaxableValue": 1000,
        "taxCategory": "S",
        "taxRate": 19,
        "taxAmount": 190,
        "lineTotal": 1000
      }
    ],
    "payment": {
      "paymentMeans": [
        {
          "paymentMeansCode": "58",
          "creditTransferInfo": {
            "payeeFinancialAccountId": "DE89370400440532013000"
          }
        }
      ]
    },
    "taxTotals": [
      {
        "taxAmount": 190,
        "taxSubtotals": [
          {
            "taxableAmount": 1000,
            "taxAmount": 190,
            "taxCategory": "S",
            "percent": 19
          }
        ]
      }
    ],
    "totals": {
      "totalLineTaxableAmount": 1000,
      "totalAmountExcludingTax": 1000,
      "totalTaxAmount": 190,
      "totalAmountIncludingTax": 1190,
      "amountDue": 1190
    },
    "extensions": {
      "peppol_seller_peppolIdScheme": "9930",
      "peppol_buyer_peppolIdScheme": "9930",
      "peppol_buyerAccountingReference": "AP-TEAM"
    }
  }
}

Replace source with the German company’s own name:version, and use an unused documentNumber. Keep environment: "sandbox" with a sandbox key. A few values need care:

  • Document type. The envelope’s documentType decides which rules apply. Complyance copies it into payload.header.documentType, replacing any value there.
  • Line amounts. lineTotal is the line’s net amount, before VAT: quantity times price, plus line charges, minus line allowances. It becomes the invoice line net amount (BT-131) checked by PEPPOL-EN16931-R120.
  • VAT breakdown. taxTotals holds one taxSubtotals line for each VAT category and rate. If you leave it out, Complyance builds it from the lines and totals.
  • Delivery date. parties.delivery.deliveries[].actualDeliveryDate is the date of supply. Without it, or an invoicing period, Unify returns a warning.

Read the German field reference for other document types and conditional fields.

Send the request

Sandbox and production use the same host, https://prod.gets.complyance.io. The "environment": "sandbox" field in the request body is what sends this invoice to sandbox.

Submit a German invoice in sandboxbash
curl --request POST 'https://prod.gets.complyance.io/api/v3/unify' \
  --header "Authorization: Bearer ${COMPLYANCE_API_KEY}" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'new-api: true' \
  --data @germany-invoice.json

Read the response

HTTP 200 means the invoice passed validation and was stored. This illustrative response includes a short Base64-encoded XML fragment to show the shape; the actual Base64XML contains the generated invoice, not this fragment.

Validated invoice — HTTP 200json
{
  "documentId": "01K5EXAMPLE00000000000142",
  "documentNumber": "DE-2026-00184",
  "message": "Your invoice was validated and is ready for submission.",
  "Base64XML": "PEludm9pY2U+PElEPkRFLTIwMjYtMDAxODQ8L0lEPjwvSW52b2ljZT4="
}

If the request returns HTTP 422, inspect every entry in errors. This sample is the response to the same request without totals.amountDue.

Missing amount due — HTTP 422json
{
  "documentId": "01K5EXAMPLE00000000000143",
  "documentNumber": "DE-2026-00184",
  "message": "Your invoice could not be validated. Review the errors and try again.",
  "validationStage": "gets",
  "errors": [
    {
      "code": "IBR-015",
      "getsPath": "totals.amountDue",
      "payloadPath": "totals.amountDue",
      "message": "An Invoice MUST have the Amount due for payment (ibt-115).",
      "severity": "error",
      "ruleSet": "de:tax_invoice"
    }
  ]
}

Correct the field named by getsPath, then send the request again. For 404, confirm your source name and version; for 403, check that the key’s environment matches environment. See Unify errors for other statuses.

Follow delivery

Follow the document by documentId, as described in Submit and retrieve. For Germany, the last step Complyance takes is delivering the invoice to the buyer’s Peppol access point. The Invoice Portal then shows the document as Submitted, with delivery Delivered. The API does not report final_valid for a German invoice: isTerminal stays false once it is delivered. Stop checking when state is delivery_success or delivery_failed. Confirm with the buyer that the invoice arrived.

Invoice to a public authority (B2G)

An invoice to a German public authority carries the authority’s Leitweg-ID, its routing ID, as the buyer reference (BT-10). Ask the authority for its Leitweg-ID and for the format and channel it accepts. Then:

  • Add the b2g modifier to documentType.modifiers.
  • Put the Leitweg-ID in extensions.de_leitwegId, and leave extensions.peppol_buyerAccountingReference out. When both are present, the buyer reference carries peppol_buyerAccountingReference, not the Leitweg-ID.
  • Use the participant ID and scheme the authority gives you. Scheme 0204 is the Peppol scheme for a Leitweg-ID used as the participant ID; see the Peppol code lists.
germany-b2g-invoice.jsonjson
{
  "country": "DE",
  "environment": "sandbox",
  "purpose": "invoicing",
  "source": "acme-erp:1.0.0",
  "documentType": { "base": "tax_invoice", "modifiers": ["b2g"] },
  "payload": {
    "header": {
      "documentType": { "base": "tax_invoice", "modifiers": ["b2g"] },
      "documentNumber": "DE-2026-00191",
      "issueDate": "2026-09-18",
      "currency": "EUR",
      "dueDate": "2026-10-18"
    },
    "parties": {
      "seller": {
        "name": "Nordlicht Systeme GmbH",
        "address": {
          "addressLine1": "12 Beispielstraße",
          "city": "Berlin",
          "postalCode": "10115",
          "country": "DE"
        },
        "contact": {
          "name": "Accounts Receivable",
          "email": "billing@example.com",
          "phone": "+49 30 1234567"
        },
        "taxIds": [{ "type": "VAT", "value": "DE123456789" }],
        "registrationNumbers": [{ "type": "CRN", "value": "HRB 123456" }],
        "peppolId": "DE123456789"
      },
      "buyer": {
        "name": "Bundesamt für Beispielwesen",
        "address": {
          "addressLine1": "1 Amtsplatz",
          "city": "Bonn",
          "postalCode": "53113",
          "country": "DE"
        },
        "peppolId": "991-01234-38"
      },
      "delivery": { "deliveries": [{ "actualDeliveryDate": "2026-09-18" }] }
    },
    "lineItems": [
      {
        "id": "1",
        "name": "Consulting services",
        "quantity": 10,
        "unitCode": "HUR",
        "price": { "amount": 100 },
        "lineTaxableValue": 1000,
        "taxCategory": "S",
        "taxRate": 19,
        "taxAmount": 190,
        "lineTotal": 1000
      }
    ],
    "payment": {
      "paymentMeans": [
        {
          "paymentMeansCode": "58",
          "creditTransferInfo": {
            "payeeFinancialAccountId": "DE89370400440532013000"
          }
        }
      ]
    },
    "taxTotals": [
      {
        "taxAmount": 190,
        "taxSubtotals": [
          {
            "taxableAmount": 1000,
            "taxAmount": 190,
            "taxCategory": "S",
            "percent": 19
          }
        ]
      }
    ],
    "totals": {
      "totalLineTaxableAmount": 1000,
      "totalAmountExcludingTax": 1000,
      "totalTaxAmount": 190,
      "totalAmountIncludingTax": 1190,
      "amountDue": 1190
    },
    "extensions": {
      "peppol_seller_peppolIdScheme": "9930",
      "peppol_buyer_peppolIdScheme": "0204",
      "de_leitwegId": "991-01234-38"
    }
  }
}

Without a buyer reference, Unify returns 422 with BR-DE-15 (“Buyer reference (BT-10) must be provided.”) on extensions.de_leitwegId.

Credit note

A credit note uses documentType.base credit_note and positive amounts for the value credited. It keeps the payment details. This one credits two of the ten consulting hours on the invoice above.

germany-credit-note.jsonjson
{
  "country": "DE",
  "environment": "sandbox",
  "purpose": "invoicing",
  "source": "acme-erp:1.0.0",
  "documentType": { "base": "credit_note", "modifiers": [] },
  "payload": {
    "header": {
      "documentType": { "base": "credit_note" },
      "documentNumber": "DE-CN-2026-00007",
      "issueDate": "2026-09-25",
      "currency": "EUR"
    },
    "parties": {
      "seller": {
        "name": "Nordlicht Systeme GmbH",
        "address": {
          "addressLine1": "12 Beispielstraße",
          "city": "Berlin",
          "postalCode": "10115",
          "country": "DE"
        },
        "contact": {
          "name": "Accounts Receivable",
          "email": "billing@example.com",
          "phone": "+49 30 1234567"
        },
        "taxIds": [{ "type": "VAT", "value": "DE123456789" }],
        "registrationNumbers": [{ "type": "CRN", "value": "HRB 123456" }],
        "peppolId": "DE123456789"
      },
      "buyer": {
        "name": "Hansa Handel AG",
        "address": {
          "addressLine1": "8 Musterweg",
          "city": "Hamburg",
          "postalCode": "20095",
          "country": "DE"
        },
        "registrationNumbers": [{ "type": "CRN", "value": "HRB 654321" }],
        "peppolId": "DE987654321"
      },
      "delivery": { "deliveries": [{ "actualDeliveryDate": "2026-09-18" }] }
    },
    "lineItems": [
      {
        "id": "1",
        "name": "Consulting services",
        "quantity": 2,
        "unitCode": "HUR",
        "price": { "amount": 100 },
        "lineTaxableValue": 200,
        "taxCategory": "S",
        "taxRate": 19,
        "taxAmount": 38,
        "lineTotal": 200
      }
    ],
    "payment": {
      "paymentMeans": [
        {
          "paymentMeansCode": "58",
          "creditTransferInfo": {
            "payeeFinancialAccountId": "DE89370400440532013000"
          }
        }
      ]
    },
    "taxTotals": [
      {
        "taxAmount": 38,
        "taxSubtotals": [
          {
            "taxableAmount": 200,
            "taxAmount": 38,
            "taxCategory": "S",
            "percent": 19
          }
        ]
      }
    ],
    "totals": {
      "totalLineTaxableAmount": 200,
      "totalAmountExcludingTax": 200,
      "totalTaxAmount": 38,
      "totalAmountIncludingTax": 238,
      "amountDue": 238
    },
    "extensions": {
      "peppol_seller_peppolIdScheme": "9930",
      "peppol_buyer_peppolIdScheme": "9930",
      "peppol_buyerAccountingReference": "AP-TEAM"
    }
  }
}

Both requests pass Unify’s validation as written. Send them the same way as the invoice.

Last updated