> ## Documentation Index
> Fetch the complete documentation index at: https://docs-consumer.voucher.allride.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing

> How AllRide bills you per redemption: billing account, SEPA Direct Debit, invoices and Stornorechnungen, ZUGFeRD and XRechnung, usage, payments, dunning, billing webhooks and permissions.

This guide is for Partner Consumers. AllRide bills only consumers; providers are never billed and never see your billing data. Everything here is available in the consumer dashboard under **Billing** and through the `/consumer/v1/billing` endpoints of the [API reference](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-account-get.md).

## How you are billed

* AllRide bills you **in arrears, once a month, per billable redemption**. There is no deposit, no advance payment and no subscription fee.
* A **billable redemption** is a completed redemption of yours, whatever the channel (API, dashboard or Redemption Link). Imported legacy redemptions are not billed.
* The **service month** of a redemption is the calendar month of its `redeemedAt` in **Berlin time (`Europe/Berlin`)**, whatever your partner time zone. Billing months follow Berlin time, so your [analytics](https://docs-consumer.voucher.allride.io/consumer/analytics.md) in another time zone can differ from the invoice at the month edges.
* On the 1st of each month at 06:00 Berlin time AllRide drafts the invoice for the previous month. AllRide reviews every draft before it is issued, so the invoice arrives a little later.
* **Voided redemptions are not billed.** Void before the month is invoiced and the redemption never appears on an invoice. An issued invoice is never changed afterwards, so a void after invoicing does not reduce it; if an invoice is wrong, talk to AllRide (see [Corrections: Stornorechnung](#corrections-stornorechnung)).
* A month with usage always produces an invoice, even if its total is zero (for example when every provider you used is free); such an invoice is immediately `paid`. A month without usage produces no invoice.
* The price per redemption is set by AllRide for you, possibly per provider or voucher set, and you accept it before you can redeem: see [Prices and price acceptance](https://docs-consumer.voucher.allride.io/consumer/prices.md).
* **AllRide decides how you pay**: by SEPA Direct Debit (the default; you set up the mandate yourself, see [SEPA Direct Debit mandate](#sepa-direct-debit-mandate)) or by bank transfer against each invoice. You see the choice as `preferredPaymentMethodType` on your billing account.

```mermaid theme={null}
flowchart LR
  R[Redemptions in month M, Berlin time] --> D[Draft on the 1st of M+1, 06:00]
  D --> A[Review by AllRide]
  A --> F[Invoice issued: number, PDF and XML]
  F --> E[Email to your invoice contacts]
  E --> P[SEPA debit or bank transfer]
```

## Billing account and contacts

Your partner has one **billing account**, created automatically when you become a consumer.

> [!NOTE]
>
> **Coming soon.** Changing the billing account through `PATCH /consumer/v1/billing/account` is not available yet. Until it is, your AllRide account manager updates the account for you; reading the account and managing contacts work today.

* Read it with `GET /consumer/v1/billing/account` ([Get the billing account](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-account-get.md)).
* Change it with `PATCH /consumer/v1/billing/account` ([Update the billing account](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-account-update.md)), a JSON merge patch. You can change `legalName`, `address`, `vatId` (`null` clears it), `buyerReference` (your Leitweg-ID for XRechnung), `purchaseOrderReference` (printed as your PO number), `invoiceLanguage` (`de` or `en`) and `eInvoiceFormat`.
* **AllRide chooses how you pay.** `preferredPaymentMethodType` is `sepa-debit` (SEPA Direct Debit, the default) or `bank-transfer` (you pay each invoice by bank transfer). It is set by AllRide and read-only for you; talk to your AllRide account manager if you would like to switch.

Rules:

* Fields that only AllRide sets, such as `mode`, `paymentTermsDays`, `voidedRedemptionsBillable` and `preferredPaymentMethodType`, are refused with `data-failed-validation` and the constraint `admin-only-field`.
* The first two letters of `vatId` must match the country of your address (Greece: `EL`), else the constraint is `vat-id-country-mismatch`.
* AllRide checks EU VAT IDs against VIES. Changing `vatId` or the address country resets `vatIdStatus` to `unverified` until the new check completes.
* `missingItems` lists what blocks invoicing: `legal-name`, `address`, `invoice-contact`, `vat-id` (for EU customers outside Germany a valid VAT ID is required) and `buyer-reference` (required for XRechnung). Your account is `active` when the list is empty and `incomplete` otherwise; it switches back and forth automatically. An incomplete account still records usage, but AllRide cannot issue its invoice until you complete it.

**Contacts** decide who receives billing emails. Each contact has an email, an optional name and at least one role: `invoices` (invoice and Stornorechnung emails, including the SEPA pre-notification), `dunning` (reminders and dunning notices) and `payment-failures` (failed debits).

| Operation | Endpoint |
| - | - |
| [List billing contacts](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-contacts-list.md) | `GET /consumer/v1/billing/contacts` |
| [Add a billing contact](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-contacts-create.md) | `POST /consumer/v1/billing/contacts` |
| [Update a billing contact](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-contacts-update.md) | `PATCH /consumer/v1/billing/contacts/{billingContactId}` (name and roles; to change the email, remove and add) |
| [Remove a billing contact](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-contacts-delete.md) | `DELETE /consumer/v1/billing/contacts/{billingContactId}` |

An email that is already a contact answers 409 [`billing-contact-exists`](https://docs-consumer.voucher.allride.io/errors/catalog#billing-contact-exists); a contact without a role fails with the constraint `billing-contact-role-required`. At least one contact with the role `invoices` is required for invoicing. Changing the account or its contacts requires a sign-in within the last 15 minutes, because these settings decide where invoices go.

Billing writes stay possible while your partner is suspended, so you can fix payment details. They are dashboard-only: an API key cannot hold `manage-consumer-billing`.

## SEPA Direct Debit mandate

> [!NOTE]
>
> **Coming soon.** SEPA Direct Debit and the payment-method operations of this section are not available yet. AllRide switches them on after sign-off and announces it by email to your technical contact (`contacts.technicalEmail`). Until then, pay your invoices by bank transfer as printed on each invoice.

You set up a SEPA Direct Debit mandate when AllRide has chosen SEPA Direct Debit for you (`preferredPaymentMethodType` is `sepa-debit`). The mandate is yours to sign, so you set it up yourself **in the consumer dashboard**, under [Billing › Payment method](https://consumer.voucher.allride.io/go/billing-payment-method). The operation behind it, `POST /consumer/v1/billing/payment-methods:setup-sepa-debit` ([Set up SEPA Direct Debit](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-payment-methods-setup-sepa-debit.md)), needs `manage-consumer-billing` and a recent sign-in, so API keys cannot call it. If AllRide collects your invoices by bank transfer, it answers 409 [`sepa-not-enabled`](https://docs-consumer.voucher.allride.io/errors/catalog#sepa-not-enabled).

1. A member with `manage-consumer-billing` starts the setup. The request has no body. The response holds the new payment method (`setup-pending`), the Stripe `clientSecret` (shown once), Stripe's `publishableKey` and the `creditor` (AllRide's name and SEPA creditor ID).
2. The dashboard loads Stripe.js with `publishableKey` and shows Stripe's IBAN field together with the account holder's name and email and the SEPA mandate text naming the creditor. The IBAN goes straight to Stripe: AllRide never receives the full IBAN and stores only the last four digits (`ibanLast4`), the bank code and the bank country.
3. You accept the mandate, and the dashboard confirms it with Stripe:

```js theme={null}
const stripe = await loadStripe(setup.publishableKey);
const iban = stripe.elements().create("iban", { supportedCountries: ["SEPA"] });
iban.mount("#iban");
// after the user accepted the mandate text
await stripe.confirmSepaDebitSetup(setup.clientSecret, {
  payment_method: {
    sepa_debit: iban,
    billing_details: { name: "Example Transit GmbH", email: "billing@example.com" },
  },
});
```

4. The payment method stays `setup-pending` until Stripe confirms the mandate, usually within a minute, then it is `active` and becomes your default. The dashboard polls [Get a payment method](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-payment-methods-get.md) until then. A setup that is not confirmed within 24 hours (`setupExpiresAt`) ends `setup-failed`; remove it or start a new one.

**One mandate at a time.** You have one SEPA mandate. To change the bank account, start a new setup (the dashboard's button reads "Replace mandate"):

* Starting it removes any other unfinished setup and cancels its SetupIntent.
* Your current mandate keeps collecting until Stripe confirms the new one. Then the new mandate is `active` and the default, and the old one is `removed` with `deactivatedReasonClass: replaced`. Scheduled debits move to the new mandate, with a new pre-notification. The webhook [`payment-method-deactivated`](https://docs-consumer.voucher.allride.io/webhooks/events/payment-method-deactivated) reports the old one with `reasonClass: replaced`, and the activation email names the IBAN it replaced.
* If the new setup fails, your current mandate stays.

Read your payment methods with [List payment methods](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-payment-methods-list.md) (`GET /consumer/v1/billing/payment-methods`, removed mandates left out unless `filter[status]` asks for them) and [Get a payment method](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-payment-methods-get.md). In the dashboard you can remove the mandate or an unfinished setup (`:remove`); removing a setup that did not succeed cancels it and does not touch your active mandate.

**Pre-notification and collection date.** The invoice email is the SEPA pre-notification: it states the amount, the collection date, the mandate reference, AllRide's creditor ID and the last four digits of your IBAN. AllRide collects on the due date, but never earlier than 3 days after the email was sent, moved to the next TARGET2 business day.

**Failed debits.** Every failed debit sends the webhook [`payment-failed`](https://docs-consumer.voucher.allride.io/webhooks/events/payment-failed) and an email to contacts with the role `payment-failures`.

* **Soft failures** (for example insufficient funds) are retried twice, 7 and 14 days after the failure is reported, within 30 days of the first failure. Each retry comes with a new pre-notification.
* **Hard failures** (mandate revoked, account closed, account details wrong) deactivate the mandate ([`payment-method-deactivated`](https://docs-consumer.voucher.allride.io/webhooks/events/payment-method-deactivated)) and move the invoice to bank transfer; your contacts receive the bank-transfer instructions. Set up a new mandate to return to direct debit.

Invoices above the SEPA limit (€10,000 by default) are paid by bank transfer.

## Invoices and Stornorechnungen

> [!NOTE]
>
> **Coming soon.** AllRide is reviewing the first billing months internally before it issues invoices. Until the first invoice is issued, the invoice list is empty and no `invoice-*` webhook is sent; your [usage estimate](#usage-and-pricing) already shows what you will be billed.

| Operation | Endpoint |
| - | - |
| [List invoices](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-list.md) | `GET /consumer/v1/billing/invoices` |
| [Get an invoice](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-get.md) | `GET /consumer/v1/billing/invoices/{invoiceId}` |
| [List invoice lines](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-lines.md) | `GET /consumer/v1/billing/invoices/{invoiceId}/lines` |
| [Download an invoice document](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-document.md) | `GET /consumer/v1/billing/invoices/{invoiceId}/document?format=pdf` or `format=xml` |
| [Resend an invoice](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-resend.md) (dashboard) | `POST /consumer/v1/billing/invoices/{invoiceId}:resend` |

* You see only issued documents. Drafts in review are invisible (404 [`invoice-not-found`](https://docs-consumer.voucher.allride.io/errors/catalog#invoice-not-found)).
* Numbers are gapless per year in one series, for example `VP-R-2026-000042`. Stornorechnungen use the same series.
* `kind` tells you what an invoice is: `periodic` (the monthly invoice), `final` (after offboarding), `corrective` (a corrected invoice issued after a cancellation) or `cancellation` (a Stornorechnung, see below).
* Invoice statuses: `finalised` (issued, email not yet sent), `sent`, `partially-paid`, `paid`, `overdue`, `uncollectible` and `void` (cancelled by a Stornorechnung).
* Each invoice line shows the provider, voucher set, quantity, `unitPrice` and net amount. Amounts are `Money` in cents; tax rates are decimal strings such as `"19.00"`.

### Corrections: Stornorechnung

An issued invoice is never edited or deleted (GoBD). If an invoice is wrong, AllRide cancels it with a **Stornorechnung** (cancellation invoice) and then issues a corrected invoice in the usual way:

1. The Stornorechnung is an invoice of its own with `kind: cancellation`, a new number in the same series and `cancelsInvoiceId` pointing to the cancelled invoice. Its document refers to the original invoice number and date.
2. It mirrors the original lines with **negative amounts**: each line has a negative `quantity` and `netAmount` with the original, positive `unitPrice`; `netAmount`, `taxAmount`, `grossAmount` and the tax breakdown are negative. Nothing is due on it: `amountDue` is `0`, `paymentInstructions.type` is `settled` and it stays `finalised` or `sent`.
3. The original invoice becomes `void`, with `cancelledByInvoiceId` naming the Stornorechnung and `amountCancelled` equal to its gross amount. Open SEPA debits or bank transfer requests for it are cancelled, and anything you already paid on it moves to your credit balance, which AllRide applies to your next invoices.
4. Where you should be billed again, AllRide issues a corrected invoice (`kind: corrective`) that you pay as usual.

Both documents reach you like any other invoice: by email to your `invoices` contacts, in the invoice list and through the [`invoice-finalised`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-finalised) webhook. The cancelled invoice also sends [`invoice-voided`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-voided). In your bookkeeping, post the Stornorechnung against the original invoice; together they net to zero.

**Downloads.** The document endpoint returns a short-lived link, not the file:

```json theme={null}
{
  "data": {
    "resource": "document-download",
    "format": "xml",
    "url": "https://storage.googleapis.com/allride-voucher-billing/VP-R-2026-000042.xml?X-Goog-Signature=example",
    "expiresAt": "2026-11-02T08:20:00Z",
    "sha256": "9f2c1b7e4d3a5c6b8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
    "sizeBytes": 48211,
    "fileName": "VP-R-2026-000042.xml"
  }
}
```

The `url` is valid for **15 minutes**: download immediately and do not store the URL; ask again when you need the file later. Compare the file's SHA-256 with `sha256`. A document that is still being rendered answers 409 [`invoice-document-not-ready`](https://docs-consumer.voucher.allride.io/errors/catalog#invoice-document-not-ready) with `Retry-After: 30`.

### Fetching invoices into your ERP with an API key

1. Create an API key with the scope `view-consumer-billing` in the [developer dashboard](https://consumer-developers.voucher.allride.io/go/api-keys).
2. Subscribe a webhook endpoint to [`invoice-finalised`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-finalised), which is sent once the document exists (for Stornorechnungen too), and to [`invoice-voided`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-voided) to mark cancelled invoices.
3. On each webhook, request the document (`format=xml` for machine processing), download it and verify the hash:

```bash theme={null}
INVOICE_ID=19017
DOWNLOAD=$(curl -s "$VOUCHER_API_BASE_URL/consumer/v1/billing/invoices/$INVOICE_ID/document?format=xml" \
  -H "Authorization: Bearer $VOUCHER_API_KEY")
DOCUMENT_URL=$(echo "$DOWNLOAD" | jq -r '.data.url')
EXPECTED_SHA256=$(echo "$DOWNLOAD" | jq -r '.data.sha256')
curl -s -o invoice.xml "$DOCUMENT_URL"
echo "$EXPECTED_SHA256  invoice.xml" | shasum -a 256 -c -
```

4. As a fallback for missed webhooks, poll daily for invoices issued since your last run:

```bash theme={null}
curl -G "$VOUCHER_API_BASE_URL/consumer/v1/billing/invoices" \
  -H "Authorization: Bearer $VOUCHER_API_KEY" \
  --data-urlencode "filter[issueDate][gte]=2026-11-01" \
  --data-urlencode "sort=issueDate"
```

Stornorechnungen come through the same endpoints; tell them apart by `kind: cancellation` and match them to the original through `cancelsInvoiceId`.

## E-invoices (ZUGFeRD/XRechnung)

> [!NOTE]
>
> **Coming soon.** E-invoices arrive with the first issued invoice (see [Invoices and Stornorechnungen](#invoices-and-stornorechnungen)). Make sure your billing account has the right `eInvoiceFormat` and, for XRechnung, `buyerReference` (your Leitweg-ID) beforehand, so the first invoice is issued in the right format.

Every invoice, Stornorechnungen included, is an e-invoice according to EN 16931. You choose the format with `eInvoiceFormat` on your billing account:

| `eInvoiceFormat` | What you get |
| - | - |
| `zugferd-en16931` (default) | A PDF/A-3 with the embedded EN 16931 CII XML (`factur-x.xml`), ZUGFeRD profile EN 16931. `format=xml` returns the same XML as a separate file |
| `xrechnung-cii` | For public-sector buyers: XRechnung in CII syntax. The XML is the legal original and the PDF a visualisation; the invoice email attaches both |

XRechnung requires your Leitweg-ID in `buyerReference` (BT-10). Without it your account is incomplete and invoicing is blocked. Every document is validated (XML schema, Schematron, PDF/A) before it is issued. Documents are in your `invoiceLanguage`.

## Usage and pricing

`GET /consumer/v1/billing/usage?serviceMonth=2026-11` ([Get the usage estimate](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-usage-get.md)) shows what you have used in a Berlin service month (default: the current month; up to 13 months back), per provider and voucher set: `quantity`, `voidedQuantity`, `unitPrice`, `netAmount` and `priced`, plus totals and `asOf`.

* Until the month is invoiced the response is an **estimate** (`isEstimate: true`), updated within about 2 minutes of each redemption. Once invoiced, `invoiced: true` and the amounts come from the invoice.
* `priced: false` means the price is still to be confirmed; such lines have no amounts.
* `unitPrice` is a `UnitPrice`: `{value, scale: 4, label}` with `value` in ten-thousandths of a euro, so `1000` is €0.10 and `1250` is €0.1250. Totals are `Money` in cents.
* Unit prices are set by AllRide for you and may differ per provider and voucher set; a price of zero is possible. You see only the resolved price that applies to you, never how it was derived. The Price Terms per voucher set and your acceptance of them are in [Prices and price acceptance](https://docs-consumer.voucher.allride.io/consumer/prices.md).

For reconciliation in your ERP, `GET /consumer/v1/billing/usage/lines?filter[serviceMonth]=2026-11` ([List usage lines](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-usage-lines.md)) pages the same lines; `filter[serviceMonth]` is required. `GET /consumer/v1/billing/balance` ([Get the balance](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-balance-get.md)) shows your open, overdue and credit amounts, your `standing` and the next planned collection.

For files, page through [List invoices](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-invoices-list.md) or the usage lines of one service month as described in [Downloading large lists](https://docs-consumer.voucher.allride.io/guides/pagination.md#downloading-large-lists).

## Payments and dunning

> [!NOTE]
>
> **Coming soon.** The payment list, the balance and the dunning emails start with the first issued invoice. The operations below are documented ahead of their release.

`GET /consumer/v1/billing/payments` ([List payments](https://docs-consumer.voucher.allride.io/api-reference/consumer-billing-payments-list.md)) lists every payment attempt with its method (`sepa-debit`, `bank-transfer` or `manual`), status, amount and, for failures, the failure class and the next attempt date.

**Bank transfer.** Invoices are paid by bank transfer when AllRide has chosen bank transfer for you (`preferredPaymentMethodType` is `bank-transfer`), when you have no active mandate, and when they are above the SEPA limit. Pay to the account in `bankTransferInstructions` of your billing account (also printed on the invoice) and use **exactly the reference printed on the invoice**, so the payment is matched automatically. AllRide applies transfers it cannot match by hand. Payment terms are 14 days unless agreed otherwise (`paymentTermsDays`).

**Dunning** (days after the due date, Berlin time):

| Day | Step | Email to contacts with role `dunning` |
| - | - | - |
| +3 | Payment reminder | Yes |
| +14 | First dunning notice | Yes |
| +28 | Second and final dunning notice | Yes |
| +42 | Account flagged `delinquent` | No; AllRide contacts you |

Your billing account and balance show the current level as `standing` (`good-standing`, `reminded`, `dunning-1`, `dunning-2`, `delinquent`). No fees or interest are added automatically, and AllRide never stops your redemptions automatically for non-payment. Emails are sent on business days only.

## Billing webhooks

These webhook types are only for consumers. Subscribing an endpoint to them requires `view-consumer-billing`. The `payload` starts with `resource` and `id`, is the consumer view of the resource and never contains payment-provider messages.

| Type | Sent when | `payload` |
| - | - | - |
| [`invoice-finalised`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-finalised) | An invoice, also a Stornorechnung, is issued and its document is ready to download | `Invoice` |
| [`invoice-paid`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-paid) | An invoice is fully paid | `Invoice` |
| [`invoice-overdue`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-overdue) | An invoice passes its due date unpaid | `Invoice` |
| [`invoice-voided`](https://docs-consumer.voucher.allride.io/webhooks/events/invoice-voided) | AllRide cancels an invoice with a Stornorechnung | `Invoice` with status `void`, plus `cancellationInvoiceId`, the Stornorechnung (also in `cancelledByInvoiceId`) |
| [`payment-failed`](https://docs-consumer.voucher.allride.io/webhooks/events/payment-failed) | A payment attempt fails | The payment (`resource: payment`) with `invoiceId`, `failureClass` and `nextAttemptDate` |
| [`payment-method-deactivated`](https://docs-consumer.voucher.allride.io/webhooks/events/payment-method-deactivated) | A mandate becomes inactive | The mandate (`resource: payment-method`) with `ibanLast4` and `reasonClass` |

Deliveries follow the general [webhook rules](https://docs-consumer.voucher.allride.io/webhooks/overview.md): at least once, unordered, signed.

## Permissions

| Permission | Grants | API keys |
| - | - | - |
| `view-consumer-billing` | Read the billing account, contacts, payment methods (masked), invoices (Stornorechnungen included), payments, usage and balance; download documents; subscribe to billing webhooks | Yes (delegable) |
| `manage-consumer-billing` | Edit the billing account and contacts, set up and remove mandates, resend documents | No: dashboard only. Creating an API key with this scope fails with the constraint `scope-not-delegable` |

The default groups `owners`, `administrators` and `billing` hold both permissions. The groups `developers` and `viewers` do not read billing data.

## Related

* [Prices and price acceptance](https://docs-consumer.voucher.allride.io/consumer/prices.md)
* [Analytics](https://docs-consumer.voucher.allride.io/consumer/analytics.md)
* [Pagination, filtering and sorting](https://docs-consumer.voucher.allride.io/guides/pagination.md)
* [Webhooks](https://docs-consumer.voucher.allride.io/webhooks/overview.md)
* [Error catalog](https://docs-consumer.voucher.allride.io/errors/catalog.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.