GuidesMETRC field guides for Rhode Island
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
On the Rhode Island sandbox on 2026-07-27, one POST /packages/v2/ carrying 2 ingredients (3 Each and 3 Each of one pre-roll item) created a single package holding 6 Each, TestPassed, on one adult-use tag, and the next sync read both sources at 0. The same day, on Rhode Island production, a cultivator did the equivalent by hand in METRC Connect: two packages of one pre-roll item holding 664 and 265 units went inactive at 20:33 UTC and a package of the same item holding 929 appeared in the same minute. Both paths leave the emptied sources in /packages/v2/active until something finishes them, because METRC never closes a package just because a draw emptied it.
- Observed
- Revised
- Environment
- Rhode Island production and sandbox
What this page is
This page records how the Rhode Island METRC API behaved when SeedLink merged packages through it and when a cultivator merged them by hand, with the date and the call behind each number. It covers the create call and its body, what a safe combine refuses before it consumes a tag, what the call leaves behind and how to close that out, and how to recognise a package that somebody else combined.
It is not METRC documentation and it is not regulatory guidance. The counts belong to one facility on one day and moved the moment the next package was created; the shape of the calls, the error messages and the lifecycle of a drained package are what this page is about. Other states run their own METRC instances and can differ on every point below.
SeedLink’s own order bookkeeping around a combine (which order lines move onto the new package, how the sellable count is re-derived) is context here, not the subject. Where it is mentioned, it is to say why a rule exists.
How every number on this site is observed, dated and bounded is on the methodology page, which also lists what SeedLink does not publish.
One POST, several ingredients
POST /packages/v2/ is documented as the call that creates packages from other packages, and its body carries an Ingredients array. Every package SeedLink had created through it before 2026-07-27 passed exactly 1 ingredient: a child cut from one source. Passing several ingredients in one call is how packages are merged. METRC creates one new package on one new tag and draws the named quantity from each source.
| Environment | How the merge was made | Sources | Result | What was read afterwards |
|---|---|---|---|---|
| Rhode Island production | By hand, in METRC Connect | Two packages of one pre-roll item, 664 and 265 units | One package of the same item holding 929 | Both sources inactive at 20:33 UTC; the successor visible in the same minute |
| Rhode Island sandbox | One POST /packages/v2/ with 2 ingredients | 3 Each and 3 Each of one pre-roll item | One package of 6 Each, TestPassed, on an adult-use tag | Both sources at 0 on the next sync, and still listed in /packages/v2/active |
Everything moves. The new package takes the full live contents of every source and the sources close out. A partial draw would leave a fragmented remainder in each source and a second sticker to print, and the cultivator is physically consolidating containers.
Lab state travels with the contents: the sandbox result read TestPassed because both sources were TestPassed. What a merge of two different states produces is not something to find out with a tag, so the mixed case is refused before the call (see the refusals below).
The grouping key is the item id, never the name
Two packages are the same sellable thing when they carry the same METRC Item.Id. That is METRC’s own definition of sameness, and it is the one to group on. A match on the product name or the strain is a guess, and a wrong guess mislabels a regulated package under a tag that has already been printed and applied.
So whether two packages may be combined is answered from Item.Id and nothing softer. Within one item the sources still have to agree on the things that make their quantities add:
- Unit of measure: a count in Each and a mass in Grams are not one quantity.
- Pack shape: a single and a 3-pack are not one unit count, even under one item.
- Lab-testing state: two
TestPassedsources produced aTestPassedresult on 2026-07-27; a passed source and an untested one are refused.
What a safe combine refuses before it consumes a tag
The new package goes onto a tag, and the tag prints on the sticker on the box, so the combine fails closed: every condition below refuses the whole group and says why, before POST /packages/v2/ is called. A refused combine costs nothing. A wrong one costs a tag, a relabel and a package to archive, the recovery the package-tags guide describes.
| Condition | Why it refuses | When it is checked |
|---|---|---|
| A source is on hold | A held package is not one to ship; the hold has to clear first | Before the call, from the synced record |
A source has no LocationName | POST /packages/v2/ returns HTTP 400 with Location was not specified.; an existing package’s LocationName is the value to pass | Before the call, from the synced record |
| Mixed lab-testing states | Merging passed product into an untested package yields a package that cannot be manifested | Before the call, from the synced record |
| Mixed pack shape | A single and a 3-pack are not one unit count | Before the call, from the synced record |
| A source another open, undispatched order draws from | Its contents are already promised; the refusal names that order | Before the call, from the open orders |
| A source does not exist, is finished, or is empty | There is nothing to draw; the synced record was stale | Live, per source, immediately before the call |
Sources disagree on Item.Id or unit of measure | They are not one sellable thing (previous section) | Live, per source, immediately before the call |
The live pass matters because the synced record is a snapshot: a package the cultivator finished, emptied or re-tagged since the last sync still looks whole in it. A source that fails the live read refuses the group rather than dropping out of it quietly.
The drained sources stay active at zero until something finishes them
METRC never closes a package because a draw emptied it. On the sandbox on 2026-07-27 both sources read 0 after the combine and were still listed by GET /packages/v2/active. Rhode Island leaves a zeroed package there until a call finishes it, and the finish is a separate write with its own verb.
The verb is PUT /packages/v2/finish, with a body of [{Label, ActualDate}]. A POST to the same path returns HTTP 405, and a package can be finished only when it is empty. A package with anything left in it is adjusted to 0 first, and an adjustment sets the quantity rather than subtracting from it, which the adjustments guide covers.
| Call | Verb | Body | Precondition | Effect observed | Undo |
|---|---|---|---|---|---|
/packages/v2/finish | PUT; a POST returns HTTP 405 | [{Label, ActualDate}] | The package is empty | The package left /packages/v2/active; the child’s SourcePackageLabels still named it (2026-07-28) | PUT /packages/v2/unfinish |
/packages/v2/unfinish | PUT | The finished package (the 2026-07-28 check recorded the effect, not the body) | The package is finished | The package returned to /packages/v2/active with its lineage intact (2026-07-28) | Finish it again |
When checking this by hand, pad the /packages/v2/active read’s lastModifiedEnd forward by a day. Without the padding a just-modified package falls outside the window and looks as if it never came back, which reads exactly like an unfinish that failed. Observed on 2026-07-28.
Finishing is reversible; the tag is not. That asymmetry is why SeedLink finishes drained sources automatically after a combine, and only what METRC itself reports at a readable numeric zero, re-read live: a quantity that cannot be read is not a quantity known to be zero. A failure in that tidy-up never fails the combine; the sources are left for the cultivator, the state they were in before.
Cultivators already finish drained sources by hand
Closing an emptied package is not a chore an integration invents; the cultivators were already doing it. A read-only probe of two Rhode Island production facilities on 2026-07-28 looked at every single-draw full drain, the shape a combine leaves behind, and at whether any finished package had ever been reopened.
| Facility | Single-draw full drains finished the same day | Finished eventually | Ever un-finished |
|---|---|---|---|
| One Rhode Island cultivator | 93% (p90 0 days) | 255 of 256 | Never |
| A second cultivator | 81% | 109 of 109 | Never |
Across 533 inactive packages at the two facilities, none had ever been un-finished. Of the 4 source packages SeedLink’s own packaging had drawn from, 3 had been finished by the cultivator by hand, not by the integration: the integration had been creating the errand, not closing it. Finishing automatically changes the timing of an outcome the cultivators had already chosen, not the outcome.
Recognising a package somebody combined by hand
Combining in METRC Connect is the long-standing habit, and it strands any record that still points at the old tags: those packages are now inactive and empty, and nothing announces the new one. In SeedLink the failure was silent until the manifest step, which failed naming the raw tags without a word about a successor.
The evidence is lineage. SourcePackageLabels on the new package is a comma-separated list of the tags it was built from, and it survives a finish: on 2026-07-28 finishing the source left the child’s lineage untouched. Recognising the successor from that field is a read, not a write, and it fails closed.
| What the live read shows | Verdict | Why |
|---|---|---|
No active package names the dead tag in SourcePackageLabels | No successor | Nothing active was built from it |
| Exactly one active package names it, on the same item | The successor | One child on the same item is the package the contents went to |
| More than one active package names it | Ambiguous; refuse | A source split across children is legal, and lineage alone cannot say which child holds which units |
| The one package naming it carries a different item | Not a combine; refuse | A production blend legitimately lists many sources; a different item is a new product |
| A candidate is finished, empty, on hold, recalled, a trade sample or marked for destruction | Excluded before any of the above | None of those can carry the contents forward |
Recognising a successor writes nothing to METRC: no tag, no package, no finish. The cultivator’s own combine in METRC Connect already finished the sources, so a finish from the integration would have nothing to act on.
A retry must find its own package, not consume a second tag
A lost response to POST /packages/v2/ looks the same as a failure, and METRC has no reservation step for tags, so a naive retry consumes a second tag on a second package. The defence is the package Note: stamp your own reference onto every package you create, and on a retry read for that stamp before creating anything. A package carrying the stamp and the right item is yours and is re-linked; a package at the tag without it is somebody else’s, and the original error stands. The package-tags guide covers why existence at a tag is not proof of ownership.
One adult-use tag is consumed per combine group, taken from GET /tags/v2/package/available through the same deny-list that keeps medical and hemp tags off wholesale packages; that list is the package-tags guide’s subject and is not repeated here.
Check it yourself
Two reads, one write, one finish. The reads cost nothing; the write consumes a tag, so run the reads first and stop if they disagree.
GET https://api-ri.metrc.com/packages/v2/<source A>?licenseNumber=<your license>
GET https://api-ri.metrc.com/packages/v2/<source B>?licenseNumber=<your license>
Authorization: Basic <base64 of VENDOR_KEY:USER_KEY>
both active, neither finished, both Quantity above zero,
same Item.Id, same unit of measure, same LabTestingState, same pack shape
POST https://api-ri.metrc.com/packages/v2/?licenseNumber=<your license>
[
{
"Tag": "<one adult-use tag from /tags/v2/package/available>",
"Location": "<the LocationName one of the sources sits in>",
"Item": "<the item name, as both sources carry it>",
"Quantity": <the quantity of A plus the quantity of B>,
"UnitOfMeasure": "<the unit both sources carry>",
"ActualDate": "<today, YYYY-MM-DD>",
"Note": "<your own reference, so a retry can find this package>",
"Ingredients": [
{ "Package": "<source A>", "Quantity": <the full live quantity of A>, "UnitOfMeasure": "<the unit>" },
{ "Package": "<source B>", "Quantity": <the full live quantity of B>, "UnitOfMeasure": "<the unit>" }
]
}
]
GET https://api-ri.metrc.com/packages/v2/<new tag>?licenseNumber=<your license>
SourcePackageLabels names <source A> and <source B>, comma-separated
PUT https://api-ri.metrc.com/packages/v2/finish?licenseNumber=<your license>
[
{ "Label": "<source A>", "ActualDate": "<today>" },
{ "Label": "<source B>", "ActualDate": "<today>" }
]Then read /packages/v2/active with lastModifiedEnd padded forward by a day: both sources are gone from it, and the new package is there with both tags in its SourcePackageLabels. PUT /packages/v2/unfinish brings the sources back with the lineage intact; the tag on the new package is the one thing in this sequence that cannot be undone.
Questions
- Can one POST /packages/v2/ merge more than one package?
- Yes. The endpoint creates packages from other packages and takes an
Ingredientsarray. On the Rhode Island sandbox on 2026-07-27 one call with 2 ingredients, 3 Each and 3 Each of one item, created one package of 6 Each on an adult-use tag. - Why are my source packages still active after the combine?
- Because METRC never closes a package just because a draw emptied it. Both sandbox sources read 0 and stayed in
/packages/v2/activeuntil they were finished withPUT /packages/v2/finish, which takes[{Label, ActualDate}]and only works on an empty package. - Is finishing a package reversible?
- Yes.
PUT /packages/v2/unfinishreturned a finished package to/packages/v2/activeon the Rhode Island sandbox on 2026-07-28, and the finish had left the child’sSourcePackageLabelsuntouched. The tag consumed by the combine is not reversible. - Why does the finish use PUT?
- Because a
POSTto/packages/v2/finishreturns HTTP 405. The create call has a required field in the same spirit:POST /packages/v2/without aLocationreturns HTTP 400 withLocation was not specified. - Can I combine packages of two different items, or two pack sizes of one item?
- Not as a combine. Sameness is
Item.Id; a package built from sources of another item is a production blend, and a single and a 3-pack do not share a unit count. Both are refused before any write. - Does the lab-testing state carry to the combined package?
- On the sandbox on 2026-07-27, two
TestPassedsources produced aTestPassedresult. Mixed states are refused before the call, because merging passed product into an untested package yields something that cannot be manifested. - How do I find the package a cultivator combined by hand in METRC Connect?
- Read
SourcePackageLabelson the active packages: it is a comma-separated list of parent tags. Exactly one active package on the same item naming the dead tag is the successor. None means no successor, more than one is ambiguous, and one on a different item is a blend; refuse rather than guess in every case but the first. - Do cultivators actually finish drained packages?
- Essentially always. On 2026-07-28 one Rhode Island cultivator had finished 93% of its single-draw full drains the same day and 255 of 256 eventually; a second had finished 81% the same day and 109 of 109 eventually; across 533 inactive packages, neither had ever un-finished one.
Sources and how to cite this page
- SeedLink combine run against the Rhode Island sandbox, 2026-07-27: one POST /packages/v2/ with two ingredients, the single-package GET on the result, and the package sync that followed.
- Rhode Island production package sync at one cultivator facility, 2026-07-27, read-only: two packages of one item inactive at 20:33 UTC and their successor appearing in the same minute after a combine by hand in METRC Connect.
- PUT /packages/v2/finish and PUT /packages/v2/unfinish exercised by hand on the Rhode Island sandbox, 2026-07-28, with GET /packages/v2/active read before and after.
- Read-only probe of package finish history at two Rhode Island production cultivator facilities, 2026-07-28.
- SeedLink METRC field guide (docs/METRC.md), sections Combining split packages into one shipment, Closing out a drained source, Adopting a package the cultivator combined by hand, and the sandbox lab-testing notes on Location and the finish verb; the request body field names were checked against SeedLink’s own METRC client.
SeedLink, "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", observed 2026-07-28, revised 2026-09-20, https://www.seedlink.net/guides/metrc/combining-packages
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/combining-packages/data.json
Related
- METRC package tags in Rhode Island: adult-use and medical share one list, and medical comes first
- METRC package adjustments in Rhode Island: Quantity is the new total, not a delta, and the adjustments log reports the difference
- A METRC transfer template becomes a manifest only when a person dispatches it in METRC Connect: Rhode Island exposes no dispatch endpoint
- METRC remediation transfers in Rhode Island: the outgoing delivery’s ShipmentTypeName is the only sign a package is out, and the incoming transfer is the proof it came back
- All metrc field guides for rhode island
- Methodology: what SeedLink publishes and what it does not