SeedLink
CustomersSign inRequest access

Guides/METRC field guides for Rhode Island

METRC package tags in Rhode Island: adult-use and medical share one list, and medical comes first

Rhode Island issues every licensed cultivator both adult-use and medical package tags, and GET /tags/v2/package/available returns both kinds in a single list with the medical tags first. On 2026-06-04 one production cultivator facility held 305 adult-use tags and 60 medical tags, in that order. An integration that takes the first N tags from that list burns medical tags on adult-use packages, and because the tag number is printed on the physical sticker, the mistake is not a database edit: it is peeling labels, archiving packages and rebuilding the manifest by hand.

Observed
September 7, 2026
Revised
September 20, 2026
Environment
Rhode Island production and sandbox

What this page is

This page records what SeedLink’s production integration observed on the Rhode Island METRC API, dated, with the read-only probe that produced each number. It is not METRC documentation and it is not regulatory guidance: it describes how the API behaved for licensed Rhode Island cultivators on the dates given.

Tag counts belong to one facility on one day and move with every package created; the shape of the response, the field names and the ordering are what this page is about. 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 available-tags endpoint returns in Rhode Island

GET /tags/v2/package/available?licenseNumber=... returns the unused package tags a facility holds. In Rhode Island the response mixes two kinds of tag, and they are told apart by two fields on every row rather than by a separate endpoint or a query parameter.

The two fields that say what a tag is, as observed at one Rhode Island production facility on 2026-06-04
FieldAdult-use tagMedical tag
TagTypeNameCannabis PackageMedical Package
TagInventoryTypeNameCannabisPackageMedicalPackage
Label prefix at this facility1A42A031A42A01
What SeedLink burns it onAdult-use wholesale packagesNothing yet: no medical seller has onboarded

There is no IsUsed field on the Rhode Island production response. The endpoint returns only unused tags, so a filter on that field is a harmless no-op that reads as if it were doing work.

The labels themselves also differ by a digit at this facility, and that is the wrong thing to filter on; the prefix encodes the license (see the section on the type fields).

The order of the list is the trap

The medical tags come first. On 2026-06-04 the facility above held 305 adult-use tags and 60 medical tags, and every medical tag preceded every adult-use tag in the response. Nothing in the payload announces the ordering; it is only visible when the two kinds are counted by position.

One facility’s available package tags on 2026-06-04, read-only, no writes
Tag kindTags availablePosition in the list
Medical (Medical Package)60First
Adult-use (Cannabis Package)305After every medical tag

The original packaging logic in SeedLink took the first N tags from the list, which is the natural thing to write against the documentation, since the documentation describes one list of available tags. Every adult-use wholesale order it packaged therefore drew from the medical pool first.

The count matters less than the order. A facility holding any medical tags makes the first-N mistake on every run; a facility holding none never sees it, which is how a bug of this kind survives testing on one license and ships to another.

The tag is physical

A METRC package tag is not a row. The tag number is printed on the sticker applied to every physical package, and for a multi-pack it is applied to each unit. A wrong tag therefore has no database fix. Recovery is: peel the labels off every unit, archive the wrongly tagged packages in METRC (a package deleted in METRC Connect is archived, and GET /packages/v2/{label} still returns it with its quantity intact), create new packages on adult-use tags, re-label, and rebuild the transfer manifest.

That is what happened on an early wholesale order SeedLink packaged in Rhode Island, in June 2026. The overnight packaging run created 2 packages on medical tags and the manifest step failed. The cultivator archived those packages, built adult-use packages and a manifest by hand in METRC Connect, and delivered on 2026-06-04; the rebuilt manifest carried 3 adult-use packages. SeedLink learned what had shipped afterwards, from a read-only probe of the outgoing transfer.

The cost is measured in units re-labelled, not in API calls. What followed was three guardrails, described below, and a rule that the tag type is shown to the cultivator before any package is created.

Match on the type fields, never the label prefix

At the facility above the medical labels begin 1A42A01 and the adult-use labels 1A42A03, and it is tempting to filter on that. Do not. The prefix encodes the license, so it is different at every facility, and the digit that happens to separate the two pools here carries no documented meaning.

  • Test TagTypeName for the substring medical, case-insensitively, and test TagInventoryTypeName the same way. A tag is medical if either field says so.
  • Treat a tag whose type fields are both empty as unclassifiable, and refuse the run rather than guess.
  • Read the type fields on every run. The tag pool changes with every package the facility creates, by hand or through any integration.

The check is deliberately a substring, not an equality. METRC has renamed things before, and a filter that demands the exact string Medical Package silently admits a renamed medical tag the day the rename lands.

Not medical is not adult-use: hemp tags

Excluding medical tags is not the same as selecting adult-use ones. The Rhode Island sandbox lists 1,000 Hemp Package tags beside 843 cannabis package tags (read on 2026-09-07 during a packaging pre-flight), and a hemp tag on a wholesale cannabis package is the same peel-the-labels failure by another name.

So the exclusion is a deny-list with two entries, medical and hemp, both matched as substrings on both type fields. Whether Rhode Island production facilities also hold hemp tags is not something this page can say: it was observed in the sandbox only.

There is no reservation step

METRC has no verb that reserves a tag. A tag leaves the available list only when POST /packages/v2/ consumes it, and the list an integration read a minute ago is already stale if anyone at the facility created a package in between, by hand in METRC Connect or through another integration.

The failure looks like this: the integration fetched the list once, consumed tags positionally, and a later create returned HTTP 400 with the message The Package Tag is not available. That error arrives at the same place in the code as a lost response does, which is exactly the case a reconcile-on-error path exists for.

The trap inside the trap is the reconcile. Asking METRC whether a package exists at that tag is trivially true in the collision case, so an integration that adopts whatever it finds links its order to somebody else’s physical package and reports success. The answer is proof of ownership, not proof of existence. SeedLink writes a note naming its own order line onto every package it creates, and Rhode Island production returns both Note and Item.Name verbatim on the single-package GET (verified 2026-07-25), so the check costs no extra call. A package that cannot be proven ours is refused and the original error is surfaced.

A guardrail that survives a rename

Three layers now stand between the tag list and the first irreversible create.

  1. Selection: the deny-list above, applied to every tag before any is consumed.
  2. A hard stop immediately before the first POST /packages/v2/: if any tag selected for the run is medical, the whole run is refused, with no partial burns, and an error is logged. It is pre-filtered today, so it never fires; it exists as a backstop for an irreversible, physical invariant.
  3. The tag and its type are shown to the cultivator in the dry run and the confirm step before anything is created, with a red alarm if a medical tag ever appears.

One version of the first layer was wrong in an instructive way. It shipped as an allow-list: a tag was consumed only if every populated type field read exactly Cannabis Package or Adult-Use Package. Any other string, such as the bare Package an older sandbox shape used, or a future rename, emptied the burnable pool for the entire license, and the resulting message told the cultivator to order more adult-use tags they already held. A deny-list cannot fail that way: an unrecognised type still burns, and is logged loudly so a person can look.

Failure modes observed or reproduced while building the tag guardrails
What the code didWhat happenedWhat replaced it
Took the first N available tagsConsumed medical tags on an adult-use order (June 2026)A substring deny-list on both type fields
Filtered on the label prefixCorrect at one facility, wrong at the nextType fields only; the prefix is license-specific
Allow-listed exact type stringsEmptied the pool on an unrecognised string and told the cultivator to buy tags they heldA deny-list; unrecognised types burn and are logged
Reconciled a 400 by checking that a package existed at the tagAdopted another party’s package after a collisionOwnership proof from the package note and item name

Check your own facility in one read-only call

The whole question is answerable with one GET and no writes.

GET https://api-ri.metrc.com/tags/v2/package/available?licenseNumber=<your license>
Authorization: Basic <base64 of VENDOR_KEY:USER_KEY>

for each row in the response:
  medical = contains(TagTypeName, "medical") or contains(TagInventoryTypeName, "medical")
  hemp    = contains(TagTypeName, "hemp")    or contains(TagInventoryTypeName, "hemp")

count the rows by (medical, hemp), and note the index of the first row that is neither

If the first row that is neither medical nor hemp is not at index zero, the first-N approach is wrong for your facility today. If it is at index zero, it is wrong for your facility on some other day.

Questions

Why does Rhode Island list medical tags before adult-use tags?
We do not know, and the ordering is undocumented. It was observed at one production facility on 2026-06-04 and is treated as arbitrary: classify every row by its type fields and never rely on position.
Can I tell adult-use from medical by the label prefix?
Not safely. At one facility the medical labels start 1A42A01 and the adult-use labels 1A42A03, but the prefix encodes the license and differs between facilities. Use TagTypeName and TagInventoryTypeName.
What happens if a medical tag is used on an adult-use package?
The tag is printed on the physical sticker, so the package has to be archived in METRC, new packages created on adult-use tags, every unit re-labelled, and the manifest rebuilt. On the June 2026 order this was done by hand in METRC Connect and the delivery still went out on 2026-06-04.
Is there an IsUsed field to filter on?
Not on the Rhode Island production response. The endpoint returns only unused tags. A filter on IsUsed does nothing and hides the fact that it does nothing.
Are hemp tags in the same list?
In the Rhode Island sandbox, yes: 1,000 Hemp Package tags beside 843 cannabis package tags on 2026-09-07. Exclude them the same way as medical tags. Whether production facilities hold hemp tags was not observed.
Can two systems consume the same tag?
They can try. There is no reservation step, so a tag read as available can be consumed by anyone before the create call, which then fails with HTTP 400 and the message The Package Tag is not available. Retry from a fresh read, and never adopt an existing package at that tag without proof that it is yours.
How do I prove that a package at a tag is mine?
Stamp a note naming your own record onto every package you create, and check that note plus the item name on the single-package GET before linking anything to it. Rhode Island production returns both verbatim.

Sources and how to cite this page

  • GET /tags/v2/package/available at one Rhode Island production facility, read-only, 2026-06-04.
  • Read-only probe of the outgoing transfer the cultivator rebuilt by hand, Rhode Island production, 2026-06-04.
  • Single-package GET returning Note and Item.Name verbatim, two packages at one Rhode Island production facility, 2026-07-25.
  • Rhode Island sandbox tag pool read during a packaging pre-flight, 2026-09-07.
  • SeedLink METRC field guide (docs/METRC.md), section Package Tags: adult-use vs medical.

SeedLink, "METRC package tags in Rhode Island: adult-use and medical share one list, and medical comes first", observed 2026-09-07, revised 2026-09-20, https://www.seedlink.net/guides/metrc/package-tags-adult-use-vs-medical

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/package-tags-adult-use-vs-medical/data.json

Related

  • 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
  • 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
  • METRC package adjustments in Rhode Island: Quantity is the new total, not a delta, and the adjustments log reports the difference
  • All metrc field guides for rhode island
  • Methodology: what SeedLink publishes and what it does not
SeedLink
GuidesMethodologyContactPrivacyTermsFor Rhode Island buyers
© 2026 SeedLink