Bill your customers from your product
Mirror customers, issue and send invoices, keep in sync, cancel — while AlphaCount books, sends and dunns.
Your product knows who bought what for which period. AlphaCount knows how a correct German invoice looks, books it, sends it, sees the payment arrive and dunns when it does not. This guide connects the two.
1. Mirror the customer
PUT /customers/by-ref/{source}/{external_ref} creates the customer or updates it to what you send — call it whenever
the customer changes in your product, or before every invoice.
What a valid invoice needs: name, e-mail (where the invoice goes), street, zip, city, country. For a business customer
in another EU country, add the vat_id — without it, AlphaCount cannot issue a reverse-charge invoice. For public
sector customers, leitweg_id goes into the XRechnung. contact_name appears as "attn." under the name.
2. Create the invoice
POST /invoices with an Idempotency-Key:
{
"customer": { "source": "myapp", "external_ref": "cust-42" },
"external_ref": "order-1001",
"lines": [
{ "description": "Licence, October 2026", "quantity": 1, "unit": "Monat", "unit_price_net": "1000.00", "vat_rate": 19 },
{ "description": "Textbook", "quantity": "3", "unit_price_net": "19.90", "vat_rate": 7 }
],
"service_period": { "start": "2026-10-01", "end": "2026-10-31" },
"payment_terms_days": 14,
"issue": true,
"send": true
}external_refis your id for the invoice. AlphaCount keeps one invoice per reference; a second request for the same reference with another key is409 invoice_external_ref_existsand names the invoice.service_periodis required: a German invoice states when the service was provided.- A line may name a product you keep in AlphaCount (
product_ref, or itsproduct_number) so that revenue lands on the product's account and revenue shares can depend on it.
What happens:
issue | send | Result |
|---|---|---|
false | — | a draft; a person reviews and issues it in the app |
true | false | issued: number, VAT verdict, booking, PDF — and e-invoice for business customers |
true | true | issued, then mailed from the company's mailbox |
Issuing runs all the checks the app runs. If one fails — the company has no tax number yet, the address is incomplete,
the VAT verdict needs a person — the answer is 422 invoice_not_issuable with the reasons, and nothing was
created: no draft, no number, no used-up idempotency key.
If the invoice was issued but the mail failed, the answer is still 201, with send_error saying why. Send it later
with POST /invoices/{id}/send.
3. Learn what happens next
Subscribe a webhook to the invoice events. Each comes once per invoice:
| Event | When |
|---|---|
invoice.issued | it got its number |
invoice.sent | it was mailed for the first time |
invoice.paid | it is paid in full — a partial payment is no event |
invoice.overdue | it is past due and unpaid |
invoice.dunning_sent | a reminder or dunning notice went out |
invoice.cancelled | it was cancelled |
Match an event to your record by data.external_ref. Events can arrive twice or out of order — use the envelope's
id to process each once.
To keep a copy in sync without webhooks, ask GET /invoices?changed_since=… on a schedule.
4. Cancel
An issued invoice cannot be changed or deleted. POST /invoices/{id}/cancel issues a cancellation invoice — the
negative mirror with its own number and a reference to the original — and books the reversal. To correct an invoice,
cancel it and create a new one with a new external_ref.
An invoice that is paid, even partly, is not cancelled through the API (422 invoice_not_cancellable): the payment
needs a person's decision first.
What the API does not do
- issue a draft — that is done in the app;
- change an issued invoice;
- override a tax warning that a person would confirm in the app;
- record payments or start dunning — AlphaCount does that from the bank statement;
- bill in another currency than EUR, or at another VAT rate than 0, 7 or 19 %.