Skip to content

Invoices API

All endpoints require authentication and invoices tool permissions.

GET /api/invoices/mapping-rules

Permission: invoices:view

Response: { rules } — each rule includes service_type_name from joined service_types.

PUT /api/invoices/mapping-rules/:serviceTypeId

Permission: invoices:manage

Body:

FieldTypeRequiredDescription
xero_account_codestringYesXero account code to map to
descriptionstringNoOptional description

Response: { rule }


GET /api/invoices

Permission: invoices:view

Query parameters:

ParamTypeDescription
statusstringFilter by invoice status
company_idstringFilter by company
budget_idstringFilter by budget
project_idstringFilter by project (via budget)
deal_idstringFilter by deal (via budget)

Response: { invoices } — each invoice includes company_name, contact_name, and budget_name.

POST /api/invoices

Permission: invoices:update

Body:

FieldTypeRequiredDescription
budget_idstringNoLink to a budget
invoice_numberstringNoCustom invoice number (auto-generated if omitted)
currencystringNoCurrency code (default: AUD)
due_datestringNoDue date (YYYY-MM-DD)
issued_datestringNoIssue date (defaults to today)
notesstringNoFree-text notes
company_idstringNoCompany ID
contact_idstringNoContact ID
generate_from_budgetbooleanNoAuto-generate line items from budget

When generate_from_budget is true, line item generation depends on the budget type:

  • Sprints / Retainer: copies budget line items at their fixed amounts. Retainer budgets can only be invoiced once.
  • Time & Materials: invoices only approved, uninvoiced time per line item.
  • Fixed Price: invoices the remaining uninvoiced amount as a single line item.

Tax is calculated at 10% GST. Auto-completes client onboarding milestone first_invoice for the company’s first invoice.

Response: { invoice } (201)

GET /api/invoices/:id

Permission: invoices:view

Response: { invoice, line_items, payments }

The invoice includes company_name, contact_name, budget_name, project_name, project_id, po_number, xero_status, and xero_url. If linked to Xero, the status is synced live from Xero on each request.

PUT /api/invoices/:id

Permission: invoices:update

Body: Any of the following fields:

FieldTypeDescription
invoice_numberstringInvoice number
statusstringInvoice status
currencystringCurrency code
due_datestringDue date
issued_datestringIssue date
notesstringNotes
company_idstringCompany ID
contact_idstringContact ID
budget_idstringBudget ID
xero_invoice_idstringXero invoice ID

Response: { invoice }

DELETE /api/invoices/:id

Permission: invoices:manage

If linked to Xero, the invoice is deleted (if DRAFT) or voided (if AUTHORISED+) in Xero before local deletion.

Response: { ok: true }


POST /api/invoices/:id/push-to-xero

Permission: invoices:update

Creates a DRAFT invoice in Xero from the local invoice and line items. Uses the company name as the Xero contact, and maps line item account codes from mapping rules. Sets local status to finalised.

Response: { invoice, xero_invoice_id }

POST /api/invoices/:id/xero-approve

Permission: invoices:manage

Transitions a Xero DRAFT invoice to AUTHORISED. Sets local status to approved.

Response: { invoice }

POST /api/invoices/:id/xero-send

Permission: invoices:manage

Sends an AUTHORISED Xero invoice via email. Sets local status to sent.

Response: { invoice }

POST /api/invoices/:id/xero-void

Permission: invoices:manage

Voids the Xero invoice. Sets local status to voided.

Response: { invoice }

POST /api/invoices/:id/xero-delete

Permission: invoices:manage

Deletes the Xero invoice (DRAFT only). Clears the local Xero ID and resets status to draft.

Response: { invoice }

GET /api/invoices/:id/pdf

Permission: invoices:view

Downloads the invoice PDF from Xero. Returns application/pdf with Content-Disposition: attachment.

POST /api/invoices/sync-xero

Permission: invoices:update

Batch syncs payment status, amounts paid/due, and individual payments for all Xero-linked invoices.

Response: { updated, errors, synced_at }

POST /api/invoices/:id/sync-xero

Permission: invoices:update

Syncs payment status and payments for a single Xero-linked invoice.

Response: { invoice, payments, xero_status, payment_status }


PUT /api/invoices/:id/line-items/reorder

Permission: invoices:update

Body:

FieldTypeRequiredDescription
item_idsstring[]YesOrdered array of line item IDs

Response: { ok: true }

POST /api/invoices/:id/line-items

Permission: invoices:update

Body:

FieldTypeRequiredDescription
descriptionstringYesLine item description
quantitynumberNoQuantity (default: 1)
unit_pricenumberNoUnit price (default: 0)
service_type_idstringNoService type ID
xero_account_codestringNoXero account code
tax_typestringNoTax type
positionnumberNoSort position

Automatically recalculates invoice totals (subtotal, 10% GST, total).

Response: { item } (201)

PUT /api/invoices/:id/line-items/:itemId

Permission: invoices:update

Body: Any of: description, quantity, unit_price, service_type_id, xero_account_code, tax_type, position.

Automatically recalculates line item amount and invoice totals.

Response: { item }

DELETE /api/invoices/:id/line-items/:itemId

Permission: invoices:update

Automatically recalculates invoice totals.

Response: { ok: true }