# Invoices

CRM invoice management: create, retrieve, update, delete, filter. An invoice is a request for payment: it carries the payer, the seller company and the product rows, and its stage shows where the invoice stands in the issue-and-payment cycle.

Bitrix24 API: `crm.item.*`, `entityTypeId` equals `31`
Scope: `crm`

## Operations

- [Create invoice](./invoices/create.md) — `POST /v1/invoices`
- [List invoices](./invoices/list.md) — `GET /v1/invoices`
- [Get invoice](./invoices/get.md) — `GET /v1/invoices/:id`
- [Update invoice](./invoices/update.md) — `PATCH /v1/invoices/:id`
- [Delete invoice](./invoices/delete.md) — `DELETE /v1/invoices/:id`
- [Search invoices](./invoices/search.md) — `POST /v1/invoices/search`
- [Invoice fields](./invoices/fields.md) — `GET /v1/invoices/fields`
- [Aggregate invoices](./invoices/aggregate.md) — `POST /v1/invoices/aggregate`
- [Get products](./invoices/products-get.md) — `GET /v1/invoices/:id/products`
- [Set products](./invoices/products-set.md) — `PUT /v1/invoices/:id/products`
- [Add product](./invoices/products-add.md) — `POST /v1/invoices/:id/products`
- [Delete product](./invoices/products-delete.md) — `DELETE /v1/invoices/:id/products/:rowId`
- [Get product](./invoices/products-get-single.md) — `GET /v1/invoices/:id/products/:rowId`
- [Update product](./invoices/products-update.md) — `PATCH /v1/invoices/:id/products/:rowId`
- [Product fields](./invoices/products-fields.md) — `GET /v1/invoices/:id/products/fields`
- [Import records](../import.md) — `POST /v1/invoices/import`

## Key fields

| Field | Type | Description |
|------|-----|---------|
| `id` | number | Invoice identifier, read-only |
| `title` | string | Invoice title. If omitted, `Invoice #<id>` is used |
| `stageId` | string | Stage, formatted `DT31_{categoryId}:{stage}`. List: [`GET /v1/statuses?filter[entityId]=SMART_INVOICE_STAGE_{categoryId}`](./statuses/list.md) |
| `categoryId` | number | Invoice pipeline identifier. The set of pipelines depends on the Bitrix24 account — read it with `GET /v1/invoices?limit=1&select=categoryId` |
| `opportunity` | number | Invoice amount |
| `currencyId` | string | Currency. List: [`GET /v1/currencies`](/docs/entities/currencies) |
| `contactId` | number | Payer contact. Lookup: [`GET /v1/contacts`](/docs/entities/contacts) |
| `companyId` | number | Payer company. Lookup: [`GET /v1/companies`](/docs/entities/companies) |
| `mycompanyId` | number | Own seller company issuing the invoice. Lookup: [`GET /v1/companies`](/docs/entities/companies) |
| `assignedById` | number | Assignee. List: [`GET /v1/users`](/docs/entities/users) |
| `accountNumber` | string | Printable invoice number |

Full list of fields — [`GET /v1/invoices/fields`](./invoices/fields.md).

## What to know before you start

1. **No field is required on create.** An empty body is rejected with `400 EMPTY_CREATE_BODY`, but any single field is enough: the rest is filled with the Bitrix24 account defaults, the title becomes `Invoice #<id>` and the stage becomes the first stage of the pipeline.
2. **Stages are specific to the Bitrix24 account.** A stage identifier carries its pipeline — `DT31_5:N` reads as "pipeline 5, stage N". Stages of one pipeline do not fit another, and the set differs between Bitrix24 accounts, so you cannot copy a value from an example: request the list of stages first.
3. **Read-only fields are rejected; unknown scalar names are ignored.** Writing `id`, `createdBy`, `createdTime` or any other field marked read-only returns `400 READONLY_FIELD` on create and on update alike. An unknown scalar name is accepted but never stored. An object under `fields` is rejected with `400 NESTED_FIELDS_ENVELOPE`; pass invoice fields at the JSON root.
4. **Product rows are a separate resource.** They do not arrive in the invoice body and are not written with it: rows have their own `products-*` operations, and `PUT /v1/invoices/:id/products` replaces the whole list.
5. **Custom fields arrive alongside the standard ones.** The `ufCrm_*` fields appear in list responses, in the `GET /v1/invoices/fields` schema, and are accepted on write.

## Typical scenario

1. Find the payer: [`GET /v1/contacts`](./contacts/list.md) or [`GET /v1/companies`](./companies/list.md).
2. Take the pipeline and its stages: [`GET /v1/invoices?limit=1&select=categoryId`](./invoices/list.md), then [`GET /v1/statuses?filter[entityId]=SMART_INVOICE_STAGE_5`](./statuses/list.md).
3. Create the invoice: [`POST /v1/invoices`](./invoices/create.md).
4. Fill it with product rows: [`PUT /v1/invoices/:id/products`](./invoices/products-set.md).
5. Move it through stages and watch the amounts: [`PATCH /v1/invoices/:id`](./invoices/update.md), [`POST /v1/invoices/aggregate`](./invoices/aggregate.md).

## Limits

| Limit | Value |
|-------|----------|
| Maximum records per request | 5000 (`limit <= 5000`) |
| Auto-pagination | enabled when `limit > 50` |
| `offset` on large selections | `limit <= 500` recommended when `offset >= 2500` |
| Search window splitting | enabled on a date-range filter wider than 14 days |
| Import | up to 100 records per [`POST /v1/invoices/import`](../import.md) call |
| Batch requests | up to 50 operations in [`POST /v1/batch`](/docs/batch) |
| Rate limit | shared across the Vibecode API — see [Limits and optimization](/docs/optimization) |

## See also

- [Entity API](/docs/entity-api)
- [Filtering syntax](/docs/filtering)
- [Batch](/docs/batch)
- [Contacts](./contacts.md)
- [Companies](./companies.md)
- [Quotes](./quotes.md)
