Gift vouchers
Named-recipient vouchers with partial redemption and scheduled delivery.
Gift vouchers are a flavour of the regular voucher with three extras: a named recipient (separate from the buyer), an optional gift message, and the ability to defer delivery to a chosen date and time. Partial redemption is enabled by default — a 100€ card can be drawn down over several visits — which makes them the right primitive for both birthday gifts and corporate "welcome to the team" cards.
Extra fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| recipient_name | string | Required | — | Who the card is for. Printed on the email + the PDF. |
| recipient_email | string | Required | — | Where the card lands. Used as the only delivery channel for now. |
| sender_name | string | — | — | Shown to the recipient as "from …". Defaults to the buyer's full name. |
| gift_message | string (≤2000) | — | — | Personal message embedded in the email and the PDF. Plain text. |
| scheduled_delivery_at | timestamptz | — | — | When set in the future, the delivery email is held until this timestamp. |
| allow_partial_redemption | boolean | — | true | When true, redemptions debit remaining_balance instead of burning the voucher in one go. |
| locale | 'de' | 'en' | — | de | Email and PDF language. |
Delivery
With scheduled_delivery_at unset, createGiftVoucher sends the email synchronously: the host clicks "Erstellen" and the recipient receives the card seconds later. With scheduled_delivery_at set, the row is queued for the /api/cron/gift-delivery worker (every 15 min), which sends the email at or shortly after the chosen minute.
delivered_at column. Instead the worker nulls out scheduled_delivery_at on successful send — that doubles as the "already delivered" flag and keeps the row off the next sweep. If the email send fails, the row stays queued for the next 15-minute window.Partial redemption
Every gift voucher tracks two amounts: original_amount stays put for reporting, and remaining_balance is drawn down by each partial redemption. The trigger gutschein_apply_partial_redemption handles the maths automatically — staff just enter the bill amount, the database debits the right value, and flips status to redeemed when the balance hits zero.
Stripe-paid gift cards
When a gift voucher is sold through the public widget rather than issued by staff, the flow goes through Stripe Checkout. The gutschein_purchases table tracks the payment state (pending → paid → refunded); the actual gutschein row is created with type=gift only afterpayment_intent.succeeded lands on the webhook. Staff don't see the pending purchase rows in the regular voucher list — they appear once paid.
qr_token. Reach out if you have a stock of cards to onboard.