For AI agents: markdown of this page — /docs-content-en/entities/invoices/products-fields.md documentation index — /llms.txt

Invoice product fields

GET /v1/invoices/:id/products/fields

Returns descriptions of the fields on invoice product rows: names, types, and whether each field is readable and writable.

The discount amount is called discount — matching the data and the write contract. The previous name discountSum remains a deprecated alias: it is still returned by this endpoint and still accepted on write, so code written against the old field list keeps working. Product rows themselves carry only discount — migrate to it.

Parameters

Parameter Type Required Description
Parameterid (path) Typenumber Requiredyes DescriptionInvoice ID

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/invoices/741/products/fields" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/invoices/741/products/fields" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/invoices/741/products/fields', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data } = await res.json()
console.log('Fields:', Object.keys(data).length)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/invoices/741/products/fields', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { success, data } = await res.json()

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata Typeobject DescriptionProduct row field dictionary. The key is the field name, and the value is its definition
Fielddata.<field>.type Typestring DescriptionValue type: integer, double, string, char
Fielddata.<field>.isReadOnly Typeboolean DescriptionRead-only: the field cannot be written
Fielddata.<field>.isRequired Typeboolean DescriptionRequired flag. false on every product-row field: a write accepts a row that carries at least one writable field
Fielddata.<field>.isImmutable Typeboolean Descriptiontrue on ownerId and ownerType: the row owner is set by the request path. Absent on priceAccount and xmlId
Fielddata.<field>.isMultiple Typeboolean Descriptionfalse on product row fields. Absent on priceAccount and xmlId
Fielddata.<field>.isDynamic Typeboolean Descriptionfalse on product row fields. Absent on priceAccount and xmlId
Fielddata.<field>.title Typestring DescriptionField label. Absent on priceAccount and xmlId
Fielddata.<field>.description Typestring DescriptionField note. Present on id and discountSum
Fieldmeta.warnings Typearray DescriptionPresent only when Bitrix24 described some of the fields but not all. An item with the code fields_partial lists the fields whose definitions were derived without labels

Product row fields described by data:

Field Type RO Required Description
Fieldid Typeinteger ROyes Required DescriptionRow ID
FieldproductId Typeinteger RO Required DescriptionProduct ID. Catalog: GET /v1/products. A row without productId is created with productId set to 0 and the name from productName — see Add a product
FieldproductName Typestring RO Required DescriptionProduct name
Fieldprice Typedouble RO Required DescriptionPrice
Fieldquantity Typedouble RO Required DescriptionQuantity
Fielddiscount Typedouble RO Required DescriptionDiscount amount. Applied when discountTypeId is 1
FielddiscountSum Typedouble RO Required DescriptionDeprecated alias of discount — accepted on write, absent from product rows
FielddiscountRate Typedouble RO Required DescriptionDiscount percentage. Applied when discountTypeId is 2
FielddiscountTypeId Typeinteger RO Required DescriptionHow the discount is set: 1 — as an amount in discount, 2 — as a percentage in discountRate. Defaults to 2
FieldtaxRate Typedouble RO Required DescriptionTax (%)
FieldtaxIncluded Typechar RO Required DescriptionTax included in price (Y/N)
FieldpriceExclusive Typedouble ROyes Required DescriptionPrice excluding tax, with discount
FieldpriceNetto Typedouble ROyes Required DescriptionNet price
FieldpriceBrutto Typedouble ROyes Required DescriptionGross price
FieldmeasureCode Typeinteger RO Required DescriptionUnit of measure code
FieldmeasureName Typestring ROyes Required DescriptionUnit of measure
Fieldcustomized Typechar ROyes Required DescriptionModified (Y/N)
Fieldsort Typeinteger RO Required DescriptionSort order
Fieldtype Typeinteger ROyes Required DescriptionProduct type — the same value as the product's type in GET /v1/catalog-products/:id: 1 — simple product, 3 — parent product with variations, 7 — service
FieldstoreId Typeinteger ROyes Required DescriptionWarehouse ID
FieldtaxName Typestring ROyes Required DescriptionTax name. Present only in the dictionary, never in product rows. In a write request body it is rejected with 400 INVALID_PARAMS
FieldownerId Typeinteger ROyes Required DescriptionOwner (invoice) ID
FieldownerType Typestring ROyes Required DescriptionOwner type
FieldpriceAccount Typedouble ROyes Required DescriptionPrice in the reporting currency
FieldxmlId Typestring ROyes Required DescriptionExternal code of the row

Response example

JSON
{
  "success": true,
  "data": {
    "id": { "type": "integer", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "ID", "description": "Row identity. Read-only as an attribute, and NOT a handle for editing: PUT /products does not preserve it — a row whose fields change comes back with a new id even if the previous one was sent. To edit a row and keep its id use PATCH /products/{rowId}." },
    "ownerId": { "type": "integer", "isRequired": false, "isReadOnly": true, "isImmutable": true, "isMultiple": false, "isDynamic": false, "title": "Owner ID" },
    "ownerType": { "type": "string", "isRequired": false, "isReadOnly": true, "isImmutable": true, "isMultiple": false, "isDynamic": false, "title": "Owner type" },
    "productId": { "type": "integer", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Product" },
    "productName": { "type": "string", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Product name" },
    "price": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Price" },
    "priceExclusive": { "type": "double", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Price excluding tax, with discount" },
    "priceNetto": { "type": "double", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "PRICE_NETTO" },
    "priceBrutto": { "type": "double", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "PRICE_BRUTTO" },
    "quantity": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Quantity" },
    "discountTypeId": { "type": "integer", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Discount type" },
    "discountRate": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Discount value" },
    "discount": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Discount amount" },
    "taxRate": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Tax" },
    "taxIncluded": { "type": "char", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Tax included in price" },
    "customized": { "type": "char", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Modified" },
    "measureCode": { "type": "integer", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Unit of measure code" },
    "measureName": { "type": "string", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Unit of measure" },
    "sort": { "type": "integer", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Sort order" },
    "type": { "type": "integer", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "TYPE" },
    "storeId": { "type": "integer", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "STORE_ID" },
    "taxName": { "type": "string", "isRequired": false, "isReadOnly": true, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "TAX_NAME" },
    "priceAccount": { "type": "double", "isReadOnly": true, "isRequired": false },
    "xmlId": { "type": "string", "isReadOnly": true, "isRequired": false },
    "discountSum": { "type": "double", "isRequired": false, "isReadOnly": false, "isImmutable": false, "isMultiple": false, "isDynamic": false, "title": "Discount amount", "description": "Deprecated alias of `discount`; kept so clients written against the previous field list keep working. Accepted on write, never present in row data — migrate to `discount`." }
  }
}

About id. An id supplied in PUT /v1/invoices/:id/products items does not guarantee the row's previous identifier: an unchanged row gets the same id even without this field, while a changed row gets a new one. For targeted editing, use PATCH /v1/invoices/:id/products/:rowId.

The schema is the same for every invoice. The response does not depend on the id in the URL: passing the ID of a nonexistent invoice returns the same schema and a 200 response rather than an error. This call cannot be used to check that an invoice exists — GET /v1/invoices/:id is there for that.

Error response example

403 — the key lacks the required scope:

JSON
{
  "success": false,
  "error": {
    "code": "SCOPE_DENIED",
    "message": "This endpoint requires 'crm' scope"
  }
}

Errors

HTTP Code Description
HTTP403 CodeSCOPE_DENIED DescriptionAPI key lacks the crm scope
HTTP401 CodeTOKEN_MISSING DescriptionAPI key has no configured tokens
HTTP429 CodeRATE_LIMITED DescriptionRate limit exceeded: 300 requests per minute per portal. All API keys of the portal share one limit. The current limit is returned in the x-ratelimit-limit header. Retry after the delay in the Retry-After header

For the full list of common API errors, see Errors.

See also