---
title: "Admin \u2014 billing & invoices"
path: reference/api/admin-billing
status: published
---

# Admin — billing & invoices

**26 endpoints** in this group. All paths are prefixed with `/api/v1`.

## Endpoints in this group

- [`POST /api/v1/admin/billing/credits`](#post-api-v1-admin-billing-credits) — Admin Apply Credit
- [`GET /api/v1/admin/billing/invoices`](#get-api-v1-admin-billing-invoices) — Admin List Invoices
- [`POST /api/v1/admin/billing/invoices`](#post-api-v1-admin-billing-invoices) — Admin Create Invoice
- [`POST /api/v1/admin/billing/invoices/regenerate-missing-pdfs`](#post-api-v1-admin-billing-invoices-regenerate-missing-pdfs) — Admin Regenerate Missing Pdfs
- [`GET /api/v1/admin/billing/invoices/{invoice_id}`](#get-api-v1-admin-billing-invoices-invoice-id) — Admin Get Invoice
- [`PATCH /api/v1/admin/billing/invoices/{invoice_id}`](#patch-api-v1-admin-billing-invoices-invoice-id) — Admin Edit Invoice
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/credit-note`](#post-api-v1-admin-billing-invoices-invoice-id-credit-note) — Admin Create Credit Note
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/finalize`](#post-api-v1-admin-billing-invoices-invoice-id-finalize) — Admin Finalize Invoice
- [`PUT /api/v1/admin/billing/invoices/{invoice_id}/line-items/order`](#put-api-v1-admin-billing-invoices-invoice-id-line-items-order) — Admin Reorder Line Items
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/line-items/sort-by-date`](#post-api-v1-admin-billing-invoices-invoice-id-line-items-sort-by-date) — Admin Sort Line Items By Date
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/refund`](#post-api-v1-admin-billing-invoices-invoice-id-refund) — Admin Refund Invoice
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/regenerate-pdf`](#post-api-v1-admin-billing-invoices-invoice-id-regenerate-pdf) — Admin Regenerate Invoice Pdf
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/send`](#post-api-v1-admin-billing-invoices-invoice-id-send) — Admin Send Invoice
- [`POST /api/v1/admin/billing/invoices/{invoice_id}/void`](#post-api-v1-admin-billing-invoices-invoice-id-void) — Admin Void Invoice
- [`PATCH /api/v1/admin/billing/payouts/{split_id}`](#patch-api-v1-admin-billing-payouts-split-id) — Admin Update Payout Status
- [`GET /api/v1/admin/billing/templates`](#get-api-v1-admin-billing-templates) — Admin List Templates
- [`POST /api/v1/admin/billing/templates`](#post-api-v1-admin-billing-templates) — Admin Upload Template
- [`POST /api/v1/admin/billing/templates/designer`](#post-api-v1-admin-billing-templates-designer) — Designer Save Template
- [`GET /api/v1/admin/billing/templates/designer/by-key`](#get-api-v1-admin-billing-templates-designer-by-key) — Designer Get By Key
- [`POST /api/v1/admin/billing/templates/designer/preview`](#post-api-v1-admin-billing-templates-designer-preview) — Designer Preview
- [`POST /api/v1/admin/billing/templates/designer/validate`](#post-api-v1-admin-billing-templates-designer-validate) — Designer Validate Template
- [`GET /api/v1/admin/billing/templates/designer/{template_id}`](#get-api-v1-admin-billing-templates-designer-template-id) — Designer Get Template
- [`PUT /api/v1/admin/billing/templates/designer/{template_id}`](#put-api-v1-admin-billing-templates-designer-template-id) — Designer Update Template
- [`GET /api/v1/admin/billing/templates/groups`](#get-api-v1-admin-billing-templates-groups) — Admin List Template Groups
- [`POST /api/v1/admin/billing/templates/send-test-email`](#post-api-v1-admin-billing-templates-send-test-email) — Send Test Email
- [`POST /api/v1/admin/billing/templates/{template_id}/preview`](#post-api-v1-admin-billing-templates-template-id-preview) — Admin Preview Template

---

### POST `/api/v1/admin/billing/credits` — Admin Apply Credit {#post-api-v1-admin-billing-credits}

Apply a credit note to a tenant's account.

Creates a negative-amount invoice (credit note) that offsets
the tenant's balance.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `AdminCreditRequest` — {`tenant_id`, `amount_cents`, `reason`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/invoices` — Admin List Invoices {#get-api-v1-admin-billing-invoices}

List all invoices (admin view). Supports filtering by status and tenant.

**Parameters**:

- `page` (query, integer, optional)
- `page_size` (query, integer, optional)
- `status` (query, string, optional)
- `tenant_id` (query, string, optional)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `PaginatedResponse_InvoiceResponse_` — {`data`, `pagination`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices` — Admin Create Invoice {#post-api-v1-admin-billing-invoices}

Create a manual draft invoice for a tenant.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `AdminInvoiceCreateRequest` — {`tenant_id`, `partner_id`, `currency`, `invoice_date` + 3 more}


**Responses**:

- `201` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/regenerate-missing-pdfs` — Admin Regenerate Missing Pdfs {#post-api-v1-admin-billing-invoices-regenerate-missing-pdfs}

Batch regenerate PDFs for all finalized invoices missing one.

Limited to `limit` invoices per call (default 50, max 500).

**Parameters**:

- `limit` (query, integer, optional)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_dict_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/invoices/{invoice_id}` — Admin Get Invoice {#get-api-v1-admin-billing-invoices-invoice-id}

Get invoice detail with line items (admin view).

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### PATCH `/api/v1/admin/billing/invoices/{invoice_id}` — Admin Edit Invoice {#patch-api-v1-admin-billing-invoices-invoice-id}

Edit a draft invoice (notes, due_date, line items).

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `AdminInvoiceEditRequest` — {`notes`, `invoice_date`, `due_date`, `period_start` + 2 more}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/credit-note` — Admin Create Credit Note {#post-api-v1-admin-billing-invoices-invoice-id-credit-note}

Issue a credit note against a finalized/sent/paid invoice.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `CreditNoteCreateRequest` — {`reason`, `line_items`}


**Responses**:

- `201` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/finalize` — Admin Finalize Invoice {#post-api-v1-admin-billing-invoices-invoice-id-finalize}

Finalize an invoice: lock it, snapshot buyer/seller, calculate VAT, generate PDF.

Optionally accepts an invoice_date override in the request body.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `AdminInvoiceFinalizeRequest` | null


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### PUT `/api/v1/admin/billing/invoices/{invoice_id}/line-items/order` — Admin Reorder Line Items {#put-api-v1-admin-billing-invoices-invoice-id-line-items-order}

Reorder a draft invoice's line items.

Body specifies the new order as a list of line-item IDs. Every existing
line must appear exactly once. Order_index is rewritten 0..N-1 in the
given order. Rejects finalized invoices.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `LineItemReorderRequest` — {`line_item_ids`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/line-items/sort-by-date` — Admin Sort Line Items By Date {#post-api-v1-admin-billing-invoices-invoice-id-line-items-sort-by-date}

Sort a draft invoice's line items by leading DD-MM-YYYY in description.

Lines whose description doesn't start with a parseable date are pushed
to the end, preserving their relative current order. Only works on
draft invoices.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/refund` — Admin Refund Invoice {#post-api-v1-admin-billing-invoices-invoice-id-refund}

Refund a paid invoice (full or partial) via the original payment provider.

**Parameters**:

- `invoice_id` (path, string, required)
- `amount_cents` (query, string, optional) — Partial refund amount; omit for full refund
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_dict_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/regenerate-pdf` — Admin Regenerate Invoice Pdf {#post-api-v1-admin-billing-invoices-invoice-id-regenerate-pdf}

Regenerate the PDF for a finalized invoice using its frozen snapshots.

Use this for invoices whose PDF generation failed previously (e.g. due to
missing dependencies). Does not change invoice data — only re-renders.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/send` — Admin Send Invoice {#post-api-v1-admin-billing-invoices-invoice-id-send}

Send an invoice by email via ScaiSend.

Attaches the PDF and optional structured e-invoice (UBL, XRechnung, CII,
ZUGFeRD). Transitions status from 'finalized' to 'sent'. Can be re-sent
if already in 'sent' status.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `InvoiceSendRequest` — {`recipient_override`, `einvoice_format`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_dict_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/invoices/{invoice_id}/void` — Admin Void Invoice {#post-api-v1-admin-billing-invoices-invoice-id-void}

Void an invoice. Only draft or sent invoices can be voided.

**Parameters**:

- `invoice_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### PATCH `/api/v1/admin/billing/payouts/{split_id}` — Admin Update Payout Status {#patch-api-v1-admin-billing-payouts-split-id}

Update the payout status of a marketplace revenue split.

**Parameters**:

- `split_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `UpdatePayoutStatusRequest` — {`status`, `payout_reference`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_dict_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/templates` — Admin List Templates {#get-api-v1-admin-billing-templates}

List invoice templates, optionally filtered by partner.

**Parameters**:

- `partner_id` (query, string, optional)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_list_InvoiceTemplateResponse__` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates` — Admin Upload Template {#post-api-v1-admin-billing-templates}

Upload a partner invoice template (HTML).

**Parameters**:

- `authorization` (header, string, optional)


**Responses**:

- `201` — Successful Response. Returns: `ApiResponse_InvoiceTemplateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates/designer` — Designer Save Template {#post-api-v1-admin-billing-templates-designer}

Upsert a designer template by (name, document_type, language).

Templates are global (no partner_id) — partner/tenant assignment lives on
the partner_configuration / tenant_billing_profiles tables. Saving the
same (name, type, language) again replaces the existing variant; saving a
new language for the same name creates a new variant under that name.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `InvoiceTemplateDesignerSave` — {`name`, `document_type`, `language`, `partner_id` + 5 more}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceTemplateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/templates/designer/by-key` — Designer Get By Key {#get-api-v1-admin-billing-templates-designer-by-key}

Load the designer variant for (name, document_type, language).

`language` omitted or empty means the any-language fallback row.
Returns 404 if no row exists for that key — the caller treats that as
"blank canvas" in the designer.

**Parameters**:

- `name` (query, string, required)
- `document_type` (query, string, optional)
- `language` (query, string, optional)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceTemplateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates/designer/preview` — Designer Preview {#post-api-v1-admin-billing-templates-designer-preview}

Render designer HTML with sample data for live preview.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `InvoiceTemplateDesignerSave` — {`name`, `document_type`, `language`, `partner_id` + 5 more}


**Responses**:

- `200` — Successful Response. Returns: —
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates/designer/validate` — Designer Validate Template {#post-api-v1-admin-billing-templates-designer-validate}

Compile the supplied html_content and subject through Jinja2.

Always returns 200 — the body says whether the template parses. Used by
the designer for live feedback while the user types, so we never have
error responses on a `valid input` happy path.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `TemplateValidateRequest` — {`html_content`, `subject`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_TemplateValidateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/templates/designer/{template_id}` — Designer Get Template {#get-api-v1-admin-billing-templates-designer-template-id}

Load a template with full content for the designer.

**Parameters**:

- `template_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceTemplateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### PUT `/api/v1/admin/billing/templates/designer/{template_id}` — Designer Update Template {#put-api-v1-admin-billing-templates-designer-template-id}

Save template content from the visual designer.

**Parameters**:

- `template_id` (path, string, required)
- `authorization` (header, string, optional)


**Body**: `InvoiceTemplateDesignerSave` — {`name`, `document_type`, `language`, `partner_id` + 5 more}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_InvoiceTemplateResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### GET `/api/v1/admin/billing/templates/groups` — Admin List Template Groups {#get-api-v1-admin-billing-templates-groups}

List templates grouped by (name, document_type), each with the set of
languages that have a saved variant. This is what the templates list page
and the partner/tenant template-pickers consume.

**Parameters**:

- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: object
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates/send-test-email` — Send Test Email {#post-api-v1-admin-billing-templates-send-test-email}

Render an email template against sample data and send it via ScaiSend.

Resolves the template by (name, document_type, language) using the same
lookup as the live send path. The email is sent to `recipient` so the
admin can preview formatting end-to-end before assigning the template.

**Parameters**:

- `authorization` (header, string, optional)


**Body**: `SendTestEmailRequest` — {`recipient`, `name`, `document_type`, `language`}


**Responses**:

- `200` — Successful Response. Returns: `ApiResponse_SendTestEmailResponse_` — {`data`, `meta`}
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}


### POST `/api/v1/admin/billing/templates/{template_id}/preview` — Admin Preview Template {#post-api-v1-admin-billing-templates-template-id-preview}

Render a template with sample data and return the HTML preview.

**Parameters**:

- `template_id` (path, string, required)
- `authorization` (header, string, optional)


**Responses**:

- `200` — Successful Response. Returns: —
- `422` — Validation Error. Returns: `HTTPValidationError` — {`detail`}
