[{"data":1,"prerenderedAt":19},["ShallowReactive",2],{"docs-entities\u002Fcrm-payments":3,"docs-tabs-entities\u002Fcrm-payments":6},{"content":4,"lastmod":5},"# CRM payments\n\nPayments of a CRM item, such as a deal: creating a payment, filling it with products from the item's product rows, setting the \"paid\" mark and removing it.\n\nBitrix24 API: `crm.item.payment.*`\nScope: `crm`\n\n## Operations\n\n- [Create a CRM payment](.\u002Fcrm-payments\u002Fcreate.md) — `POST \u002Fv1\u002Fcrm-payments`\n- [List CRM payments](.\u002Fcrm-payments\u002Flist.md) — `GET \u002Fv1\u002Fcrm-payments`\n- [Get a CRM payment](.\u002Fcrm-payments\u002Fget.md) — `GET \u002Fv1\u002Fcrm-payments\u002F:id`\n- [Update a CRM payment](.\u002Fcrm-payments\u002Fupdate.md) — `PATCH \u002Fv1\u002Fcrm-payments\u002F:id`\n- [Delete a CRM payment](.\u002Fcrm-payments\u002Fdelete.md) — `DELETE \u002Fv1\u002Fcrm-payments\u002F:id`\n- [Set the \"paid\" mark](.\u002Fcrm-payments\u002Fpay.md) — `POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fpay`\n- [Remove the \"paid\" mark](.\u002Fcrm-payments\u002Funpay.md) — `POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`\n- [Available product rows](.\u002Fcrm-payments\u002Favailable-products.md) — `GET \u002Fv1\u002Fcrm-payments\u002Favailable-products`\n- [List payment line items](.\u002Fcrm-payments\u002Fproducts-list.md) — `GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`\n- [Add a line item](.\u002Fcrm-payments\u002Fproducts-add.md) — `POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`\n- [Delete a line item](.\u002Fcrm-payments\u002Fproducts-delete.md) — `DELETE \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`\n- [Change the quantity in a line item](.\u002Fcrm-payments\u002Fproducts-update.md) — `PATCH \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`\n\n## Key fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `id` | number | Payment ID. The same payment has the same ID in the [order payments](.\u002Fpayments.md) section |\n| `accountNumber` | string | Payment number: the linked order number and the payment's sequence number separated by `\u002F`, for example `1035\u002F1` |\n| `paid` | string | Payment mark: `Y` — paid, `N` — not paid |\n| `sum` | number | Payment amount. Made up of the line items and cannot be set directly |\n| `paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `entityTypeId`, `entityId` | number | The CRM item the payment belongs to. For a deal, `entityTypeId` is `2` and `entityId` is the ID from [`GET \u002Fv1\u002Fdeals`](\u002Fdocs\u002Fentities\u002Fdeals\u002Flist) |\n| `rowId` | number | ID of the item's product row when adding a line item. List: [`GET \u002Fv1\u002Fcrm-payments\u002Favailable-products`](.\u002Fcrm-payments\u002Favailable-products.md) |\n| `itemId` | number | Payment line item ID for changing and deleting. List: [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](.\u002Fcrm-payments\u002Fproducts-list.md) |\n\nA payment has few fields, and there is no separate field schema method. The full set is in [`GET \u002Fv1\u002Fcrm-payments\u002F:id`](.\u002Fcrm-payments\u002Fget.md).\n\n## Before you start\n\n1. **A payment always belongs to a CRM item.** Listing payments, creating a payment and fetching available product rows require `entityTypeId` and `entityId`. When a payment is created for a deal, the deal gets a linked order. You do not need to create it separately.\n2. **The amount is made up of line items.** A new payment is created with the amount `0`. A line item is a part of the item's product row in a whole-number quantity, and each product row goes into a payment as a single line item. The quantity added to payments is taken from the row's remainder and returns to it when the line item is deleted or its quantity is reduced.\n3. **The same ID appears in order payments.** A CRM payment is also visible in [`GET \u002Fv1\u002Fpayments\u002F:id`](.\u002Fpayments\u002Fget.md) with the `sale` scope, but in a different format: there `paid` is `true` or `false`, and the order ID is in `orderId`. For payments of an existing order that is not linked to a CRM item, use [order payments](.\u002Fpayments.md).\n4. **The \"paid\" mark does not transfer money.** [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fpay`](.\u002Fcrm-payments\u002Fpay.md) only sets the mark and can trigger automation, an email or an online receipt. A payment marked as paid cannot be deleted. Remove the mark first via [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`](.\u002Fcrm-payments\u002Funpay.md).\n5. **A write is confirmed by the reread payment.** The response to creating and updating a payment, setting and removing the mark, adding a line item and changing its quantity contains the payment read after the write. If it could not be reread, the response carries `meta.readbackUnavailable: true`, and `data` contains only the ID: of the payment or, when adding a line item, of the line item and the payment. The write has already completed. You do not need to repeat the call. Check the result by ID instead.\n\n## Typical scenario\n\n1. Find the deal's product rows that have a remaining quantity: [`GET \u002Fv1\u002Fcrm-payments\u002Favailable-products?entityTypeId=2&entityId=:dealId`](.\u002Fcrm-payments\u002Favailable-products.md).\n2. Create a payment for the deal: [`POST \u002Fv1\u002Fcrm-payments`](.\u002Fcrm-payments\u002Fcreate.md) with `entityTypeId` and `entityId`.\n3. Add line items: [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](.\u002Fcrm-payments\u002Fproducts-add.md) with the row's `rowId` and an integer `quantity`.\n4. Check the amount: [`GET \u002Fv1\u002Fcrm-payments\u002F:id`](.\u002Fcrm-payments\u002Fget.md).\n5. When the money is received, set the mark: [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fpay`](.\u002Fcrm-payments\u002Fpay.md).\n\n## Limits\n\n| Limit | Value |\n|-------|----------|\n| List pagination | none — the item's payments and the payment's line items all arrive in one call |\n| `filter` and `order` in the payment list | payment fields only, exact value match |\n| Quantity in a line item | positive integer. When adding, no more than the product row's remainder. When changing, no more than the line item's current quantity plus the row's remainder |\n| Line items of one product row in a payment | one |\n| Batch calls | not supported: [`POST \u002Fv1\u002Fbatch`](\u002Fdocs\u002Fbatch) returns `UNKNOWN_ENTITY` for `crm-payments`, so call the section's endpoints one at a time |\n| Request rate | shared across the Vibecode API — see [Limits and optimization](\u002Fdocs\u002Foptimization) |\n\n## See also\n\n- [Order payments](.\u002Fpayments.md)\n- [Deals](.\u002Fdeals.md)\n- [Payment systems](.\u002Fpay-systems.md)\n- [Basket items](.\u002Fbasket-items.md)\n- [Entity reference](\u002Fdocs\u002Fentity-api)","2026-10-09",{"crm-payments\u002Fcreate.md":7,"crm-payments\u002Flist.md":8,"crm-payments\u002Fget.md":9,"crm-payments\u002Fupdate.md":10,"crm-payments\u002Fdelete.md":11,"crm-payments\u002Fpay.md":12,"crm-payments\u002Funpay.md":13,"crm-payments\u002Favailable-products.md":14,"crm-payments\u002Fproducts-list.md":15,"crm-payments\u002Fproducts-add.md":16,"crm-payments\u002Fproducts-delete.md":17,"crm-payments\u002Fproducts-update.md":18},"\n## Create a CRM payment\n\n`POST \u002Fv1\u002Fcrm-payments`\n\nCreates an empty payment for a CRM item, such as a deal: no line items, a zero amount and no \"paid\" mark.\n\nProducts are added to the payment in the next step, as [payment line items](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add). Fields are passed flat at the JSON root, without a `fields` wrapper.\n\n## Request fields (body)\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|---------|\n| `entityTypeId` | number | yes | CRM item type. For a deal, `2` |\n| `entityId` | number | yes | CRM item ID. For a deal, the ID from [`GET \u002Fv1\u002Fdeals`](\u002Fdocs\u002Fentities\u002Fdeals\u002Flist) |\n| `paySystemId` | number | no | Payment system ID, a non-negative integer. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist). If omitted or `0`, a payment system is assigned automatically and its ID is returned in the response |\n\nThe amount and the paid mark cannot be set at creation.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"entityTypeId\": 2, \"entityId\": 8761, \"paySystemId\": 1 }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"entityTypeId\": 2, \"entityId\": 8761, \"paySystemId\": 1 }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ entityTypeId: 2, entityId: 8761, paySystemId: 1 }),\n})\n\nconst { data } = await res.json()\nconsole.log('Payment ID:', data.id, 'number:', data.accountNumber)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ entityTypeId: 2, entityId: 8761, paySystemId: 1 }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nThe HTTP status of a successful response is `201`.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data.id` | number | ID of the created payment |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment's sequence number separated by `\u002F`, for example `1029\u002F2` |\n| `data.paid` | string | Paid mark, `N` for a new payment |\n| `data.datePaid` | null | `null` for a new payment |\n| `data.empPaidId` | null | `null` for a new payment |\n| `data.paySystemId` | number | Payment system ID, either the one passed or the one assigned automatically. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount, `0` for a new payment |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n| `meta.readbackUnavailable` | boolean | Returned only with the value `true` when the payment was created but could not be read back. In that case `data` contains only `id`. Do not create it again. Fetch the payment by this `id` instead |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 565,\n    \"accountNumber\": \"1029\u002F2\",\n    \"paid\": \"N\",\n    \"datePaid\": null,\n    \"empPaidId\": null,\n    \"paySystemId\": 1,\n    \"sum\": 0,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Bank transfer (Companies)\"\n  }\n}\n```\n\n## Error response example\n\n400 — `paySystemId` is negative or not an integer:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_PARAMS\",\n    \"message\": \"paySystemId must be a non-negative integer.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `MISSING_REQUIRED_FIELDS` | `entityTypeId` or `entityId` is missing, or the value is not a positive integer |\n| 400 | `READONLY_FIELD` | The body contains a field other than `entityTypeId`, `entityId` and `paySystemId` |\n| 400 | `INVALID_PARAMS` | `paySystemId` is negative or not an integer |\n| 404 | `ENTITY_NOT_FOUND` | No CRM item with this `entityTypeId` and `entityId` exists |\n| 422 | `BITRIX_NO_EFFECT` | The payment was not created, for example because no payment system with this `paySystemId` exists. No new payment appears on the item |\n| 422 | `BITRIX_ERROR` | CRM items of this type have no payments, for example a lead with `entityTypeId` equal to `1`. The message says that payment creation is unavailable for this entity |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is missing |\n\nFull list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## See also\n\n- [Add a line item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add)\n- [Available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products)\n- [List CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist)\n- [Mark a payment as paid](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fpay)\n- [Pay systems](\u002Fdocs\u002Fentities\u002Fpay-systems)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","## List CRM payments\n\n`GET \u002Fv1\u002Fcrm-payments`\n\nReturns all payments of one CRM item, such as a deal, with filtering and sorting by payment fields.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `entityTypeId` (query) | number | yes | CRM item type. For a deal — `2` |\n| `entityId` (query) | number | yes | CRM item ID. For a deal — the ID from [`GET \u002Fv1\u002Fdeals`](\u002Fdocs\u002Fentities\u002Fdeals\u002Flist) |\n| `filter` (query) | object | no | Filter by payment fields from the \"Response fields\" table — exact value match only; keys cannot contain comparison operators.\u003Cbr>[Filtering syntax](\u002Fdocs\u002Ffiltering). Example: `?filter[paid]=Y` |\n| `order` (query) | object | no | Sort by payment fields from the \"Response fields\" table: `asc`, `desc`, `ASC` or `DESC`. Example: `?order[id]=desc` |\n\nThere is no pagination: the response contains all payments of the item in a single call. The method accepts no other query parameters, including `limit` and `offset`.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments?entityTypeId=2&entityId=8761&order[id]=asc\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments?entityTypeId=2&entityId=8761&order[id]=asc\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst params = new URLSearchParams({ entityTypeId: '2', entityId: '8761', 'order[id]': 'asc' })\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments?${params}`, {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data, meta } = await res.json()\nconsole.log(`Payments: ${meta.total}`, data.map(p => `${p.accountNumber} — ${p.paid}`))\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst params = new URLSearchParams({ entityTypeId: '2', entityId: '8761', 'order[id]': 'asc' })\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments?${params}`, {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data, meta } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data` | array | Payments of the item. An empty array if the item has no payments |\n| `data[].id` | number | Payment ID |\n| `data[].accountNumber` | string | Payment number: the linked order number and the payment sequence number separated by `\u002F`, for example `1029\u002F2` |\n| `data[].paid` | string | Paid mark: `Y` — paid, `N` — not paid |\n| `data[].datePaid` | string \\| null | Time of the last \"paid\" mark, ISO 8601 with a time zone offset. `null` if the payment was never marked |\n| `data[].empPaidId` | number \\| null | ID of the employee who last marked the payment. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data[].paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data[].sum` | number | Payment amount. The sum of the payment's items; `0` for a new payment |\n| `data[].currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data[].paySystemName` | string | Payment system name |\n| `meta.total` | number | Number of payments in `data` |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 563,\n      \"accountNumber\": \"1029\u002F1\",\n      \"paid\": \"N\",\n      \"datePaid\": null,\n      \"empPaidId\": null,\n      \"paySystemId\": 19,\n      \"sum\": 3000,\n      \"currency\": \"USD\",\n      \"paySystemName\": \"Card payment\"\n    },\n    {\n      \"id\": 565,\n      \"accountNumber\": \"1029\u002F2\",\n      \"paid\": \"Y\",\n      \"datePaid\": \"2026-10-05T09:29:34+00:00\",\n      \"empPaidId\": 1317,\n      \"paySystemId\": 3,\n      \"sum\": 0,\n      \"currency\": \"USD\",\n      \"paySystemName\": \"Bank transfer (Contacts)\"\n    }\n  ],\n  \"meta\": {\n    \"total\": 2\n  }\n}\n```\n\n## Error response example\n\n400 — filtering or sorting by a field that is not in the response:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"UNKNOWN_FILTER_FIELD\",\n    \"message\": \"Filter and order support only payment response fields.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `MISSING_REQUIRED_FIELDS` | `entityTypeId` or `entityId` is missing, or the value is not a positive integer |\n| 400 | `UNKNOWN_FILTER_FIELD` | `filter` or `order` contains a field that is not in the \"Response fields\" table, a key with a comparison operator, or a sort direction other than `asc`, `desc`, `ASC`, `DESC`; or another query parameter was passed |\n| 404 | `ENTITY_NOT_FOUND` | No CRM item exists with this `entityTypeId` and `entityId` |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request; the reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Removing the mark does not clear the time and author of the last mark.** After the mark is removed, the `datePaid` and `empPaidId` fields keep the values of the last mark. Only `paid` reflects the current state.\n\n## See also\n\n- [Get a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget)\n- [Create a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fcreate)\n- [Available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n- [Filtering syntax](\u002Fdocs\u002Ffiltering)\n","## Get a CRM payment\n\n`GET \u002Fv1\u002Fcrm-payments\u002F:id`\n\nReturns one CRM payment by ID, for example to check the amount after adding items or to find out whether the payment is marked as paid.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F563\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F563\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F563', {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data } = await res.json()\nconsole.log(`Payment ${data.accountNumber}: ${data.sum} ${data.currency}, paid: ${data.paid}`)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F563', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data` | object | Payment object. Key payment fields are on the [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments) page |\n| `data.id` | number | Payment ID |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment sequence number separated by `\u002F`, for example `1029\u002F1` |\n| `data.paid` | string | Paid mark: `Y` — paid, `N` — not paid |\n| `data.datePaid` | string \\| null | Time of the last \"paid\" mark, ISO 8601 with a time zone offset. `null` if the payment was never marked |\n| `data.empPaidId` | number \\| null | ID of the employee who last marked the payment. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data.paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount. Made up of the payment items |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 563,\n    \"accountNumber\": \"1029\u002F1\",\n    \"paid\": \"N\",\n    \"datePaid\": null,\n    \"empPaidId\": null,\n    \"paySystemId\": 19,\n    \"sum\": 0,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Card payment\"\n  }\n}\n```\n\n## Error response example\n\n404 — no payment with this ID:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payment has not been found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Removing the \"paid\" mark does not clear the time and author of the last mark.** After the mark is removed, the `datePaid` and `empPaidId` fields keep the values of the last mark. Only `paid` reflects the current state.\n\n## See also\n\n- [List CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist)\n- [Update a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fupdate)\n- [Set the \"paid\" mark](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fpay)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Update a CRM payment\n\n`PATCH \u002Fv1\u002Fcrm-payments\u002F:id`\n\nChanges a CRM payment's payment system or its \"paid\" mark: sets the mark or clears it.\n\nFields are passed flat at the JSON root, without a `fields` wrapper.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. List of an item's payments: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\n## Request fields (body)\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|---------|\n| `paid` | boolean | no | `true` sets the \"paid\" mark, `false` clears it |\n| `paySystemId` | number | no | ID of an existing payment system. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist). The value `0` is rejected, as is the ID of a nonexistent system |\n\nPass at least one of the two fields. The payment amount is the sum of its [line items](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add) and cannot be set directly.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"paySystemId\": 3 }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"paySystemId\": 3 }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ paySystemId: 3 }),\n})\n\nconst { data } = await res.json()\nconsole.log('Payment system:', data.paySystemName)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ paySystemId: 3 }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nReturns the payment after the change.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data.id` | number | Payment ID |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment's sequence number separated by `\u002F` |\n| `data.paid` | string | Paid mark: `Y` for paid, `N` for not paid |\n| `data.datePaid` | string \\| null | Time of the latest \"paid\" mark, ISO 8601 with a time zone offset. `null` if the payment was never marked |\n| `data.empPaidId` | number \\| null | ID of the employee who last marked the payment. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data.paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n| `meta.readbackUnavailable` | boolean | Returned only with the value `true` when the change was applied but the payment could not be read back. In that case `data` contains only `id`. Do not repeat the request; fetch the payment by this `id` |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 565,\n    \"accountNumber\": \"1029\u002F2\",\n    \"paid\": \"N\",\n    \"datePaid\": null,\n    \"empPaidId\": null,\n    \"paySystemId\": 3,\n    \"sum\": 0,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Bank transfer (Contacts)\"\n  }\n}\n```\n\n## Error response example\n\n400 — `paid` is not a boolean:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_PARAMS\",\n    \"message\": \"paid must be a boolean.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `MISSING_REQUIRED_FIELDS` | The body is missing, is not an object, or is an empty object `{}` |\n| 400 | `READONLY_FIELD` | The body contains a field other than `paid` and `paySystemId` |\n| 400 | `INVALID_PARAMS` | `paid` is not a boolean, for example the string `\"Y\"`, or `paySystemId` is negative or not an integer |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` exists |\n| 422 | `BITRIX_ERROR` | No payment system with this `paySystemId` exists, including `0`. Message: `Payment system has not been found` |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request; the reason is in `error.message` |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm the change |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is missing |\n\nFull list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**`paid` has different types in the request and the response.** In the request body `paid` is a boolean, `true` or `false`; in the response it is the string `Y` or `N`.\n\n**`paid` behaves like the pay and unpay endpoints.** `paid: true` sets the mark, like [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fpay`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fpay), and `paid: false` clears it, like [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay). Repeating `paid: true` on a payment that is already marked paid does not change `datePaid`. The mark does not transfer money, but it can trigger automation rules, an email or an online receipt.\n\n## See also\n\n- [Get a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget)\n- [Mark a payment as paid](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fpay)\n- [Clear the paid mark](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay)\n- [Pay systems](\u002Fdocs\u002Fentities\u002Fpay-systems)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Delete a CRM payment\n\n`DELETE \u002Fv1\u002Fcrm-payments\u002F:id`\n\nDeletes a CRM payment that is not marked as paid, together with its line items; the product quantities from those items become available for payments again. A deleted payment cannot be restored through the API; create a new one if needed.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. List of an item's payments: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F567\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F567\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F567', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nif (res.status === 204) {\n  console.log('Payment deleted')\n}\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F567', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nif (res.status === 204) {\n  console.log('Payment deleted')\n}\n```\n\n## Response\n\nOn successful deletion the API returns HTTP status `204 No Content` with an empty body; check the status code to confirm success.\n\n## Response example\n\n```http\nHTTP\u002F1.1 204 No Content\n```\n\n## Error response example\n\n404 — no payment with this ID exists, including one that was already deleted:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payment has not been found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` exists, including one that was already deleted |\n| 422 | `BITRIX_ERROR` | The payment is marked as paid; `error.b24Code` equals `SALE_PAYMENT_DELETE_EXIST_PAID`. Clear the mark first with [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay) |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request; the reason is in `error.message` |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm the deletion |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is missing |\n\nFull list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**After deletion the product quantities are available for payments again.** The quantity that was in the deleted payment's line items shows up again in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) and can go into a new payment.\n\n## See also\n\n- [Clear the paid mark](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay)\n- [List CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist)\n- [Create a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fcreate)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","## Mark a CRM payment as paid\n\n`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fpay`\n\nMarks a CRM payment as paid and records when the mark was set and which employee set it. The mark does not transfer money, but it can trigger automation rules, an email or an online receipt.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of an item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\nSend no request body or send `{}`.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Fpay\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Fpay\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Fpay', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data } = await res.json()\nconsole.log(`Payment ${data.accountNumber} marked as paid: ${data.datePaid}`)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Fpay', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nReturns the payment after the mark is set.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data.id` | number | Payment ID |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment sequence number, separated by `\u002F` |\n| `data.paid` | string | `Y` — the payment is marked as paid |\n| `data.datePaid` | string | Time the payment was last marked as paid, ISO 8601 with a time zone offset |\n| `data.empPaidId` | number | ID of the employee who set the mark — the key's user. A repeated call for a payment that is already marked does not change the value. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data.paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n| `meta.readbackUnavailable` | boolean | Present only as `true` when the mark is set but the payment could not be read back. In that case `data` contains only `id`. You do not need to repeat the request — get the payment by this `id` |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 565,\n    \"accountNumber\": \"1029\u002F2\",\n    \"paid\": \"Y\",\n    \"datePaid\": \"2026-10-05T09:29:34+00:00\",\n    \"empPaidId\": 1317,\n    \"paySystemId\": 3,\n    \"sum\": 0,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Bank transfer (Contacts)\"\n  }\n}\n```\n\n## Error response example\n\n404 — no payment with this ID:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payment has not been found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` |\n| 400 | `READONLY_FIELD` | The request body is not empty |\n| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application\u002Fjson` header is sent with an empty body. Send `{}` as the body or remove the header |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm the mark |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not sent |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**A repeated mark does not change the payment.** A call for a payment that is already marked as paid returns `200` with the same `datePaid` and `empPaidId`.\n\n**A payment marked as paid cannot be deleted.** Before [deleting](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fdelete) it, remove the mark with [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay).\n\n## See also\n\n- [Remove the paid mark](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Funpay)\n- [Update a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fupdate)\n- [Get a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","## Remove the paid mark from a CRM payment\n\n`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Funpay`\n\nRemoves the paid mark from a CRM payment, for example before deleting it: a payment marked as paid cannot be deleted. Removing the mark, like setting it, can trigger Bitrix24 account automation rules.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of an item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\nSend no request body or send `{}`.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Funpay\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Funpay\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Funpay', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data } = await res.json()\nconsole.log(`Payment ${data.accountNumber}, paid mark: ${data.paid}`)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F565\u002Funpay', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nReturns the payment after the mark is removed.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data` | object | Payment object. Key payment fields are on the [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments) page |\n| `data.id` | number | Payment ID |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment sequence number, separated by `\u002F` |\n| `data.paid` | string | `N` — the mark is removed |\n| `data.datePaid` | string \\| null | Time the payment was last marked as paid, ISO 8601 with a time zone offset. Removing the mark does not clear it |\n| `data.empPaidId` | number \\| null | ID of the employee who last marked the payment as paid. Removing the mark does not clear it. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data.paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n| `meta.readbackUnavailable` | boolean | Present only as `true` when the mark is removed but the payment could not be read back. In that case `data` contains only `id`. You do not need to repeat the request — get the payment by this `id` |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 565,\n    \"accountNumber\": \"1029\u002F2\",\n    \"paid\": \"N\",\n    \"datePaid\": \"2026-10-05T09:29:34+00:00\",\n    \"empPaidId\": 1317,\n    \"paySystemId\": 3,\n    \"sum\": 0,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Bank transfer (Contacts)\"\n  }\n}\n```\n\n## Error response example\n\n404 — no payment with this ID:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payment has not been found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` |\n| 400 | `READONLY_FIELD` | The request body is not empty |\n| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application\u002Fjson` header is sent with an empty body. Send `{}` as the body or remove the header |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm removing the mark |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request; the reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not sent |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Removing the mark again does not change the payment.** Calling it for a payment without the mark returns `200` with the same payment.\n\n## See also\n\n- [Mark as paid](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fpay)\n- [Delete a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fdelete)\n- [Update a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fupdate)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Product rows available for CRM payment\n\n`GET \u002Fv1\u002Fcrm-payments\u002Favailable-products`\n\nReturns the product rows of a CRM entity, such as a deal, with the quantity not yet included in payments.\n\nPass a row ID from this response as `rowId` when [adding an item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add).\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `entityTypeId` (query) | number | yes | CRM entity type. For a deal, `2` |\n| `entityId` (query) | number | yes | CRM entity ID. For a deal, an ID from [`GET \u002Fv1\u002Fdeals`](\u002Fdocs\u002Fentities\u002Fdeals\u002Flist) |\n\nThe generic `filter` parameter is not applied by this endpoint. By default, the API preserves the previous HTTP 200 response and data, adds `Warning: 299 - \"filter is not supported on this endpoint and was ignored\"`, and records unsupported-filter use in the server log.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002Favailable-products?entityTypeId=2&entityId=8761\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002Favailable-products?entityTypeId=2&entityId=8761\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002Favailable-products?entityTypeId=2&entityId=8761', {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data } = await res.json()\nfor (const row of data.productRows) {\n  console.log(`${row.id}: ${row.productName} — ${row.quantity} ${row.measureName} available`)\n}\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002Favailable-products?entityTypeId=2&entityId=8761', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data.productRows` | array | Product rows of the entity |\n| `data.productRows[].id` | number | ID of the entity's product row. Pass it as `rowId` to [`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add) |\n| `data.productRows[].ownerId` | number | CRM entity ID |\n| `data.productRows[].ownerType` | string | CRM entity type as a letter code, `D` for a deal |\n| `data.productRows[].productId` | number | Product ID. Catalog: [`GET \u002Fv1\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fproducts\u002Flist). `0` means the row has no catalog product |\n| `data.productRows[].productName` | string | Product name |\n| `data.productRows[].price` | number | Price |\n| `data.productRows[].priceAccount` | number | Price in the reporting currency |\n| `data.productRows[].priceExclusive` | number | Price excluding tax, with discount |\n| `data.productRows[].priceNetto` | number | Net price |\n| `data.productRows[].priceBrutto` | number | Gross price |\n| `data.productRows[].quantity` | number | Quantity not yet included in the entity's payments |\n| `data.productRows[].discountTypeId` | number | How the discount is set: `1` as an amount, `2` as a percentage |\n| `data.productRows[].discountRate` | number | Discount percentage |\n| `data.productRows[].discountSum` | number | Discount amount |\n| `data.productRows[].taxRate` | number \\| null | Tax rate in percent. `null` means no tax is set |\n| `data.productRows[].taxIncluded` | string | Tax included in the price: `Y` or `N` |\n| `data.productRows[].customized` | string | Row edited manually: `Y` or `N` |\n| `data.productRows[].measureCode` | number | Unit of measure code |\n| `data.productRows[].measureName` | string | Unit of measure |\n| `data.productRows[].sort` | number | Sort order |\n| `data.productRows[].xmlId` | string | External row code |\n| `data.productRows[].type` | number | Product type |\n| `data.productRows[].taxName` | string | Tax name |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"productRows\": [\n      {\n        \"id\": 2355,\n        \"ownerId\": 8761,\n        \"ownerType\": \"D\",\n        \"productId\": 0,\n        \"productName\": \"TEST item for payment\",\n        \"price\": 1500,\n        \"priceAccount\": 1500,\n        \"priceExclusive\": 1500,\n        \"priceNetto\": 1500,\n        \"priceBrutto\": 1500,\n        \"quantity\": 1,\n        \"discountTypeId\": 2,\n        \"discountRate\": 0,\n        \"discountSum\": 0,\n        \"taxRate\": null,\n        \"taxIncluded\": \"N\",\n        \"customized\": \"Y\",\n        \"measureCode\": 796,\n        \"measureName\": \"pcs\",\n        \"sort\": 0,\n        \"xmlId\": \"\",\n        \"type\": 1,\n        \"taxName\": \"No VAT\"\n      }\n    ]\n  }\n}\n```\n\n## Error response example\n\n400: `entityTypeId` holds an unknown CRM entity type:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INVALID_ENTITY_TYPE\",\n    \"message\": \"This CRM entity type has no payable product rows.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 200 | `Warning: 299` | The filter is ignored by default; previous data is preserved and the warning is sent in the `Warning` header. |\n| 400 (strict mode only) | `UNSUPPORTED_FILTER` | The server mode is disabled by default; until it is enabled, the endpoint preserves HTTP 200 and the previous data. |\n| 400 | `MISSING_REQUIRED_FIELDS` | `entityTypeId` or `entityId` is missing, or the value is not a positive integer |\n| 400 | `INVALID_ENTITY_TYPE` | `entityTypeId` is not a CRM entity type, for example `999` |\n| 404 | `ENTITY_NOT_FOUND` | No CRM entity with this `entityTypeId` and `entityId` exists |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM entity or payment in Bitrix24 |\n| 403 | `SCOPE_DENIED` | The API key lacks the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is missing |\n\nFull list of common API errors: [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**The remainder is counted across all payments of the entity.** For a row with quantity `3`, of which `2` are already added to a payment, `quantity` is `1`. After that payment is deleted, the remainder returns to `3`.\n\n## See also\n\n- [Add an item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add)\n- [Create a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fcreate)\n- [Deal product rows](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-get)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## List CRM payment line items\n\n`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`\n\nReturns the line items of a CRM payment: how many units of each product the payment includes. Use it to get a line item `id` before changing the quantity or deleting the line item.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\nThere are no query string parameters: all line items arrive at once, without pagination or filters.\n\nThe generic `filter` parameter is not applied by this endpoint. By default, the API preserves the previous HTTP 200 response and data, adds `Warning: 299 - \"filter is not supported on this endpoint and was ignored\"`, and records unsupported-filter use in the server log.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts', {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { data, meta } = await res.json()\nconsole.log(`Line items in the payment: ${meta.total}`)\nfor (const item of data) {\n  console.log(`Line item ${item.id}: ${item.quantity} pcs`)\n}\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data, meta } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data` | array | Payment line items. An empty array for a payment without line items |\n| `data[].id` | number | Payment line item ID. Passed as `itemId` to [`PATCH \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update) and [`DELETE \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-delete) |\n| `data[].paymentId` | number | Payment ID |\n| `data[].quantity` | number | Number of product units in the line item |\n| `data[].entityId` | number | ID of the basket item in the linked order. List: [`GET \u002Fv1\u002Fbasket-items`](\u002Fdocs\u002Fentities\u002Fbasket-items\u002Flist) with `filter[orderId]` set to the order ID from the payment's `orderId` field in [`GET \u002Fv1\u002Fpayments\u002F:id`](\u002Fdocs\u002Fentities\u002Fpayments\u002Fget) |\n| `meta.total` | number | Number of line items in the payment |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 445,\n      \"paymentId\": 573,\n      \"quantity\": 2,\n      \"entityId\": 1391\n    }\n  ],\n  \"meta\": {\n    \"total\": 1\n  }\n}\n```\n\n## Error response example\n\n404 — no payment with this ID:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payment has not been found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id` |\n| 200 | `Warning: 299` | The filter is ignored by default; previous data is preserved and the warning is sent in the `Warning` header. |\n| 400 (strict mode only) | `UNSUPPORTED_FILTER` | The server mode is disabled by default; until it is enabled, the endpoint preserves HTTP 200 and the previous data. |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**A line item does not contain the deal product row ID.** `entityId` points to the basket item of the order, not to the deal product row that was passed as `rowId` when [adding the line item](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add). To get the line item's name, price and product, look up the basket item by `entityId`.\n\n## See also\n\n- [Add a line item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add)\n- [Change the quantity in a line item](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update)\n- [Delete a line item from a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-delete)\n- [Get a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget)\n- [Basket items](\u002Fdocs\u002Fentities\u002Fbasket-items)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Add a line item to a CRM payment\n\n`POST \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`\n\nAdds a line item to a CRM payment: the specified quantity taken from a product row of a CRM item, such as a deal. The payment amount is recalculated immediately.\n\nFields are passed flat at the JSON root, without a `fields` wrapper.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n\n## Request fields (body)\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|---------|\n| `rowId` | number | yes | ID of the CRM item's product row. List: [`GET \u002Fv1\u002Fcrm-payments\u002Favailable-products`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products), field `productRows[].id` |\n| `quantity` | number | yes | Quantity, a positive integer. Must not exceed the row's remainder, which is the `productRows[].quantity` field in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"rowId\": 2357, \"quantity\": 2 }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"rowId\": 2357, \"quantity\": 2 }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ rowId: 2357, quantity: 2 }),\n})\n\nconst { data } = await res.json()\nconsole.log('Line item ID:', data.id, 'payment amount:', data.payment.sum)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ rowId: 2357, quantity: 2 }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nA successful response returns HTTP status `201`.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data.id` | number | ID of the created payment line item. Passed as `itemId` to [`PATCH`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update) and [`DELETE \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-delete) |\n| `data.payment` | object | The payment after the line item is added, with the same fields as in [`GET \u002Fv1\u002Fcrm-payments\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget) |\n| `data.payment.id` | number | Payment ID |\n| `data.payment.sum` | number | Payment amount including the new line item |\n| `meta.readbackUnavailable` | boolean | Returned only with the value `true` when the line item was added but the payment could not be read back. In that case `data.payment` contains only `id`. Do not add the line item again. Check the line items via [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list) |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 445,\n    \"payment\": {\n      \"id\": 573,\n      \"accountNumber\": \"1035\u002F1\",\n      \"paid\": \"N\",\n      \"datePaid\": null,\n      \"empPaidId\": null,\n      \"paySystemId\": 19,\n      \"sum\": 3000,\n      \"currency\": \"USD\",\n      \"paySystemName\": \"Card payment\"\n    }\n  }\n}\n```\n\n## Error response example\n\n422 — `quantity` exceeds the product row's remainder:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BITRIX_ERROR\",\n    \"message\": \"Not enough product to add to the payment\",\n    \"b24Code\": \"0\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `MISSING_REQUIRED_FIELDS` | The body is missing and there is no `Content-Type` header, `rowId` or `quantity` is not provided, or the value is not a positive integer, for example `1.5` |\n| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application\u002Fjson` header is sent with an empty body |\n| 400 | `READONLY_FIELD` | The body contains a field other than `rowId` and `quantity`, or the body is not a JSON object, for example `null` or an array |\n| 400 | `INVALID_ID` | `id` is not a positive integer |\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id`, message `Payment has not been found` |\n| 404 | `ENTITY_NOT_FOUND` | The row lookup confirmed that no product row has this `rowId`; message `Product row was not found.` in every portal language |\n| 404 | `ENTITY_NOT_FOUND` | The product row exists, but this payment cannot pay for it; message `Product was not found.` on en\u002Fde\u002Fkz portals, or a localized Russian message on ru portals (shown in the Russian documentation) |\n| 422 | `BITRIX_ERROR` | `quantity` exceeds the row's remainder, message `Not enough product to add to the payment` |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 422 | `BITRIX_NO_EFFECT` | The line item was not created, for example because a row with this `rowId` is already in this payment. The existing line item does not change. To change its quantity, use [`PATCH \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update) |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**The added quantity is taken from the row's remainder.** After 2 units are added from a row of 3 units, the `quantity` of this row in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) becomes `1`.\n\n## See also\n\n- [Available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products)\n- [List payment line items](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list)\n- [Change the quantity in a line item](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update)\n- [Delete a line item from a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-delete)\n- [Create a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fcreate)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Delete a line item from a CRM payment\n\n`DELETE \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`\n\nDeletes a line item from a CRM payment. The payment amount is recalculated immediately. A deleted line item cannot be restored via the API. Add it again if needed.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n| `itemId` (path) | number | yes | Payment line item ID, not the deal product row ID. List: [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list), field `data[].id` |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nif (res.status === 204) {\n  console.log('Line item deleted')\n}\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445', {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nif (res.status === 204) {\n  console.log('Line item deleted')\n}\n```\n\n## Response\n\nOn successful deletion the response is HTTP status `204 No Content` with an empty body. Check success by the status. The new payment amount is returned by [`GET \u002Fv1\u002Fcrm-payments\u002F:id`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fget).\n\n## Response example\n\n```http\nHTTP\u002F1.1 204 No Content\n```\n\n## Error response example\n\n404 — no line item with this `itemId` in this payment, including one already deleted:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payable item has not been found in this payment.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | No line item with this `itemId` in this payment, including one already deleted, message `Payable item has not been found in this payment.` |\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id`, message `Payment has not been found` |\n| 400 | `INVALID_ID` | `id` or `itemId` is not a positive integer |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm the deletion |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**The line item quantity returns to the row's remainder.** After a line item of 3 units is deleted, the row's `quantity` in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) again includes these 3 units, and they can be added to this or another payment.\n\n## See also\n\n- [List payment line items](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list)\n- [Add a line item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add)\n- [Change the quantity in a line item](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-update)\n- [Delete a CRM payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fdelete)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n","\n## Change the quantity in a CRM payment line item\n\n`PATCH \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts\u002F:itemId`\n\nSets a new quantity for a CRM payment line item. The payment amount is recalculated immediately.\n\nThe field is passed flat at the JSON root, without a `fields` wrapper.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET \u002Fv1\u002Fcrm-payments`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Flist) |\n| `itemId` (path) | number | yes | Payment line item ID, not the deal product row ID. List: [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list), field `data[].id` |\n\n## Request fields (body)\n\n| Field | Type | Required | Description |\n|------|-----|:-----:|---------|\n| `quantity` | number | yes | New quantity, a positive integer. No more than the line item's current quantity plus the row's remainder in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"quantity\": 3 }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"quantity\": 3 }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ quantity: 3 }),\n})\n\nconst { data } = await res.json()\nconsole.log(`Payment ${data.accountNumber} amount: ${data.sum} ${data.currency}`)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fcrm-payments\u002F573\u002Fproducts\u002F445', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ quantity: 3 }),\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\nThe response is the payment after the change, not the line item. The updated line item quantity is in [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list).\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | `true` on success |\n| `data` | object | Payment object. Key payment fields are on the [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments) page |\n| `data.id` | number | Payment ID |\n| `data.accountNumber` | string | Payment number: the linked order number and the payment's sequence number separated by `\u002F`, for example `1035\u002F1` |\n| `data.paid` | string | Paid mark: `Y` — paid, `N` — not paid |\n| `data.datePaid` | string \\| null | Time of the last \"paid\" mark, ISO 8601 with a time zone offset. `null` if the payment was never marked |\n| `data.empPaidId` | number \\| null | ID of the employee who last marked the payment as paid. List: [`GET \u002Fv1\u002Fusers`](\u002Fdocs\u002Fentities\u002Fusers\u002Flist) |\n| `data.paySystemId` | number | Payment system ID. List: [`GET \u002Fv1\u002Fpay-systems`](\u002Fdocs\u002Fentities\u002Fpay-systems\u002Flist) |\n| `data.sum` | number | Payment amount including the new quantity |\n| `data.currency` | string | Currency code. List: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies\u002Flist) |\n| `data.paySystemName` | string | Payment system name |\n| `meta.readbackUnavailable` | boolean | Returned only with the value `true` when the quantity was changed but the payment could not be read back. In that case `data` contains only `id`. Do not repeat the change. Check the line items via [`GET \u002Fv1\u002Fcrm-payments\u002F:id\u002Fproducts`](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list) |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 573,\n    \"accountNumber\": \"1035\u002F1\",\n    \"paid\": \"N\",\n    \"datePaid\": null,\n    \"empPaidId\": null,\n    \"paySystemId\": 19,\n    \"sum\": 4500,\n    \"currency\": \"USD\",\n    \"paySystemName\": \"Card payment\"\n  }\n}\n```\n\n## Error response example\n\n404 — no line item with this `itemId` in this payment:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Payable item has not been found in this payment.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `MISSING_REQUIRED_FIELDS` | The body is missing and there is no `Content-Type` header, `quantity` is not provided, or the value is not a positive integer, for example `0` or `1.5` |\n| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application\u002Fjson` header is sent with an empty body |\n| 400 | `READONLY_FIELD` | The body contains a field other than `quantity`, or the body is not a JSON object, for example `null` or an array |\n| 400 | `INVALID_ID` | `id` or `itemId` is not a positive integer |\n| 404 | `ENTITY_NOT_FOUND` | No line item with this `itemId` in this payment, message `Payable item has not been found in this payment.` |\n| 404 | `ENTITY_NOT_FOUND` | No payment with this `id`, message `Payment has not been found` |\n| 422 | `BITRIX_ERROR` | `quantity` exceeds the line item's current quantity plus the row's remainder, message `Not enough product to add to the payment` |\n| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |\n| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not confirm the quantity change |\n| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |\n| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Reducing the quantity returns it to the row's remainder.** After a line item is reduced from 2 to 1 unit, the row's `quantity` in the [available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products) increases by 1.\n\n## See also\n\n- [List payment line items](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-list)\n- [Add a line item to a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-add)\n- [Delete a line item from a payment](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Fproducts-delete)\n- [Available product rows](\u002Fdocs\u002Fentities\u002Fcrm-payments\u002Favailable-products)\n- [CRM payments](\u002Fdocs\u002Fentities\u002Fcrm-payments)\n",1794739356362]