GuidesMETRC field guides for Rhode Island
METRC package adjustments in Rhode Island: Quantity is the new total, not a delta, and the adjustments log reports the difference
PUT /packages/v2/adjust sets a package’s quantity to the number in the request; it does not add that number to what the package held. On 2026-09-03, on the Rhode Island sandbox, sending Quantity: -1 to a package holding 40 Each returned HTTP 200 and left the package at -1, not 39, and GET /packages/v2/adjustments logged an AdjustmentQuantity of -41, the delta METRC computed from 40 to the target. Sending Quantity: 40 put the package back to 40, where a delta reading would have given 39. METRC’s own API reference shows an example body with "Quantity": -2.0, which reads unmistakably as subtract two, and that is the trap.
- Observed
- Revised
- Environment
- Rhode Island production and sandbox
What this page is
This page records what SeedLink observed about the package adjustment call on the Rhode Island METRC API, dated, with the call that produced each observation. The delta-versus-absolute proof, the accepted negative quantity, the unit mismatch and the on-transfer refusal were all made on one Rhode Island sandbox facility on 2026-09-03; the manifest that followed a hand adjustment was read on Rhode Island production the same day. It is not METRC documentation and it is not regulatory guidance.
It is also not a description of what SeedLink writes. SeedLink writes no adjustments today; the writes on this page were made on a sandbox package to settle a question that the documentation’s own example answers the wrong way, and the page says so where the sandbox and production have been seen to differ. Other states run their own METRC instances and can differ on every point below.
How every number on this site is observed, dated and bounded is on the methodology page, which also lists what SeedLink does not publish.
What the adjust call takes
The endpoint is PUT /packages/v2/adjust, and the body is an array: one element per package, each with six fields. Five of them are what they look like. The sixth, Quantity, is not.
| Field | What it carries | What was observed |
|---|---|---|
Label | The tag of the package being adjusted | One package per element; the body is an array |
Quantity | The new absolute quantity of the package, not a change to it | Sending -1 to a package holding 40 Each left it at -1; sending 40 put it back to 40 |
UnitOfMeasure | The package’s existing unit | Each on a Grams package: HTTP 400, the unit cannot be changed |
AdjustmentDate | The date of the adjustment | Carried on every call; nothing further observed |
AdjustmentReason | One of the reasons GET /packages/v2/adjust/reasons lists | Nine reasons in Rhode Island, and every one requires a note |
ReasonNote | The note the reason requires | Required on all nine reasons; a human statement about physical reality |
METRC’s API reference shows an example body for this call with "Quantity": -2.0. Read cold, that is "subtract two", and an integration written against the example sends the shortfall as the quantity. The proof below is what happens to a body written that way.
Sent, read back, logged: the proof
On 2026-09-03 SeedLink made the two writes below on one Rhode Island sandbox facility, against a package holding 40 Each, and read the package and the adjustments log after each. The request takes the target total and the adjustments log reports the delta, and those are two different numbers.
| Step | Sent in the body | `GET /packages/v2/{label}` read | `GET /packages/v2/adjustments` logged | A delta reading would have given |
|---|---|---|---|---|
| Before any call | No call yet | Quantity = 40 | No call yet | 40 |
| The "short by one" the documentation implies | Quantity: -1 | Quantity = -1 | AdjustmentQuantity = -41 | 39 |
| Restore | Quantity: 40 | Quantity = 40 | Not read | 39 |
The decisive number is the -41. A delta request of -1 would have logged -1. METRC logged the difference between the package’s prior 40 and the -1 it was told to hold, which means it treated -1 as the destination. The restore says the same thing from the other side: a delta of 40 on a package at -1 gives 39, and the package read 40.
Both calls returned HTTP 200. Nothing in either response said the package had gone negative, and nothing in either distinguished "set to" from "changed by".
No clamp at zero
METRC accepted a negative package quantity with HTTP 200 and no warning: a package holding 40 Each was left holding -1 and the API raised nothing.
On the sandbox that is a curiosity. Against a production license it is a false inventory statement filed under the user’s own METRC account. So a write path has to refuse a negative result itself, before the call: compute the target from a live read, compare it to zero, and stop. METRC provides no backstop, and the call that files a false statement looks identical to the call that files a true one.
All nine reasons require a note
GET /packages/v2/adjust/reasons returns the reasons an adjustment may carry. On the Rhode Island sandbox on 2026-09-03 it listed 9, and RequiresNote was true on every one of them. There is no note-free adjustment in Rhode Island.
| Reason | `RequiresNote` |
|---|---|
| Drying | true |
| Entry Error | true |
| OCR Investigation | true |
| Processing Loss | true |
| Quality Control Sample | true |
| Scale Variance | true |
| Spoilage | true |
| Theft | true |
| Waste | true |
The reason and the note are a human judgement about physical reality, which is the other reason an integration should not fabricate them. On one Rhode Island production correction the cultivator’s own reason was Entry Error, with a note giving the real count: a person who counted, saying what they counted.
The unit must match the package, and a third of packages are in grams
UnitOfMeasure is not a conversion. Adjusting a Grams package with Each on 2026-09-03 returned HTTP 400 with the message The Unit of Measure must match the existing package (Grams), cannot be changed to Each. The field has to repeat the unit the package already has, which means the package has to be read live before it is adjusted.
This is not a rare shape: of the 1,355 packages the three connected cultivators shipped in the 540 days to 2026-09-03, 472 (34.8%) were mass-denominated, and every product category shipped one way only.
| Product categories | Shipped in | Packages | Packages the other way |
|---|---|---|---|
| Bud/Flower, Shake/Trim, Concentrate, Wet Whole Plant, Infused Bud/Flower | Grams | 472 | None by count |
| Edible, Tinctures, Vape Cart, Pre-Packaged Bud, pre-rolls | Count | 883 | None by mass |
The category says which unit to look for; the live read confirms it. The 400 comes from the same endpoint, with the same status, as the refusal in the next section.
A package on a transfer is locked to the API, not to a person
PUT /packages/v2/adjust on a package that is part of a transfer template or a dispatched transfer returned HTTP 400 with the message Package <label> cannot be Adjusted because it is part of an existing Transfer. The identical call on a package with no transfer returned HTTP 200 (both on 2026-09-03, Rhode Island sandbox). The lock is the transfer, not permissions: same credentials, same body, different package.
That window is where a short count is actually found: at the loading dock, when a template or a dispatched transfer already exists. The case the API refuses is the common one, not the edge.
METRC Connect can still adjust such a package, and the manifest follows. On Rhode Island production a cultivator adjusted a package on a dispatched, in-transit manifest (dispatched 2026-09-02 at 01:24 UTC, adjusted 2026-09-03 at 05:21 UTC, by -21) and the transfer’s ShippedQuantity moved from 100 to 79 on its own; the delivery had not yet been received. There is no API equivalent, and what a person did in the web UI is not evidence of what the API allows.
It also explains why a manifest is never edited. A transfer template carries no quantity: PackageLabel, WholesalePrice, GrossWeight and GrossUnitOfWeightName only. The package is adjusted and the manifest ships what the package holds.
| The call | The package | METRC answered | What to do |
|---|---|---|---|
UnitOfMeasure: Each | A Grams package, no transfer | HTTP 400: The Unit of Measure must match the existing package (Grams), cannot be changed to Each. | Read the package first and send the unit it reports |
| A valid body | On a transfer template or a dispatched transfer | HTTP 400: Package <label> cannot be Adjusted because it is part of an existing Transfer. | Do not retry. The correction is made by a person in METRC Connect, and the manifest follows the package |
| The identical body | The same shape of package, no transfer | HTTP 200 | The adjustment applied; the earlier refusal was the transfer, not the credentials |
Quantity: -1 | Holding 40 Each, no transfer | HTTP 200, no warning; the package then read -1 | Refuse a negative target before the call; METRC does not |
Both 400s come from the same endpoint with the same status. Classify on METRC’s message text, never on the status code: one means "send the right unit", the other means "stop, a person has to do this".
What SeedLink does with a short count
SeedLink writes no adjustments today. The path that works for a real short count runs the other way round: the cultivator fixes the count in METRC Connect first, which is the one door that is open while the package sits on a manifest; the integration then reads the package live, sees that it already holds the target, and corrects only its own records.
Two things fall out of the proof for anyone who does write the call. The target is computed from a live read of the package, never from a remembered balance, because the request replaces the balance rather than moving it. And a target below zero is refused before the request is built, because METRC accepts it.
Check it yourself, and the sandbox caveat
Two read-only calls show the two numbers side by side on any package that has been adjusted: the package’s running balance, and the delta METRC computed for the adjustment.
GET /packages/v2/{label}?licenseNumber=<your license>
read Quantity: the running balance
GET /packages/v2/adjustments?licenseNumber=<your license>
find the row for that label; read AdjustmentQuantity: the delta METRC computed
after a hand adjustment from an old count to a new count:
Quantity = the new count
AdjustmentQuantity = the new count minus the old countThe proof itself needs a write, so it belongs on the sandbox and never on a production license. SeedLink’s proof was: send Quantity: -1, read both endpoints, then send the original count to restore the package. If the package reads the number you sent and the log reads the difference, the call is absolute.
One sandbox caveat. On 2026-07-23 the single-package GET after an adjust reported the last adjustment amount as Quantity rather than the running balance on the Rhode Island sandbox. The 2026-09-03 reads were consistent, and the adjustments log is what settles the question either way, so anyone verifying this should prefer production reads or read the adjustments log alongside the package.
Questions
- Is Quantity in PUT /packages/v2/adjust a delta or the new total?
- The new total. On the Rhode Island sandbox on 2026-09-03 a package holding 40 Each was sent
Quantity: -1and then held -1, not 39; the adjustments log recorded -41, the delta METRC computed. Sending 40 restored it to 40. - Why does METRC’s API reference show "Quantity": -2.0?
- It is the example body in the reference for this call, and it reads as "subtract two". The observed behaviour is that the package is set to the number sent. We do not know why the example is written that way.
- What happens if the new total is negative?
- METRC accepts it. A package went to -1 with HTTP 200 and no warning on 2026-09-03. Against a production license that is a false inventory statement under your own account, so refuse a negative target before the call is made.
- Which adjustment reasons need a note?
- All of them.
GET /packages/v2/adjust/reasonslisted 9 reasons on 2026-09-03 withRequiresNotetrue on every one: Drying, Entry Error, OCR Investigation, Processing Loss, Quality Control Sample, Scale Variance, Spoilage, Theft and Waste. - Can I adjust a package in a different unit of measure?
- No. A Grams package adjusted with
Eachreturned HTTP 400 and the messageThe Unit of Measure must match the existing package (Grams), cannot be changed to Each.Read the package’s unit live and send that. - Can I adjust a package that is already on a manifest?
- Not through the API. A package on a template or a dispatched transfer returned HTTP 400 with
Package <label> cannot be Adjusted because it is part of an existing Transfer.A person can adjust it in METRC Connect, and on production the transfer’sShippedQuantityfollowed, from 100 to 79, while the delivery was still in transit. - Do I fix the manifest quantity instead?
- There is nothing on the manifest to fix. A transfer template carries no quantity, only
PackageLabel,WholesalePrice,GrossWeightandGrossUnitOfWeightName. The package is adjusted and the manifest ships what the package holds.
Sources and how to cite this page
- PUT /packages/v2/adjust, GET /packages/v2/{label} and GET /packages/v2/adjustments on one Rhode Island sandbox facility, 2026-09-03: the delta-versus-absolute proof (Quantity -1 then 40 on a package holding 40 Each), the accepted negative, the unit-mismatch 400, and the on-transfer 400 beside its no-transfer 200.
- GET /packages/v2/adjust/reasons, Rhode Island sandbox, 2026-09-03: nine reasons, RequiresNote true on each.
- Read-only probe of one dispatched outgoing transfer and its package on Rhode Island production, 2026-09-03: ShippedQuantity 100 to 79 after a METRC Connect adjustment of -21.
- Single-package GET after an adjust on a different Rhode Island sandbox facility, 2026-07-23.
- SeedLink METRC field guide (docs/METRC.md), section Manifest and order reconciliation: the denomination split across 1,355 packages shipped in the 540 days to 2026-09-03.
SeedLink, "METRC package adjustments in Rhode Island: Quantity is the new total, not a delta, and the adjustments log reports the difference", observed 2026-09-03, revised 2026-09-20, https://www.seedlink.net/guides/metrc/adjust-is-absolute
Every figure above carries the date it was observed and the environment it was observed in. A count belongs to one facility on one day; the field names, orderings and error messages are the durable part.
Machine-readable copy of this page, with the same facts, dates and sources: /guides/metrc/adjust-is-absolute/data.json
Related
- A METRC transfer template becomes a manifest only when a person dispatches it in METRC Connect: Rhode Island exposes no dispatch endpoint
- The Rhode Island METRC API returns an empty HTTP 200 when the required date filters are missing, and several other traps produce the same empty answer
- Combining two METRC packages of one item in Rhode Island is one POST with two ingredients, and the drained sources stay active until you finish them
- METRC item UnitWeight in Rhode Island: it persists only when the category has RequiresUnitWeight true, and the PUT returns 200 either way
- All metrc field guides for rhode island
- Methodology: what SeedLink publishes and what it does not