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— Admin Apply CreditGET /api/v1/admin/billing/invoices— Admin List InvoicesPOST /api/v1/admin/billing/invoices— Admin Create InvoicePOST /api/v1/admin/billing/invoices/regenerate-missing-pdfs— Admin Regenerate Missing PdfsGET /api/v1/admin/billing/invoices/{invoice_id}— Admin Get InvoicePATCH /api/v1/admin/billing/invoices/{invoice_id}— Admin Edit InvoicePOST /api/v1/admin/billing/invoices/{invoice_id}/credit-note— Admin Create Credit NotePOST /api/v1/admin/billing/invoices/{invoice_id}/finalize— Admin Finalize InvoicePUT /api/v1/admin/billing/invoices/{invoice_id}/line-items/order— Admin Reorder Line ItemsPOST /api/v1/admin/billing/invoices/{invoice_id}/line-items/sort-by-date— Admin Sort Line Items By DatePOST /api/v1/admin/billing/invoices/{invoice_id}/refund— Admin Refund InvoicePOST /api/v1/admin/billing/invoices/{invoice_id}/regenerate-pdf— Admin Regenerate Invoice PdfPOST /api/v1/admin/billing/invoices/{invoice_id}/send— Admin Send InvoicePOST /api/v1/admin/billing/invoices/{invoice_id}/void— Admin Void InvoicePATCH /api/v1/admin/billing/payouts/{split_id}— Admin Update Payout StatusGET /api/v1/admin/billing/templates— Admin List TemplatesPOST /api/v1/admin/billing/templates— Admin Upload TemplatePOST /api/v1/admin/billing/templates/designer— Designer Save TemplateGET /api/v1/admin/billing/templates/designer/by-key— Designer Get By KeyPOST /api/v1/admin/billing/templates/designer/preview— Designer PreviewPOST /api/v1/admin/billing/templates/designer/validate— Designer Validate TemplateGET /api/v1/admin/billing/templates/designer/{template_id}— Designer Get TemplatePUT /api/v1/admin/billing/templates/designer/{template_id}— Designer Update TemplateGET /api/v1/admin/billing/templates/groups— Admin List Template GroupsPOST /api/v1/admin/billing/templates/send-test-email— Send Test EmailPOST /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 refundauthorization(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: object422— 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}