product.product: fields, relations and API
The product.product model ("Product Variant") is a persistent model declared by the Products & Pricelists module, then extended by 34 other modules. It exposes 139 fields, 110 of them declared directly on the model; 107 fields from other models point to it. Below you will find every field with its technical name, type, label and relations, followed by an Odoo 20 JSON-2 API call.
Model identity
- Technical name
product.product- Label
- Product Variant
- Type
- Persistent (models.Model)
- SQL table
product_product- Origin module
- Products & Pricelists (
product) - Extended by
- account, sale, sale_project, event_product, event_booth_sale, hr_expense, point_of_sale, loyalty, stock, mrp, stock_account, mrp_account, stock_delivery, purchase, purchase_stock, product_expiry, repair, mrp_subcontracting, mrp_subcontracting_account, stock_dropshipping, mrp_subcontracting_purchase, pos_hr, pos_loyalty, pos_self_order, product_margin, purchase_requisition, sale_edi_ubl, sale_gelato, sale_timesheet, website_sale, website_sale_slides, website_event_sale, website_sale_stock, website_sale_loyalty
- Default order (_order)
default_code, name, id- Inherits from (mixins)
- mail.threadmail.activity.mixinpos.load.mixinwebsite.structured_data.mixinwebsite.trackable.mixin
- Delegation (_inherits)
- product.template: fields of this model are also available, through
product_tmpl_id
Model fields
110 own fields, 24 inherited from mixins and 5 automatic ORM fields. Click a name to get a direct link to that field.
139 of 139 fields shown
| Technical name | Label | Type | Details |
|---|---|---|---|
| active | Active If unchecked, it will allow you to hide the product without removing it. | boolean | |
| additional_product_tag_ids | Variant Tags | many2many | |
| all_product_tag_ids | All Product Tag | many2many | computed |
| avg_cost | Average Cost | monetary | computed added by WMS Accounting ( |
| barcode | Barcode International Article Number used for product identification. | char | |
| base_unit_count | Reference Unit Display base unit price. Set to 0 to hide it for this product. | float | required |
| base_unit_id | Custom Unit of Measure Define a custom unit to display in the price per unit of measure field. | many2one | |
| base_unit_name | Base Unit Name Displays the custom unit for the products if defined or the selected unit of measure otherwise. | char | computed |
| base_unit_price | Price Per Unit | monetary | computed |
| bom_count | # Bill of Material | integer | computed added by Manufacturing ( |
| bom_line_ids | BoM Components | one2many | inverse: added by Manufacturing ( |
| can_image_1024_be_zoomed | Can Image 1024 be zoomed | boolean | computed |
| can_image_variant_1024_be_zoomed | Can Variant Image 1024 be zoomed | boolean | computed, stored |
| catalog_is_in_order | Catalog Is In Order | boolean | |
| catalog_is_in_selected_section | Catalog Is In Selected Section | boolean | added by Invoicing ( |
| channel_ids | Courses | one2many | inverse: added by Sell Courses ( |
| code | Reference | char | computed |
| combination_indices | Combination Indices | char | computed, stored |
| company_currency_id | Valuation Currency Technical field to correctly show the currently selected company's currency that corresponds to the totaled value of the product's valuation layers | many2one | computed added by WMS Accounting ( |
| country_of_origin | Origin of Goods Rules of origin determine where goods originate, i.e. not where they have been shipped from, but where they have been produced or manufactured. As such, the ‘origin’ is the 'economic nationality' of goods traded in commerce. | many2one | added by Delivery - Stock ( |
| date_from | Margin Date From | date | computed added by Margins by Products ( |
| date_to | Margin Date To | date | computed added by Margins by Products ( |
| default_code | Internal Reference | char | |
| event_ticket_ids | Event Tickets | one2many | inverse: added by Events Product ( |
| expected_margin | Expected Margin Expected Sale - Normal Cost | float | computed added by Margins by Products ( |
| expected_margin_rate | Expected Margin (%) Expected margin * 100 / Expected Sale | float | computed added by Margins by Products ( |
| expense_job_position_limit_ids | Job Position Limits | one2many | inverse: added by Expenses ( |
| extra_uom_ids | Extra Packagings Variant-specific additional packagings for this product which can be used for sales | many2many→ uom.uom | |
| free_qty | Free To Use Quantity Available quantity (computed as Quantity On Hand - reserved quantity - quantity to remove) In a context with a single Stock Location, this includes goods stored in this location, or any of its children. In a context with a single Warehouse, this includes goods stored in the Stock Location of this Warehouse, or any of its children. Otherwise, this includes goods stored in any Stock Location with 'internal' type. | float | computed |
| gelato_product_uid | Gelato Product Uid | char | read-only added by Gelato ( |
| gelato_variant_image_ids | Gelato Variant Print Images To ensure a good printing result, upload a PNG of the entire printing area with your graphics correctly placed on it. | one2many | read-only inverse: added by Gelato ( |
| hs_code | HS Code Standardized code for international shipping and goods declaration. | char | added by Delivery - Stock ( |
| image_1024 | Image 1024 | image | computed |
| image_128 | Image 128 | image | computed |
| image_1920 | Image | image | computed |
| image_256 | Image 256 | image | computed |
| image_512 | Image 512 | image | computed |
| image_variant_1024 | Variant Image 1024 | image | related: |
| image_variant_128 | Variant Image 128 | image | related: |
| image_variant_1920 | Variant Image | image | |
| image_variant_256 | Variant Image 256 | image | related: |
| image_variant_512 | Variant Image 512 | image | related: |
| import_attribute_values | Product Values | char | computed |
| incoming_qty | Incoming Quantity of planned incoming products. In a context with a single Stock Location, this includes goods arriving to this Location, or any of its children. In a context with a single Warehouse, this includes goods arriving to the Stock Location of this Warehouse, or any of its children. Otherwise, this includes goods arriving to any Stock Location with 'internal' type. | float | computed |
| invoice_state | Invoice State | selection | read-onlycomputed Values: added by Margins by Products ( |
| is_favorite | Is Favorite | boolean | related: |
| is_kits | Is Kits | boolean | computed added by Manufacturing ( |
| is_product_variant | Is Product Variant | boolean | computed |
| lot_properties_definition | Lot Properties | properties_definition | added by Inventory ( |
| lst_price | Sales Price The sale price can be set manually or computed from the product template. Click on the 'Configure Variants' button to set the extra attribute prices. | float | computed, stored |
| monthly_demand | Monthly Demand | float | computed added by Purchase Stock ( |
| mrp_product_qty | Manufactured | float | computed added by Manufacturing ( |
| nbr_moves_in | Nbr Moves In Number of incoming stock moves in the past 12 months | integer | computed added by Inventory ( |
| nbr_moves_out | Nbr Moves Out Number of outgoing stock moves in the past 12 months | integer | computed added by Inventory ( |
| nbr_reordering_rules | Reordering Rules | integer | computed added by Inventory ( |
| normal_cost | Normal Cost Sum of Multiplication of Cost price and quantity of Vendor Bills | float | computed added by Margins by Products ( |
| orderpoint_ids | Minimum Stock Rules | one2many | inverse: added by Inventory ( |
| outgoing_qty | Outgoing Quantity of planned outgoing products. In a context with a single Stock Location, this includes goods leaving this Location, or any of its children. In a context with a single Warehouse, this includes goods leaving the Stock Location of this Warehouse, or any of its children. Otherwise, this includes goods leaving any Stock Location with 'internal' type. | float | computed |
| partner_ref | Customer Ref | char | computed |
| previously_bought_by_customer | Previously Bought By Customer | boolean | added by Sales ( |
| price_extra | Variant Price Extra This is the sum of the extra price of all attributes | float | computed |
| pricelist_rule_ids | Pricelist Rules | one2many | computed inverse: |
| product_document_count | Documents Count | integer | computed |
| product_document_ids | Documents | one2many | inverse: |
| product_template_attribute_value_ids | Attribute Values | many2many | |
| product_template_image_ids | Product Template Image | one2many | related: added by eCommerce ( |
| product_template_variant_value_ids | Attributes | many2many | |
| product_tmpl_id | Product Template | many2one | required |
| product_uom_ids | Unit Barcode | one2many | inverse: |
| purchase_avg_price | Avg. Purchase Unit Price Avg. Price in Vendor Bills | float | computed added by Margins by Products ( |
| purchase_gap | Purchase Gap Normal Cost - Total Cost | float | computed added by Margins by Products ( |
| purchase_num_invoiced | # Invoiced in Purchase Sum of Quantity in Vendor Bills | float | computed added by Margins by Products ( |
| purchase_order_line_ids | PO Lines | one2many | inverse: added by Purchase Stock ( |
| purchased_product_qty | Purchased | float | computed added by Purchase ( |
| putaway_rule_ids | Putaway Rules | one2many | inverse: added by Inventory ( |
| qty_available | Quantity On Hand Current quantity of products. In a context with a single Stock Location, this includes goods stored at this Location, or any of its children. In a context with a single Warehouse, this includes goods stored in the Stock Location of this Warehouse, or any of its children. stored in the Stock Location of the Warehouse of this Shop, or any of its children. Otherwise, this includes goods stored in any Stock Location with 'internal' type. | float | computedcompany-dependent |
| reordering_max_qty | Reordering Max Qty | float | computed added by Inventory ( |
| reordering_min_qty | Reordering Min Qty | float | computed added by Inventory ( |
| sale_avg_price | Avg. Sale Unit Price Avg. Price in Customer Invoices. | float | computed added by Margins by Products ( |
| sale_expected | Expected Sale Sum of Multiplication of Sale Catalog price and quantity of Customer Invoices | float | computed added by Margins by Products ( |
| sale_num_invoiced | # Invoiced in Sale Sum of Quantity in Customer Invoices | float | computed added by Margins by Products ( |
| sales_count | Sold | float | computed added by Sales ( |
| sales_gap | Sales Gap Expected Sale - Turn Over | float | computed added by Margins by Products ( |
| show_forecasted_qty_status_button | Show Forecasted Qty Status Button | boolean | computed added by Inventory ( |
| show_on_hand_qty_status_button | Show On Hand Qty Status Button | boolean | computed added by Inventory ( |
| show_qty_update_button | Show Qty Update Button | boolean | computed added by Inventory ( |
| sold_by_vendor_id | Vendor | many2one | added by Purchase ( |
| standard_price | Cost Value of the product (automatically computed in AVCO). Used to value the product when the purchase cost is not known (e.g. inventory adjustment). Used to compute margins on sale orders. | float | company-dependent |
| stock_move_ids | Stock Move | one2many | inverse: added by Inventory ( |
| stock_quant_ids | Stock Quant | one2many | inverse: added by Inventory ( |
| storage_category_capacity_ids | Storage Category Capacity | one2many | inverse: added by Inventory ( |
| suggest_estimated_price | Suggest Estimated Price | float | computed added by Purchase Stock ( |
| suggested_qty | Suggested Qty | integer | computed added by Purchase Stock ( |
| tax_string | Tax String | char | computed added by Invoicing ( |
| total_cost | Total Cost Sum of Multiplication of Invoice price and quantity of Vendor Bills | float | computed added by Margins by Products ( |
| total_margin | Total Margin Turnover - Total cost | float | computed added by Margins by Products ( |
| total_margin_rate | Total Margin Rate(%) Total margin * 100 / Turnover | float | computed added by Margins by Products ( |
| total_value | Total Value | monetary | computed added by WMS Accounting ( |
| turnover | Turnover Sum of Multiplication of Invoice price and quantity of Customer Invoices | float | computed added by Margins by Products ( |
| used_in_bom_count | # BoM Where Used | integer | computed added by Manufacturing ( |
| valid_ean | Barcode is valid EAN | boolean | computed added by Inventory ( |
| variant_bom_ids | BOM Product Variants | one2many→ mrp.bom | inverse: added by Manufacturing ( |
| variant_image_ids | Variant Extra Images | many2many | computed, stored added by eCommerce ( |
| variant_ribbon_id | Variant Ribbon | many2one | added by eCommerce ( |
| virtual_available | Forecasted Quantity Forecast quantity (computed as Quantity On Hand - Outgoing + Incoming - Quantity to Remove) In a context with a single Stock Location, this includes goods stored in this location, or any of its children. In a context with a single Warehouse, this includes goods stored in the Stock Location of this Warehouse, or any of its children. Otherwise, this includes goods stored in any Stock Location with 'internal' type. | float | computed |
| volume | Volume | float | |
| website_id | Website | many2one | related: added by eCommerce ( |
| website_url | Website URL The full URL to access the document through the website. | char | computed added by eCommerce ( |
| weight | Weight | float | |
| write_date | Write Date | datetime | computed, stored |
| activity_calendar_event_id | Next Activity Calendar Event | many2one | computed inherited from mail.activity.mixin |
| activity_date_deadline | Next Activity Deadline | date | read-onlycomputed inherited from mail.activity.mixin |
| activity_exception_decoration | Activity Exception Decoration Type of the exception activity on record. | selection | computed Values: inherited from mail.activity.mixin |
| activity_exception_icon | Icon Icon to indicate an exception activity. | char | computed inherited from mail.activity.mixin |
| activity_ids | Activities | one2many | inverse: inherited from mail.activity.mixin |
| activity_plans_ids | Activity Plans | many2many | computed inherited from mail.activity.mixin |
| activity_state | Activity State Status based on activities Overdue: Due date is already passed Today: Activity date is today Planned: Future activities. | selection | computed Values: inherited from mail.activity.mixin |
| activity_summary | Next Activity Summary | char | related: inherited from mail.activity.mixin |
| activity_type_icon | Activity Type Icon | char | related: inherited from mail.activity.mixin |
| activity_type_id | Next Activity Type | many2one | related: inherited from mail.activity.mixin |
| activity_user_id | Responsible User | many2one | read-onlycomputed inherited from mail.activity.mixin |
| has_message | Has Message | boolean | computed inherited from mail.thread |
| message_attachment_count | Attachment Count | integer | computed inherited from mail.thread |
| message_follower_ids | Followers | one2many | inverse: inherited from mail.thread |
| message_has_error | Message Delivery error If checked, some messages have a delivery error. | boolean | computed inherited from mail.thread |
| message_has_error_counter | Number of errors Number of messages with delivery error | integer | computed inherited from mail.thread |
| message_has_sms_error | SMS Delivery error If checked, some messages have a delivery error. | boolean | computed inherited from mail.thread |
| message_ids | Messages | one2many | inverse: inherited from mail.thread |
| message_is_follower | Is Follower | boolean | computed inherited from mail.thread |
| message_needaction | Action Needed If checked, new messages require your attention. | boolean | computed inherited from mail.thread |
| message_needaction_counter | Number of Actions Number of messages requiring action | integer | computed inherited from mail.thread |
| message_partner_ids | Followers (Partners) | many2many | computed inherited from mail.thread |
| my_activity_date_deadline | My Activity Deadline | date | read-onlycomputed inherited from mail.activity.mixin |
| rating_ids | Ratings | one2many | inverse: inherited from mail.thread |
| create_date | Created on | datetime | read-onlyautomatic |
| create_uid | Created by | many2one | read-onlyautomatic |
| display_name | Display Name | char | read-onlycomputedautomatic |
| id | ID | integer | read-onlyautomatic |
| write_uid | Last Updated by | many2one | read-onlyautomatic |
Relations
Models linked from this model
- event.event.ticket: event_ticket_ids
- hr.expense.product.job.position.limit: expense_job_position_limit_ids
- mrp.bom: variant_bom_ids
- mrp.bom.line: bom_line_ids
- product.base.unit: base_unit_id
- product.document: gelato_variant_image_ids, product_document_ids
- product.image: product_template_image_ids, variant_image_ids
- product.pricelist.item: pricelist_rule_ids
- product.ribbon: variant_ribbon_id
- product.tag: additional_product_tag_ids, all_product_tag_ids
- product.template: product_tmpl_id
- product.template.attribute.value: product_template_attribute_value_ids, product_template_variant_value_ids
- product.uom: product_uom_ids
- purchase.order.line: purchase_order_line_ids
- res.country: country_of_origin
- res.currency: company_currency_id
- res.partner: sold_by_vendor_id
- slide.channel: channel_ids
- stock.move: stock_move_ids
- stock.putaway.rule: putaway_rule_ids
- stock.quant: stock_quant_ids
- stock.storage.category.capacity: storage_category_capacity_ids
- stock.warehouse.orderpoint: orderpoint_ids
- uom.uom: extra_uom_ids
Fields of other models pointing here
- account.analytic.distribution.model: product_id
- account.analytic.line: product_id
- account.invoice.report: product_id
- account.move.line: product_id
- customer.product.reference: product_id
- delivery.carrier: product_id
- delivery.note.wizard.line: product_id
- event.booth.category: product_id
- event.booth.configurator: product_id
- event.event.configurator: additional_product_ids, product_id
- event.sale.report: product_id
- event.type.booth: product_id
- event.type.ticket: additional_product_ids, product_id
- hr.expense: product_id
- hr.expense.product.job.position.limit: product_id
- hr.expense.split: product_id
- loyalty.program: payment_program_discount_product_id, trigger_product_ids
- loyalty.reward: all_discount_product_ids, discount_line_product_id, discount_product_ids, reward_product_id, reward_product_ids
- loyalty.rule: product_ids, valid_product_ids
- mrp.bom: product_id
- mrp.bom.byproduct: product_id
- mrp.bom.line: product_id
- mrp.consumption.warning.line: product_id
- mrp.production: bom_product_ids, product_id
- mrp.production.split: product_id
- mrp.unbuild: product_id
- mrp.workcenter.capacity: product_id
- mrp.workorder: product_id
- pos.config: default_product_id, discount_product_id, down_payment_product_id, tip_product_id
- pos.order.line: product_id
- pos.pack.operation.lot: product_id
- pos.prep.line: product_id
- pos.preset: delivery_product_id, service_fee_product_id
- product.catalog.line.mixin: product_id
- product.combo.item: product_id
- product.label.layout: product_ids
- product.pricelist.item: product_id
- product.replenish: product_id
- product.stock.notification: product_id
- product.supplierinfo: product_id
- and 45 more
Reading this model through the API
Odoo 20 JSON-2 API call reading the first five records with real fields of the model. Replace the instance, database and API key with your own.
curl -X POST "https://your-instance.odoo.com/json/2/product.product/search_read" \
-H "Authorization: bearer $ODOO_API_KEY" \
-H "X-Odoo-Database: your-db" \
-H "Content-Type: application/json" \
-d '{"domain":[],"fields":["base_unit_count","product_tmpl_id","base_unit_id","country_of_origin","sold_by_vendor_id"],"limit":5}'import requests
BASE_URL = "https://your-instance.odoo.com/json/2"
headers = {"Authorization": f"bearer {API_KEY}", "X-Odoo-Database": "your-db"}
res = requests.post(
f"{BASE_URL}/product.product/search_read",
headers=headers,
json={"domain": [], "fields": ["base_unit_count","product_tmpl_id","base_unit_id","country_of_origin","sold_by_vendor_id"], "limit": 5},
)
res.raise_for_status()
print(res.json())- External API access requires Odoo's Custom plan.
- XML-RPC and JSON-RPC will be removed in Odoo 22 (fall 2028): use JSON-2.
- The access rights and record rules of the key's user apply.
Cite this tool
Writing a tutorial, internal documentation or a forum answer? Copy this link to send your readers to the up-to-date reference.
<a href="https://aidoo.ai/en/outils/explorateur-modeles-odoo/product-product">product.product (Odoo 20.0)</a>Sources
Data verified on September 25, 2026 · Odoo 20.0 Community
Have an Odoo project, or want to put your ERP to work with AI? Let's talk
Implementation, custom module development, connecting Claude or ChatGPT to your data: tell us about your context and we will reply within 24 business hours.