Invoice API

REST endpoint for creating and issuing invoices from external systems, authenticated with rotatable API tokens.

The invoice API creates and issues invoices through a single REST endpoint. The sender is bound to the token in use and is not passed in the request. Issued invoices receive a sequential, gapless number and a PDF; the operation cannot be undone.

Behavior overview:

  • Every successful request issues the invoice immediately and permanently.
  • Clients are referenced by an existing id, or created when a name is provided. Bookings cannot be referenced through the API; such fields are rejected.
  • Amounts are accepted as strings in German number format ("1.234,50") or as numbers.

Plan-dependent: the invoice API is a separate plan feature. If it is not enabled, the endpoint responds with 403 FEATURE_LOCKED.

Endpoint

POST https://app.kreativmind.at/api/public/invoices
Content-Type: application/json
Authorization: Bearer <token>

Authentication

Requests authenticate with a bearer token in the Authorization header. Tokens are managed under Settings → Billing and are bound to exactly one sender.

  • The token is output in plaintext exactly once, at creation and rotation, and stored server-side only as a SHA-256 hash.
  • Rotation invalidates the previous token immediately; the sender binding is preserved.
  • Revoked tokens are rejected with 403 TOKEN_REVOKED.

Example

curl -X POST https://app.kreativmind.at/api/public/invoices \
  -H "Authorization: Bearer $INVOICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-2026-0042" \
  -d '{
    "client": {
      "name": "Musterfirma GmbH",
      "email": "office@musterfirma.at",
      "addressStreet": "Hauptstraße 1",
      "addressZip": "1010",
      "addressCity": "Wien"
    },
    "serviceDate": "2026-06-30",
    "items": [
      {
        "name": "Photo shoot",
        "unit": "h",
        "unitPrice": "120,00",
        "quantity": "3",
        "taxRate": "20"
      }
    ]
  }'

Request

The request body is JSON. Required: a client reference, a service date and at least one line item. Unset optional fields fall back to the sender's defaults.

Client

Either pass an existing client id, or — without an id — at least client.name. In the latter case the client is created; the generated id is returned in the response and can be reused for subsequent invoices.

FieldTypeDescription
client.idstringId of an existing client. Must belong to the account, otherwise 422.
client.namestringRequired when client.id is absent. Creates a new client.
client.emailstringOptional; only used on creation.
client.addressStreet / addressZip / addressCity / addressCountrystringOptional; only used on creation.

Client creation counts against the plan's client limit (403 LIMIT_REACHED when exceeded).

Service date

At least one of the following fields is required (422 VALIDATION_ERROR otherwise):

FieldTypeDescription
serviceDatedateService date, ISO 8601 (2026-06-30).
serviceFrom / serviceTodateService period. serviceTo is optional.
servicePeriodTextstringFree text, e.g. "June 2026".

Line items (items[])

At least one item is required.

FieldTypeDescription
name *stringItem description.
unitPrice *string | numberNet unit price.
quantity *string | numberQuantity.
unitstringUnit. Default: "Stk".
taxRatestring | numberVAT rate in percent. Defaults to the sender's standard rate.
discountPercentstring | numberLine-item discount in percent.

Additional fields

FieldTypeDescription
title / introText / footerTextstringInvoice title, intro and footer text. Sender defaults apply when unset.
dueDatedateDue date. The sender's payment terms apply when unset.
currencystringISO currency code. Default: EUR.
discountType / discountValueenum / string | numberTotal discount: NONE, PERCENT or AMOUNT with the corresponding value.
skontoPercent / skontoDaysstring | number / numberEarly-payment discount in percent and days.

Response

201 Created with the references of the issued invoice:

{
  "invoiceId": "cmck3…",
  "number": "2026-014",
  "clientId": "cmck1…",
  "clientCreated": true,
  "pdfUrl": "https://app.kreativmind.at/api/public/billing/…/pdf",
  "viewUrl": "https://app.kreativmind.at/inv/…"
}
FieldTypeDescription
invoiceIdstringId of the created invoice.
numberstringAssigned gapless invoice number.
clientIdstringId of the linked client.
clientCreatedbooleantrue if the client was created by this request.
pdfUrlstringPublic PDF download of the invoice.
viewUrlstringPublic invoice view page.

Errors

Error responses are JSON with a machine-readable code. Validation errors additionally carry field codes in the fields object.

StatusCodeMeaning
401NOT_AUTHENTICATEDAuthorization header missing, token unknown or rotated.
403TOKEN_REVOKEDThe token has been revoked.
403SENDER_ARCHIVEDThe bound sender is archived.
403TENANT_LOCKEDThe account is locked.
403FEATURE_LOCKED / LIMIT_REACHED / NO_PACKAGEFeature not in the plan or plan limit reached.
422VALIDATION_ERRORInvalid request. fields names the affected fields, e.g. { "client.name": "REQUIRED" }.
500SERVER_ERRORUnexpected error. Retry the request with the same idempotency key.

If the body contains bookingId or orderId, the request is rejected with 422 and { "bookingId": "NOT_ALLOWED" }.

Idempotency

The optional Idempotency-Key header prevents duplicate invoices on retries (timeouts, automatic retry logic). A repeated request with the same key returns the originally created invoice with 200 instead of assigning another number.

Idempotency-Key: order-2026-0042

Use a stable, business-level key per transaction, such as the calling system's internal order id.