---
title: "Invoicing"
slug: admin/billing-runs
url: https://projectri.com/docs/admin/billing-runs
section: admin
audience: admin
app_route: "/[slug]/admin/billing-runs"
permissions: [finance.billing.run, finance.billing.issue, finance.billing.writeoff]
plan: commercial.billing_runs
mobile: "/billing"
updated: 2026-09-08
source: Projectri documentation
---

# Invoicing

Assemble a period's billing from approved time, expenses, fixed fees, milestones and retainer draws, review what it proposes per client, then issue it as invoices.

![Invoicing](https://projectri.com/docs-shots/admin-billing-runs.png)

## What it is

Invoicing is month-end. A **run** gathers everything billable in a period —
approved time, marked-up expenses, fixed and milestone fees, retainer draws —
and proposes **one invoice per contract**, with the write-downs and the
realisation percentage beside each total. Nothing here charges anybody until
somebody presses **Issue**.

> [!NOTE]
> This page bills **your clients**. The workspace's own subscription to
> Projectri is on [Billing](/docs/admin/billing). Readers conflate the two
> constantly; they share no data and no permission key.

## How to get there

**Money → Invoicing** in the admin console rail, above Billing on purpose:
assembling the month is why a finance lead opens the console, and paying us is a
once-a-year thought. The **ADMIN** role is required to open any console page.

Every route behind this screen is gated on the `commercial.billing_runs`
entitlement, which starts at the **Pro** tier. On top of that:

- `finance.billing.run` — assemble a run and review its proposals.
- `finance.billing.issue` — turn a proposal into an invoice. Without it the
  **Issue** buttons are not drawn.
- `finance.billing.writeoff` — reduce a line below its standard value. Without
  it the line editor is disabled and says why.

## How to use it

### Assemble a period

1. Press **New run**.
2. The dates default to **last complete month**, which is the run people open
   this screen to do. Both fields bound each other, so an end before its start
   cannot be picked.
3. Optionally narrow to one **Client**. Left as all clients, the run bills the
   whole period at once. The picker is only offered if you can read the client
   list.
4. Press **Assemble**. You land in the run's review screen.

### Review what it proposes

1. The four numbers across the top are what a month is judged on: **To bill**,
   **Written off**, **Realization**, and how many proposals are **On hold**.
2. Under them, **Not billed:** lists the assembler's own account of what it left
   out and why — period-locked time, approved time with no bill rate, time
   covered by a retainer allowance, approved time with no project, expenses
   absorbed by a retainer, scheduled fees not yet ready, and any currency with
   no exchange rate.
3. The left rail is one row per proposal, with its client, subtotal and
   realisation. A proposal billing under 90% of card rate has its percentage in
   amber.
4. Opening a run jumps straight to the first proposal that needs a decision — a
   failed one, else a pending one — rather than the first row.
5. Lines are grouped by kind: Time, Expenses, Fixed fee, Milestones, Retainer,
   Adjustments. Each row shows quantity, rate, **Standard** value and the
   **Amount** you are actually billing.

### Edit, exclude or write down a line

1. Press the pencil on a line to open the editor. It needs
   `finance.billing.writeoff`.
2. Change the **Amount** in major units — the form converts through the
   currency's own exponent, so a yen or dinar line is not out by a factor of a
   hundred.
3. Anything below the standard value is recorded as a write-off and the dialog
   says how much. A **Reason for the write-down** becomes mandatory at that
   moment, because the engine will require one anyway.
4. The circle-slash button excludes a line from the invoice without deleting it;
   it stays visible, struck through, and can be put back.

### Approve, hold and release

1. **Approve** marks a proposal ready to issue. Only approved proposals are
   picked up by a bulk issue.
2. **Hold** asks for a reason and skips the proposal on a bulk issue. A hold
   survives a re-assembly, which is the point of it.
3. **Release** puts a held proposal back to pending.

### Issue

1. **Issue** on one proposal, or **Issue N approved** in the header for the
   whole run.
2. The confirmation names the count and the sum. Two currencies read as
   "£12,000 + $4,300" rather than being added together, because no single figure
   would be an amount anybody is about to be charged.
3. Confirming creates the invoice, numbers it `INV-YYYYMM-NNNN` restarting each
   month, freezes the tax determination onto the document, and stamps every
   source row as billed — all inside one transaction. Due date defaults to
   **30 days** after the issue date.
4. A bulk issue isolates each proposal. Some succeeding and some failing is an
   ordinary outcome; the run lands on **Partly issued** and the screen reports
   the split rather than claiming success.

### Re-assemble

1. **Re-assemble** rebuilds every proposal from source — for example after
   approving more time.
2. If the run has hand-edited lines, it stops and tells you how many edits would
   be discarded. Continuing is a second, deliberate answer.

## What it affects

- **Receivables.** An issued invoice appears immediately on
  [Receivables](/docs/admin/receivables), where it ages, gets chased and can be
  credited or written off.
- **WIP.** Issuing stamps the underlying time entries, expenses, schedule items
  and retainer periods as invoiced, so they leave the unbilled balance on
  [Financials](/docs/admin/financials).
- **Realisation and margin.** Because the line keeps `standardAmount` and
  `writeOffAmount` separately from what you billed, the realisation report can
  answer "what did we give away" for every past period. A system that stored
  only the invoiced figure has thrown that away permanently.
- **The client portal.** The client sees their own copy of the invoice at
  [Invoices](/docs/portal/invoices).
- **Your ERP.** If a connection owns invoices, the new invoice is offered to it
  after the transaction commits. See the gotcha below.

## On mobile

The **Billing** screens in the phone app carry the deciding half: the list of
runs, a run's proposals, and approve, hold, release and issue on a single
proposal. There is deliberately **no New run button** — a run assembled by a
thumb on a train with the wrong period is forty proposals somebody has to throw
away. Editing lines and writing them down stay on the web.

## Limits and gotchas

> [!WARNING]
> Issuing has no undo. Every hour and expense on the proposal is marked billed
> in the same transaction that creates the invoice. That is why
> `finance.billing.issue` is its own permission key.

- **Retainer-backed work never bills twice.** Time on a contract funded by a
  retainer is consumed by the allowance and excluded from time-and-materials;
  the retainer period is billed instead. Retainers measured in **hours** are
  excluded from assembly entirely and said so out loud — their periodic fee is
  not a modelled number, so it belongs on a scheduled fee line.
- **Double-billing is structurally prevented, not prevented by convention.**
  Eligibility means "no invoice line yet", and the stamp is filtered on that
  with a count check. Two people pressing Issue at the same moment produce one
  invoice and one error. If a source row was claimed while your proposal was
  open, you get a 409 asking you to re-assemble.
- **A missing exchange rate is not fatal, but it is loud.** Amounts in a
  currency with no rate to your reporting currency are carried at 1:1 and named
  in the excluded notes. Fix it on [Finance setup](/docs/admin/finance).
- **The push to an ERP is not transactional.** The invoice is created locally
  first and the push happens afterwards, so a failed push cannot un-stamp rows
  that were already billed. A failed push marks the proposal **Failed** with the
  error, and **Retry push** re-attempts it. No connector currently has a live
  outbound invoice client, so a workspace with an ERP that owns invoices will
  see the invoice stand locally and no push happen — that is the honest state,
  not a fault.
- A run with nothing to bill is a normal answer for a period whose time is not
  approved yet. Check the "Not billed" strip before assuming the run is broken.
- Money everywhere here is in minor units on the wire and formatted for display;
  a currency's exponent is respected, so JPY has none and KWD has three.

## Related

- [Receivables](/docs/admin/receivables) — what came back after you issued.
- [Finance setup](/docs/admin/finance) — the rate cards, tax rules and exchange rates a run reads.
- [ERP](/docs/admin/finance-erp) — which system owns invoices, and what is waiting to be billed.
- [Financials](/docs/admin/financials) — WIP, realisation and margin after the run.
- [Contracts](/docs/workspace/contracts) — the contract a proposal is assembled against.

## Related

- [Receivables](https://projectri.com/docs/admin/receivables.md): What your clients owe, how late it is, what the dunning ladder is doing about it, and the credit notes, write-offs and refunds that change the balance.
- [Finance setup](https://projectri.com/docs/admin/finance.md): The configuration every financial number divides by — rate cards, working calendars, exchange rates, targets, leave, timesheet and expense policy, overtime, tax, dunning, payments, cost centres, budget alerts and the month-end close.
- [ERP](https://projectri.com/docs/admin/finance-erp.md): Which system owns each kind of finance record — yours or your accounting system's — and the approved, unbilled work waiting for the ERP to pick up.
- [Financials](https://projectri.com/docs/admin/financials.md): The finance reports — a scorecard, utilisation, project profitability, WIP and ageing, the tax return, and the exceptions list that says what to do on Monday.
- [Contracts](https://projectri.com/docs/workspace/contracts.md): The register of what the firm is bound to — every MSA, statement of work and order form, its lifecycle state, its value and whether it is still inside its period.
