Using the Inventory Adjustment endpoint, you can adjust quantities for reasons such as damage, stock write-off, shrinkage, or expiration. The endpoint automatically handles the underlying accounting to ensure that quantity reflects correctly. This helps you build complex inventory use cases while ensuring that inventory data is consistent and accurate across both QuickBooks Online and your app. Your customers can view and verify inventory quantity and valuation using Inventory Valuation reports. This functionality is available for QuickBooks Online Plus and advanced SKUs in the US.
Note
sparse = true
) is supported. A partial update means only the state sent in the request payload will be updated.There are several use cases for Inventory Adjustment, including:
The Inventory Adjustment APIs also handle errors occurring due to accounting validations. The APIs return specific error codes and messages for different validation scenarios that may occur while adding Inventory Adjustment entries to QuickBooks Online. Some of the accounting validation use cases are given below:
Note
Note: The transaction date cannot be edited.
This section describes the QuickBooks Online Customer Inventory configuration setup required to support inventory adjustment tracking and management.
The chart of accounts and general ledger mappings can be viewed in the QuickBooks Online UI. For example, Inventory Asset account increases when inventory is added and Cost of Goods account increases when inventory is sold or removed.
If Track classes and Track locations are turned on in QuickBooks Online Settings as described above, this information is tracked by Inventory Adjustment.
To close the books, go to Account and Settings > Advanced:
Note
Note: For new customers, when you log in to QuickBooks Online for the first time, QuickBooks Online starts the get to know me (GTKM) flow in the UI, asking about your business and operational needs.
After the books are closed, no inventory adjustments can be made for the company either through the UI or through the API.
To track classes and locations, use the Preferences endpoint. The Preferences object provides the same information as the UI settings:
ClassTrackingPerTxnLine
provides class tracking information, equivalent to Track classes.TrackDepartments
provides location information, equivalent to Track locations.
The following shows an example object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | "Preferences": [ { "AccountingInfoPrefs": { "UseAccountNumbers": false, "TrackDepartments": true, "DepartmentTerminology": "Location", "ClassTrackingPerTxn": false, "ClassTrackingPerTxnLine": true, "FirstMonthOfFiscalYear": "January", "TaxYearMonth": "January", "TaxForm": "1", "CustomerTerminology": "Customers" }, ] |
The following are useful endpoints when working with item adjustments:
This section provides an example of how to adjust inventory. In this example, a user provides the following values to update the inventoryadjustment resource:
Id
: This is the Inventory Adjustment Id, or payload id.Line.Id
: The position of the line items.Line.ItemAdjustmentLineDetail.ItemRef.value
: The item variantIds (This is same value returned for Item.Id
when making a Get Item call after migration.To get the item to adjust, send the following request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | GET /v3/company/{{realmid}}/query?query=select * from Item where Id='1010000001'&minorversion=70 { "QueryResponse": { "Item": [ { "Name": "football", "Active": true, "FullyQualifiedName": "football", "Taxable": true, "UnitPrice": 0, "Type": "Inventory", "IncomeAccountRef": { "value": "79", "name": "Sales of Product Income" }, "PurchaseCost": 100, "ExpenseAccountRef": { "value": "80", "name": "Cost of Goods Sold" }, "AssetAccountRef": { "value": "81", "name": "Inventory Asset" }, "TrackQtyOnHand": true, "QtyOnHand": 200, "ReorderPoint": 0, "InvStartDate": "2024-01-12", "TaxClassificationRef": { "value": "EUC-09020802-V1-00120000", "name": "General taxable retail products - use this if nothing else fits" }, "domain": "QBO", "sparse": false, "Id": "1010000001", "SyncToken": "27", "MetaData": { "CreateTime": "2024-01-12T09:33:47-08:00", "LastUpdatedTime": "2024-05-12T20:13:20-07:00" } } ], "startPosition": 1, "maxResults": 1 }, "time": "2024-05-12T20:52:29.145-07:00" } |
Create the inventory adjustment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | POST /v3/company/<realm_id>/inventoryadjustment?minorversion={{minorversion}} curl --location 'https://quickbooks.api.intuit.com/v3/company/1234567890123456/inventoryadjustment' \ --header 'Content-Type: application/json' \ --header 'Authorization: <auth>' \ --header 'Accept: application/json' --header 'Content-Type: application/json' --data '{"AdjustAccountRef":{"value":"5","name":"Inventory Shrinkage"},"domain":"QBO","sparse":false,"MetaData":{"CreateTime":"2021-07-28T22:16:43-07:00","LastUpdatedTime":"2021-07-28T22:20:01-07:00"},"DocNumber":"2024","TxnDate":"2025-09-01","Line":[{"Id":"123","DetailType":"ItemAdjustmentLineDetail","ItemAdjustmentLineDetail":{"ItemRef":{"value":"1010000001"},"QtyDiff":20}}]} { "AdjustAccountRef": { "value": "5", }, "domain": "QBO", "sparse": false, "DocNumber": "2024", "TxnDate": "2025-09-01", "Line": [ { "Id": "1", "DetailType": "ItemAdjustmentLineDetail", "ItemAdjustmentLineDetail": { "ItemRef": { "value": "1010000001" }, "QtyDiff": 20 } } ] } |
The adjusted inventory item appears in the QuickBooks Online UI as shown below:
Inventory adjustments are tracked by Inventory Adjustment Id and displayed in the UI as shown below:
In this example, InventoryAdjustment.Id
= 145500061
The following is an example of how to use inventory adjustment–in this case, converting raw materials to finished goods. The example shows the steps for each part of the process and how the corresponding information displays in the UI. Assume it takes the following to convert the raw materials to finished goods:
We’ll first create the products, account, and expenses:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | { "AccountRef":{ "value":"35" }, "PaymentType":"Cash", "EntityRef":{ "value":"66", "name":"RawMaterialVendor", "type":"Vendor" }, "Line":[ { "Id":"1", "Amount":20.00, "DetailType":"ItemBasedExpenseLineDetail", "ItemBasedExpenseLineDetail":{ "BillableStatus":"NotBillable", "ItemRef":{ "value":"1010000042", "name":"Raw Material A" }, "UnitPrice":10, "Qty":2, "TaxCodeRef":{ "value":"NON" } } }, { "Id":"2", "Amount":10.00, "DetailType":"ItemBasedExpenseLineDetail", "ItemBasedExpenseLineDetail":{ "BillableStatus":"NotBillable", "ItemRef":{ "value":"1010000081", "name":"Raw Material B" }, "UnitPrice":5, "Qty":2, "TaxCodeRef":{ "value":"NON" } } } ] } |
Once these are created, they appear as follows in the UI:
The quantity is updated as shown here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | "AccountRef":{ "value":"35" }, "PaymentType":"Cash", "EntityRef":{ "value":"67", "name":"Labor", "type":"Employee" }, "Line":[ { "Id":"1", "Amount":1.00, "DetailType":"AccountBasedExpenseLineDetail", "AccountBasedExpenseLineDetail":{ "AccountRef":{ "value":"92", "name":"WIP" }, "BillableStatus":"NotBillable", "TaxCodeRef":{ "value":"NON" } } } ] } |
This appears in the UI as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | { "AdjustAccountRef":{ "value": "92" }, "domain":"QBO", "sparse":false, "DocNumber":"51", "TxnDate":"2024-05-31", "Line":[ { "Id": "1", "DetailType":"ItemAdjustmentLineDetail", "ItemAdjustmentLineDetail":{ "ItemRef":{ "value":"1010000081" }, "QtyDiff":-1 } }, { "Id": "2", "DetailType":"ItemAdjustmentLineDetail", "ItemAdjustmentLineDetail":{ "ItemRef":{ "value":"1010000042" }, "QtyDiff":-1 } } ] } |
Response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | "InventoryAdjustment": { "Id": "1455000166", "AdjustAccountRef": { "value": "92", "name": "Inventory Shrinkage" }, "TxnDate": "2024-05-31", "PrivateNote": "", "DocNumber": "51", "MetaData": { "LastUpdatedTime": "2024-05-31" }, "SyncToken": "0", "Line": [ { "ItemAdjustmentLineDetail": { "ItemRef": { "value": "1010000081" }, "QtyDiff": -1 }, "Id": "1" }, { "ItemAdjustmentLineDetail": { "ItemRef": { "value": "1010000042" }, "QtyDiff": -1 }, "Id": "2" } ], "domain": "QBO", "sparse": false }, "time": "2024-05-31T13:58:07.001-07:00" |
This appears in the UI as follows:
Now the WIP is $16:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "AdjustAccountRef":{ "value": "92" }, "domain":"QBO", "sparse":false, "DocNumber":"51", "TxnDate":"2024-05-31", "Line":[ { "DetailType":"ItemAdjustmentLineDetail", "ItemAdjustmentLineDetail":{ "ItemRef":{ "value":"1010000062" }, "QtyDiff":1, "PrivateNote": "Convert Raw material to finished goods" } } ] } |
Response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | { "InventoryAdjustment": { "Id": "1455000171", "AdjustAccountRef": { "value": "92", "name": "Inventory Shrinkage" }, "TxnDate": "2024-05-31", "PrivateNote": "", "DocNumber": "51", "MetaData": { "LastUpdatedTime": "2024-05-31" }, "SyncToken": "0", "Line": [ { "ItemAdjustmentLineDetail": { "ItemRef": { "value": "1010000062" }, "QtyDiff": 1 }, "Id": "1" } ], "domain": "QBO", "sparse": false }, "time": "2024-05-31T14:03:58.941-07:00" } |
This appears in the UI as follows:
With this change, WIP goes to zero:
The raw material has now been converted to finished product:
For a detailed list of error codes, see Review QuickBooks Online Accounting API error codes.
Any errors not described on the Errors page are returned with error code = 6000 in the following format:
Message = BusinessValidationError : <message details>
The system supports only 500 line items in an adjustment. If more than 500 line items are included in a create or update adjustment, the system throws a validation error with the message:
Provided Adjustment Line Items exceed the max limit. Please reduce the line items.
If a value for the SyncToken
attribute is not provided during an update operation, this may result in an error similar to the following:
{"Fault":{"Error":[{"code":"6000","Message":"Validation error with user input","Detail":"Variable \"$input\" got invalid value { id: \"1455000298\", adjustmentAccountId: \"5\", adjustmentDate: \"2023-08-25\", referenceNumber: \"2014\", reason: \"SHRINKAGE\", adjustmentLineItems: [[Object]] }; Field \"version\" of required type \"Long!\" was not provided."}],"type":"ValidationFault"}, "time":"04:33:10.209637"}
The following are solutions to errors caused by common API mistakes.
{"Fault":{"Error":[{"Message":"A business validation error has occurred while processing your request","Detail":"Business Validation Error : You need to provide accounts element id","code":"6000","element":""}],"type":"ValidationFault"}, "time":"2024-07-11T08:04:50.559-07:00"}
If this error occurs, check that AdjustAccountRef.value
in your request payload is set to a valid existing account id for your company realm.
To see a list of valid account id values, query the account as in the following example:
GET /v3/company/<realmID>/query?query=Select * from Account where Name='Inventory Shrinkage'&minorversion=70
For more on this endpoint, see Query an account.
{"Fault":{"Error":[{"Message":"Unsupported Operation","Detail":"Operation Could not find resource","code":"500"}],"type":"ValidationFault"},"time":"2024-07-11T08:02:01.180-07:00"}
If this error occurs, check the following:
POST
operations.Id
does not need to be provided in the request body.AdjustAccountRef.value
attribute must be a valid/existing account value for your company realm and the sparse
attribute must be set to true
.