# Write-Offs



Overview [#overview]

There are occasions where an individual or set of invoices may be deemed uncollectible, but still need to become settled so that they don't remain on the system, forever in an incomplete state. Additionally, use cases such as fee discounts at the invoice item level require an even more precise degree of credit handling. **Write-Offs** allow users to write off entire invoices, specific invoice items or partial amounts.

Key Capabilities [#key-capabilities]

* Target either full invoices or individual invoice items.
* Specify a custom amount per target, or allow the system to compute the unsettled amount.
* Supports partial write-offs of invoice items.
* Multiple targets per write-off are supported, processed in the order provided.
* Write-offs propagate to Data Lake for downstream reporting.
* A full reversal capability is supported via a simple `POST` call.

Accounting Behavior [#accounting-behavior]

Granular write-offs follow the same accounting rules as traditional full invoice write-offs. Each target is processed independently and credited accordingly.

API Usage [#api-usage]

Create a write-off by specifying one or more `invoice` or `invoiceItem` targets. All targets must belong to the same account and use the same currency.

<ApiEndpoint name="writeOff" title="Create Write-Off" />

<ApiSchema name="WriteOffRequest" />

<ApiSchema name="WriteOffTarget" />

<Callout>
  Invoices can also be directly targeted for write off via their locator, however this approach is limited in that it can target only the remaining balance of the invoice, and in its entirety.
</Callout>

<ApiEndpoint name="writeOffInvoice" title="Write-Off an Invoice" />

Reversal Support [#reversal-support]

Write-offs can be fully reversed using the existing reversal endpoint, unsetting all credits made across all `invoice` and `invoiceItem` targets. Partial reversals are not supported.

<ApiEndpoint name="reverseWriteOff" title="Reverse a Write-Off" />

Limitations [#limitations]

* **Maximum targets:** A request can include up to 100 targets. Requests exceeding this limit will be rejected.

* **Same account constraint:** All targets (`invoice` and `invoiceItems`) must belong to the account specified in the request. Cross-account targeting is not allowed.

* **Same currency:** All targets in a request must have the same currency.

* **No duplicate targets:** Each target must be unique. Duplicate `invoice` or `invoiceItem` entries within the same request will result in an error.

* **Disjoint targets:** `invoiceItems` cannot be targeted individually if they are already indirectly included via their parent invoice in the same request. Each target must be independent.

* **Valid types only:**
  * Only `invoice` and `invoiceItem` container types are supported.
  * Other types (e.g., account) are not valid targets.

* **Target must exist:** All provided target locators must correspond to existing invoices or invoice items; otherwise, the request will fail.

* **Amount must be valid:** The amount specified per target must be positive and non-zero. The amount must not exceed the target's remaining unsettled amount.

* **Settled items cannot be written off:** Targets that are already fully settled are not eligible for write-off.

* **Targets are required:** A write-off request must include at least one valid target.

See Also [#see-also]

* [Write-Offs API](/api/billing/write-offs)


## API Reference

POST /billing/{tenantLocator}/writeOffs — writeOff
Tags: write-off-controller
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (WriteOffRequest):
Responses:
  200 WriteOffResponse — OK

PATCH /billing/{tenantLocator}/invoices/{locator}/writeOff — writeOffInvoice
Tags: invoices-controller
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

PATCH /billing/{tenantLocator}/writeOffs/{locator}/reverse — reverseWriteOff
Tags: write-off-controller
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

WriteOffRequest
Properties:
  accountLocator (ulid, required)
  targets (WriteOffTarget[], required)

WriteOffTarget
Properties:
  containerLocator (ulid, required)
  containerType (Enum invoice | account | subpayment | invoiceItem, required)
  amount (number)