Receipts
A receipt (Beleg) records money for one or more applications of one family: a payment taken at the counter, a payment made online, an invoice that is still open, or a reversal (Storno) of an earlier receipt.
All receipt endpoints need ROLE_PAYMENTS_ADMIN. Amounts are in cents; the items of a reversal are negative.
An invoice is not a separate resource: it's a receipt that hasn't been paid yet. You create a receipt open and pay it when the money comes in, or create it paid if you take the money at the counter right away.
The receipt model
- Name
uuid- Type
- string
- Description
The receipt's identifier.
- Name
receiptNumber- Type
- string
- Description
The receipt number: the municipality's prefix followed by a running number. Assigned when the receipt is paid, so an open invoice has none yet.
- Name
status- Type
- string
- Description
created(open: an invoice, or an online payment that hasn't gone through yet),paid,failedorabandoned. See the receipt workflow.
- Name
totalAmount- Type
- integer
- Description
The sum of the items, in cents.
- Name
createdAt- Type
- timestamp
- Description
When the receipt was created.
- Name
billingAddress- Type
- string
- Description
The billing address as printed on the receipt, one line per line.
- Name
billingEmail- Type
- string
- Description
The e-mail address the receipt goes to.
- Name
paymentMethod- Type
- string
- Description
The name of the online payment method for online payments (
Online-Zahlungif it isn't known), andBargeldfor every other receipt, including open invoices and reversals.
- Name
debtor- Type
- object
- Description
The family's ledger: its
uuidand currentbalance.
- Name
account- Type
- reference
- Description
The family account.
- Name
recordedBy- Type
- reference
- Description
Who created the receipt: the colleague who recorded it, or for online payments the family's own account. Missing for receipts created by a service account.
- Name
items- Type
- object[]
- Description
The lines of the receipt. Each has a
uuid, atype(attendancefor an application,discountfor credit used), anamount, and theattendanceUUID with itsofferandparticipantas references. Ondiscountlines these three arenull.
- Name
isReversal- Type
- boolean
- Description
Whether the receipt's total is negative, as a reversal's is. A reversal of
0(withholding 100 %) showsfalse; usereversalOfto be sure.
- Name
reversalOf- Type
- reference
- Description
The receipt this one reverses. The reference's
nameis its receipt number.
- Name
reversals- Type
- reference[]
- Description
Receipts that reverse this one, fully or in part.
- Name
canBeAdjusted- Type
- boolean
- Description
Whether this receipt can be adjusted: a paid, unreversed counter receipt.
- Name
onlineTransactionId- Type
- string
- Description
The payment provider's transaction ID, for online payments.
- Name
transitions- Type
- string[]
- Description
The workflow transitions you can apply right now:
payandabandonfor an open receipt, none otherwise.
The receipt workflow
A receipt starts open (created) and ends paid or abandoned. An open receipt is an invoice: the family owes the money, nothing is marked paid yet, and the receipt has no number. Apply a transition with POST /receipts/{uuid}/transition.
| Transition | From | To | What happens |
|---|---|---|---|
pay | created | paid | The money was taken. The receipt gets its number, the applications are marked paid, and the credit it uses is taken from the family's ledger. |
abandon | created | abandoned | The receipt is dropped. The applications stay unpaid. |
To take money at the counter in one step, create the receipt with "paid": true.
A receipt the family was sent a payment link for is open as well, and can be paid at the counter too. Once the family starts paying online, the receipt gets an onlineTransactionId and the payment provider moves it on to paid or failed: it has no transitions for you any more.
A paid receipt doesn't change state again. To give money back, reverse it; to correct it, adjust it.
List all receipts
Returns a page of receipts, newest first.
Optional filters
- Name
q- Type
- string
- Description
Only receipts whose number, billing address or billing e-mail contains this text.
- Name
status- Type
- string
- Description
Only receipts in this state:
created,paid,failedorabandoned.
- Name
account- Type
- string
- Description
Only receipts of this family (UUID or e-mail address).
- Name
debtor- Type
- string
- Description
Only receipts of this debtor (UUID).
- Name
participant- Type
- string
- Description
Only receipts covering an application of this participant (UUID).
- Name
attendance- Type
- string
- Description
Only receipts covering this application (UUID).
- Name
edition- Type
- string
- Description
Only receipts covering applications in this edition (UUID or alias).
- Name
reversals- Type
- boolean
- Description
truefor reversals only,falseto leave them out.
- Name
createdSince- Type
- timestamp
- Description
Only receipts created since this moment.
- Name
page, itemsPerPage- Type
- integer
- Description
See Pagination.
Request
curl -G https://ferienpass-musterstadt.de/api/receipts \
-H "Authorization: Bearer $FEPLI_TOKEN" \
--data-urlencode "account=familie.mueller@example.org"
Response
[
{
"uuid": "0192e1a0-7b8c-7d9e-a0f1-2b3c4d5e6f08",
"receiptNumber": "RE-142",
"status": "paid",
"totalAmount": 1250,
"createdAt": "2026-09-10T10:22:31+02:00",
"billingAddress": "Anna Müller\nLindenallee 12\n12345 Musterstadt",
"billingEmail": "familie.mueller@example.org",
"paymentMethod": "Bargeld",
"debtor": {
"uuid": "0191c7b4-5a6b-7c8d-9e0f-1a2b3c4d5e09",
"balance": 0
},
"account": {
"uuid": "0191c7b2-4d5e-7f60-8a1b-2c3d4e5f6a05",
"name": "Anna Müller"
},
"recordedBy": {
"uuid": "0190a1b2-c3d4-7e5f-8a6b-7c8d9e0f1a22",
"name": "Sabine Krüger"
},
"items": [
{
"uuid": "0192e1a0-8c9d-7e0f-a1b2-c3d4e5f6a724",
"type": "attendance",
"amount": 750,
"attendance": "0192d0e8-3a4b-7c5d-9e6f-7a8b9c0d1e07",
"offer": {
"uuid": "0192a4f1-6e3b-7c85-b1d2-8f4e6a9c3b03",
"name": "Fahrradtour durch den Stadtpark",
"alias": "fahrradtour-durch-den-stadtpark"
},
"participant": {
"uuid": "0191c7b3-1f2a-7c4d-8e5f-6a7b8c9d0e06",
"name": "Lena Müller"
}
},
{
"uuid": "0192e1a0-9dae-7f10-b2c3-d4e5f6a7b825",
"type": "attendance",
"amount": 500,
"attendance": "0192d0f1-4b5c-7d6e-8f7a-9b0c1d2e3f23",
"offer": {
"uuid": "0193c8a2-5d6e-7f70-9a8b-1c2d3e4f5a14",
"name": "Töpfern für Anfänger",
"alias": "toepfern-fuer-anfaenger"
},
"participant": {
"uuid": "0191c7b3-2e3f-7a4b-9c5d-6e7f8a9b0c16",
"name": "Paul Müller"
}
}
],
"isReversal": false,
"reversals": [],
"canBeAdjusted": true,
"transitions": []
}
]
Retrieve a receipt
Returns one receipt.
Request
curl https://ferienpass-musterstadt.de/api/receipts/0192e1a0-7b8c-7d9e-a0f1-2b3c4d5e6f08 \
-H "Authorization: Bearer $FEPLI_TOKEN"
Create a receipt
Creates a receipt for one or more open applications of one family. By default, the receipt is open: an invoice, the Rechnung of the admin. Nothing is marked paid until you apply pay.
With "paid": true, the receipt records money taken at the counter, like Zahlung erfassen in the admin: the applications are marked paid and the receipt gets its number right away.
- All applications must belong to the same family, be unpaid, and be in an edition that collects fees through fepli.
- If the family has credit on their ledger, it is used first (as a
discountitem) unless you send"useBalance": false. - If an item's amount is less than the fee, the rest is booked as a claim on the family's ledger when the receipt is paid (for participants with an account).
Required attributes
- Name
items- Type
- object[]
- Description
The applications on the receipt: objects with
attendance(UUID) and optionallyamountin cents, from0up to the fee. Withoutamount, the full fee is charged.
Optional attributes
- Name
paid- Type
- boolean
- Description
The money was taken at the counter: the receipt is paid right away. Defaults to
false, an open receipt.
- Name
useBalance- Type
- boolean
- Description
Use the family's credit. Defaults to
true.
- Name
billingAddress- Type
- string
- Description
The billing address as printed on the receipt. Defaults to the family account's address, or else the participant's.
- Name
billingEmail- Type
- string
- Description
Where the receipt is sent. Defaults to the family account's e-mail address.
- Name
notify- Type
- boolean
- Description
E-mail the receipt to the family. Defaults to
false. Needspaid.
Request
curl -X POST https://ferienpass-musterstadt.de/api/receipts \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "attendance": "0192d0e8-3a4b-7c5d-9e6f-7a8b9c0d1e07" },
{ "attendance": "0192d0f1-4b5c-7d6e-8f7a-9b0c1d2e3f23" }
]
}'
Response (201 Created, excerpt)
{
"uuid": "0193d2b4-6c7d-7e8f-9a0b-1c2d3e4f5a26",
"receiptNumber": null,
"status": "created",
"totalAmount": 1250,
"…": "…",
"transitions": ["pay", "abandon"]
}
Apply a transition
Moves an open receipt through its workflow: pay when the money has been taken, abandon when the receipt is no longer needed. The receipt's transitions list the ones possible right now. Anything else is a 409 that names the possible transitions, and so is any transition on an online payment.
Before pay, the receipt is checked against what happened since it was created. If one of its applications was paid in the meantime, or the family no longer has the credit the receipt uses, the answer is 409: abandon the receipt and create a new one.
Required attributes
- Name
transition- Type
- string
- Description
payorabandon.
Optional attributes
- Name
notify- Type
- boolean
- Description
For
pay: e-mail the receipt to the family. Defaults tofalse.
Request
curl -X POST https://ferienpass-musterstadt.de/api/receipts/0193d2b4-6c7d-7e8f-9a0b-1c2d3e4f5a26/transition \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"transition": "pay", "notify": true}'
Response (excerpt)
{
"uuid": "0193d2b4-6c7d-7e8f-9a0b-1c2d3e4f5a26",
"receiptNumber": "RE-158",
"status": "paid",
"totalAmount": 1250,
"…": "…",
"canBeAdjusted": true,
"transitions": []
}
Reverse a receipt
Reverses (storniert) a paid receipt, fully or in part, and returns the new reversal receipt. By default, the applications are marked unpaid again and the money is paid out. The reversal receipt is e-mailed to the billing address, as in the admin.
Only paid receipts can be reversed, and a reversal can't be reversed itself (409). An open receipt has nothing to reverse: abandon it instead. Applications that were already reversed and marked unpaid are skipped; if nothing is left to reverse, the answer is 409.
Optional attributes
- Name
items- Type
- string[]
- Description
The item UUIDs to reverse. Leave it out to reverse every application on the receipt.
- Name
partial- Type
- object
- Description
Reverse less than the full amount.
{"type": "percent", "value": 20}withholds 20 % and reverses the other 80 %, for example to keep a cancellation fee.{"type": "amount", "value": 1250}reverses exactly 1250 cents. Leave it out to reverse the full amount.
- Name
payout- Type
- string
- Description
Where the money goes:
payout(handed back, the default) orbalance(credited to the family's ledger for later use).
- Name
unpay- Type
- boolean
- Description
Mark the applications unpaid again. Defaults to
true. Sendfalseif the money was returned for another reason and the applications stay paid.
- Name
withdraw- Type
- boolean
- Description
Also withdraw the applications. Defaults to
false.
Request
curl -X POST https://ferienpass-musterstadt.de/api/receipts/0192e1a0-7b8c-7d9e-a0f1-2b3c4d5e6f08/reverse \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": ["0192e1a0-8c9d-7e0f-a1b2-c3d4e5f6a724"],
"payout": "balance",
"withdraw": true
}'
Response (excerpt)
{
"uuid": "0193d3c5-7d8e-7f90-8a1b-2c3d4e5f6a27",
"receiptNumber": "RE-157",
"status": "paid",
"totalAmount": -750,
"isReversal": true,
"reversalOf": {
"uuid": "0192e1a0-7b8c-7d9e-a0f1-2b3c4d5e6f08",
"name": "RE-142"
},
"items": [
{
"uuid": "0193d3c5-8e9f-7a01-9b2c-3d4e5f6a7b28",
"type": "attendance",
"amount": -750,
"attendance": "0192d0e8-3a4b-7c5d-9e6f-7a8b9c0d1e07",
"…": "…"
}
],
"…": "…"
}
Adjust a receipt
Corrects a counter receipt, for example when the wrong amount was entered. The original receipt is reversed in full and a new one is issued with the items, address and e-mail you send. Returns the new receipt.
Only paid, unreversed counter receipts can be adjusted: check canBeAdjusted. Otherwise the answer is 409.
Required attributes
- Name
items- Type
- object[]
- Description
The items of the new receipt: objects with
attendance(UUID, one of the original receipt's applications) andamountin cents.
Optional attributes
- Name
billingAddress- Type
- string
- Description
The billing address. Defaults to the original receipt's.
- Name
billingEmail- Type
- string
- Description
The e-mail address. Defaults to the original receipt's.
- Name
paid- Type
- boolean
- Description
Mark the new receipt paid. Defaults to
true. Withfalse, the new receipt stays open until youpayit.
- Name
notify- Type
- boolean
- Description
E-mail the new receipt. Defaults to
false. Needspaidand abillingEmailin the request.
Request
curl -X POST https://ferienpass-musterstadt.de/api/receipts/0192e1a0-7b8c-7d9e-a0f1-2b3c4d5e6f08/adjust \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "attendance": "0192d0e8-3a4b-7c5d-9e6f-7a8b9c0d1e07", "amount": 750 },
{ "attendance": "0192d0f1-4b5c-7d6e-8f7a-9b0c1d2e3f23", "amount": 250 }
]
}'