GuidesMETRC field guides for Rhode Island
A METRC transfer template becomes a manifest only when a person dispatches it in METRC Connect: Rhode Island exposes no dispatch endpoint
On 2026-04-24, on the Rhode Island sandbox, POST /transfers/v2/templates/outgoing returned 200 with {Ids: [N]} and a template whose manifest number was T-prefixed (T-0000000001), and every write that might have dispatched it, POST /transfers/v2/outgoing and the /start, /submit and /dispatch verbs on the template, returned 404 or 405. Dispatch is a click on "Start" in METRC Connect, about 3 clicks in all when the template is staged first (sandbox, 2026-07-26). Only then does GET /transfers/v2/outgoing list a new transfer with its own Id, a plain-numeric manifest number and OriginatingTemplateId set to the template’s Id; that field is the one link between the plan and the shipment.
- Observed
- Revised
- Environment
- Rhode Island production and sandbox
What this page is
This page records how a transfer moves from an API-created template to a dispatched manifest on the Rhode Island METRC API, as SeedLink’s integration observed it, with the date and the call behind each statement, or a note where the record holds no date. It is not METRC documentation and it is not regulatory guidance: it describes what the endpoints returned to licensed Rhode Island cultivator credentials on the dates given.
The verbs that returned 404 and 405 are listed because an integrator reaches for them first and the documentation does not say they are absent. Field names, response shapes and the order of the steps are what this page is about; the counts on one delivery belong to that delivery on that day. Other states run their own METRC instances and can differ on every point below.
Nothing here mutates a transfer. SeedLink creates templates, reads what METRC Connect produced, and surfaces any difference to the cultivator. METRC is the legal record and the cultivator owns every correction to it.
How every number on this site is observed, dated and bounded is on the methodology page, which also lists what SeedLink does not publish.
The lifecycle, stage by stage
A wholesale shipment in Rhode Island passes through two METRC records, not one. The template is the plan; the outgoing transfer is the shipment. They have separate Ids from separate counters, manifest numbers of different shapes, and the only field that ties them together is OriginatingTemplateId on the transfer.
| Stage | Who acts | What the API shows | Observed |
|---|---|---|---|
| Template created | The integration, with POST /transfers/v2/templates/outgoing | A template with its own Id and a T-prefixed ManifestNumber; no PDF yet | 2026-04-24, sandbox |
| Dispatched | A person clicks "Start" in METRC Connect | A new row on GET /transfers/v2/outgoing with its own Id, a plain-numeric ManifestNumber and OriginatingTemplateId | 2026-04-24, sandbox |
| In transit | METRC Connect stamps the departure | ActualDepartureDateTime is set on the delivery | Reading rule; the stamp is a METRC Connect action |
| Received | The recipient accepts the manifest | ReceivedDateTime is set; the package appears on /packages/v2/transferred with its wholesale price | 2026-06-04, production |
| Rejected and returned | The recipient refuses a package; the shipper records the return leg | ShipmentPackageState walks Shipped, Rejected, Returned; RejectedPackagesReturned flips true | 2026-07-29, production |
Every action in the second column after the first row is a METRC Connect action. The API creates the plan and reads each later state; it never advances one.
Creating the template: what comes back, and what a template holds
POST /transfers/v2/templates/outgoing creates the template. On 2026-04-24 the Rhode Island sandbox answered 200 with {Ids: [N]}, and the id in that response was unreliable: SeedLink needed a follow-up GET /transfers/v2/templates/outgoing to find the template it had just created. That list gives each template its own Id and a ManifestNumber prefixed with T-, such as T-0000000001. There is no PDF at this stage; the manifest PDF endpoint takes the Id of the dispatched transfer, which does not exist yet.
A template carries no quantity. Read on 2026-09-03 on both the sandbox and production, each package on a template holds four fields and nothing about how much is inside.
| Field | What it holds |
|---|---|
PackageLabel | The tag of the package on the shipment |
WholesalePrice | A price for the package; no quantity field sits beside it |
GrossWeight | A gross weight for the package |
GrossUnitOfWeightName | The unit of that gross weight |
The manifest ships whatever the package holds. That is why there is no way to edit a quantity on a manifest, and why a quantity correction is made on the package instead; the section on the read-only transfer below shows what that looks like.
The template also names a transfer type, and the name is not free text. Probed from GET /transfers/v2/types on Rhode Island cultivator and lab licenses (the day of that probe is not in our record), a wholesale sale from a cultivator to a dispensary is an Unaffiliated Transfer, or an Affiliated Transfer when the two facilities share ownership. The bare name Transfer is refused with 400 and the message Transfer Type Name not specified.
| License class | Type names returned | Wholesale manifest possible |
|---|---|---|
| Cultivator | Affiliated Transfer, Beginning Inventory Transfer, Clone Transfer, External Hemp Transfer, External Transfer, Lab Transfer, Remediated Transfer, Unaffiliated Transfer; one cultivator license also listed Trade Sample | Yes: Unaffiliated Transfer, or Affiliated Transfer under common ownership |
| Lab | External Hemp Transfer, External Patient Testing, Lab Transfer | No: none of its types qualifies for an outgoing licensed shipment |
A lab credential therefore cannot create a wholesale manifest at all, and on 2026-07-26 a POST /transfers/v2/external/incoming from a lab license on the sandbox returned 401. Keep the credential that builds templates pointed at the cultivator license.
No endpoint dispatches a template
The template does not promote itself, and nothing in the API promotes it. The cultivator clicks "Start" in the METRC Connect web interface, which is the regulatory human-in-the-loop step standing for the physical loading of the truck. SeedLink probed every verb that might have stood in for that click, on two days, and none exists.
| Call | Status | Date |
|---|---|---|
POST /transfers/v2/outgoing | 405 | 2026-04-24 |
POST /transfers/v2/templates/outgoing/{id}/start | 404 | 2026-04-24 |
POST /transfers/v2/templates/outgoing/{id}/submit | 404 | 2026-04-24 |
POST /transfers/v2/templates/outgoing/{id}/dispatch | 404 | 2026-04-24 |
POST /transfers/v2/{id}/start | 404 | 2026-04-24 |
POST /transfers/v2/outgoing | 405, does not support http method 'POST' | 2026-07-26 |
/transfers/v2/ | 404 | 2026-07-26 |
/transfers/v2/external/outgoing | 404 | 2026-07-26 |
/transfers/v2/deliveries | 404 | 2026-07-26 |
/transfers/v2/templates/{id}/dispatch | 404 | 2026-07-26 |
/transfers/v2/templates/{id}/transfer | 404 | 2026-07-26 |
/transfers/v2/templates/outgoing/{id}/create | 404 | 2026-07-26 |
What the API does buy is a shorter click path. With the template staged first, the dispatch step in METRC Connect was about 3 clicks on 2026-07-26. The API’s contribution to dispatch is that the plan is already on the screen when the person gets there.
A template is not a shipment. An integration that marks an order as shipped when the template is created, or that treats an empty poll of GET /transfers/v2/outgoing as anything other than "not dispatched yet", is reporting a truck that has not left.
After dispatch: a second record with its own Id
When the person clicks "Start", METRC creates a real outgoing transfer. It has its own Id, a plain-numeric ManifestNumber (0000000817 on the sandbox on 2026-04-24, against the template’s T-0000000001), and OriginatingTemplateId set to the template’s Id. GET /transfers/v2/outgoing lists it. SeedLink matches on OriginatingTemplateId first and falls back to Name, because the template name it writes is unique per order.
The two Ids come from independent counters. A template Id and an outgoing-transfer Id can carry the same number and name unrelated records, which is harmless when reading lists and dangerous on the PDF endpoint, described in the next section.
The row on GET /transfers/v2/outgoing is thin. On 2026-06-04, on production, the rows read carried a null RecipientFacilityName; the recipient is on GET /transfers/v2/{id}/deliveries, and the packages that shipped are on GET /transfers/v2/deliveries/{deliveryId}/packages. After dispatch, that second list is the real shipped list, and it is the one to diff against whatever the integration recorded when it built the template.
The package set can differ from the template. Cultivators legitimately edit it while they are in METRC Connect: they swap a package, add a ride-along, or drop one that missed the van. SeedLink learned this on one order in June 2026, when the dispatched manifest carried a package set that differed from the template it had built, and the order went on describing the plan instead of the shipment until someone looked.
The posture on any difference is to surface it, never to mutate. METRC is the legal record, the cultivator owns the correction, and a wrong automatic fix to a shipping record is worse than a warning that gets dismissed. SeedLink shows the difference on the order and changes nothing in METRC.
The manifest PDF takes the transfer Id, and only with a license number
GET /transfers/v2/manifest/{id}/pdf returns the manifest. The {id} is the outgoing-transfer Id: not the template Id, and not the manifest number. It also requires ?licenseNumber=, which the documentation does not mention. Without it, on 2026-04-24, the sandbox returned 404 with the body No HTTP resource was found that matches the request URI /transfers/v2/manifest/N/pdf., a message that names the path and not the missing parameter.
The response is not a binary PDF. It is JSON with the file inside it as base64.
| Field | Value |
|---|---|
FileContents | The PDF, base64-encoded |
ContentType | application/octet-stream |
FileDownloadName | TransferManifestReport-N.pdf, N being the Id in the request |
The collision hazard follows from the independent counters. On 2026-04-24, GET /transfers/v2/manifest/1/pdf on the sandbox returned a pre-seeded demo manifest for an unrelated facility in another state, with no error, because the sandbox holds a demo transfer at that Id. An integration that passes its template Id to this endpoint gets a real PDF for somebody else’s shipment and no signal that anything is wrong. SeedLink refuses the PDF request while the manifest number it holds still starts with T- (its own 409, template_not_dispatched), so a template Id can never reach the endpoint.
A dispatched transfer is read-only, and the quantity lives on the package
Once dispatched, the transfer is read-only to the API, permanently. On 2026-09-03 SeedLink tried the writes on both the sandbox and production.
| Call | Status |
|---|---|
POST /transfers/v2/outgoing | 405 |
PUT /transfers/v2/outgoing | 405 |
PUT /transfers/v2/outgoing/packages | 404 |
| Adjusting, through the API, a package that is on a transfer | 400, Package <label> cannot be Adjusted because it is part of an existing Transfer. |
| The identical adjust call on a package with no transfer | 200 |
So the API cannot change what a dispatched manifest says, and it cannot change the package under it either. METRC Connect can. On 2026-09-02 one Rhode Island cultivator dispatched a manifest; on 2026-09-03, with the shipment in transit, they adjusted one of its packages in METRC Connect, and the transfer’s ShippedQuantity followed on its own, from 100 to 79. The manifest was never edited. The package was, and the manifest reports the package.
That is the rule to carry: you never edit a manifest, you adjust the package, and once the transfer is dispatched only a person in METRC Connect can do it. The template’s four per-package fields have no quantity for the same reason. The quantity is the package’s.
Reading the trip: departure, receipt, rejection and return
Every later state is written by METRC Connect and read by the integration. Two stamps on the delivery carry the trip: ActualDepartureDateTime set means the shipment is in transit, and ReceivedDateTime set means it was delivered. Dispatch and both stamps are METRC Connect actions.
A package the recipient refuses at the door walks three states, and the third is one METRC’s documentation does not show. On 2026-07-29, on production, one delivery’s ShipmentPackageState read Shipped, then Rejected at receipt, then Returned once the shipper recorded the return leg, at which point the delivery’s RejectedPackagesReturned flipped true.
| Field | Value on that delivery | What it says |
|---|---|---|
ShipmentPackageState | Shipped, then Rejected, then Returned | The refused package’s three states, in order |
RejectedPackagesReturned | true after the return leg | The shipper recorded the return |
ReceivedQuantity | null on the returned package | Nothing of it was received |
DeliveryPackageCount | 5 | Packages on the delivery |
DeliveryReceivedPackageCount | 4 | Packages the recipient accepted |
The returned package landed back on the shipper’s side as its own active package. An integration that treats every dispatched package as gone for good misses it.
/packages/v2/transferred is the other place a shipment shows up, and it lags. A just-dispatched package is absent from it until the recipient accepts the manifest, so departures are read from GET /transfers/v2/outgoing, where the transfer appears at dispatch. Once the recipient has accepted, /packages/v2/transferred carries the shipped package with ShipperWholesalePrice and ReceiverWholesalePrice, SourcePackageLabels and ManifestNumber, in a flat schema with no nested Item. On 2026-06-04, on production, the wholesale price per shipped package appeared there once the recipient had accepted.
Check it yourself with four read-only calls
The whole lifecycle is readable with GETs and no writes.
GET /transfers/v2/templates/outgoing?licenseNumber=<your license>
each template: Id, ManifestNumber starting with T-
GET /transfers/v2/outgoing?licenseNumber=<your license>
each dispatched transfer: Id, a plain-numeric ManifestNumber, OriginatingTemplateId
match OriginatingTemplateId to the template Id; RecipientFacilityName can be null here
GET /transfers/v2/{transferId}/deliveries?licenseNumber=<your license>
the recipient, ActualDepartureDateTime, ReceivedDateTime, RejectedPackagesReturned,
DeliveryPackageCount, DeliveryReceivedPackageCount
GET /transfers/v2/deliveries/{deliveryId}/packages?licenseNumber=<your license>
what shipped: PackageLabel, ShippedQuantity, ShipmentPackageState, ReceivedQuantityIf the transfer you are looking for is absent from the second call, it has not been dispatched, whatever the template says. If it is present, ActualDepartureDateTime is the stamp that says it left and ReceivedDateTime the stamp that says it arrived. And if the package list from the fourth call does not match the template you wrote, the list is right and the template is history.
Questions
- Is there an API call that dispatches a METRC transfer template?
- Not in Rhode Island.
POST /transfers/v2/outgoingreturns 405, and the/start,/submit,/dispatch,/transferand/createverbs on the template return 404 (sandbox, 2026-04-24 and 2026-07-26). A person clicks "Start" in METRC Connect; with the template staged, that was about 3 clicks. - Why does the dispatched transfer have a different Id from the template?
- Because it is a different record. METRC creates a new outgoing transfer at dispatch with its own Id from its own counter, a plain-numeric manifest number in place of the template’s T-prefixed one, and
OriginatingTemplateIdpointing back at the template. Match on that field, never on the Id. - Which Id does the manifest PDF endpoint take?
- The outgoing-transfer Id, with
?licenseNumber=. Not the template Id and not the manifest number. Passing a template Id can return a real PDF for an unrelated shipment with no error: on the sandbox, Id 1 returned a pre-seeded demo manifest from another state (2026-04-24). - Can I change a quantity on a dispatched manifest through the API?
- No.
POSTandPUT /transfers/v2/outgoingreturn 405,PUT /transfers/v2/outgoing/packagesreturns 404, and adjusting a package that is on a transfer returns 400 withPackage <label> cannot be Adjusted because it is part of an existing Transfer.(2026-09-03). A person can adjust the package in METRC Connect, and the manifest’sShippedQuantityfollows: one in-transit package went from 100 to 79 that way. - Why is a package I just dispatched missing from /packages/v2/transferred?
- That endpoint lags until the recipient accepts the manifest. Read departures from
GET /transfers/v2/outgoing, where the transfer appears at dispatch. Once accepted, the package appears on/packages/v2/transferredwith its wholesale price fields (production, 2026-06-04). - What does ShipmentPackageState Returned mean?
- A package the recipient refused and the shipper took back. It reads
Shipped, thenRejectedat receipt, thenReturnedonce the return leg is recorded, and the delivery’sRejectedPackagesReturnedflips true. The value is not in METRC’s documentation; it was read on production on 2026-07-29, and the package came back as an active package on the shipper’s side. - Why is RecipientFacilityName null on GET /transfers/v2/outgoing?
- On production on 2026-06-04 the rows read carried null there. The recipient is on
GET /transfers/v2/{id}/deliveries, and the shipped packages onGET /transfers/v2/deliveries/{deliveryId}/packages. Treat the outgoing row as an index, not a description. - Which transfer type name does a wholesale sale use?
Unaffiliated Transferfrom a cultivator to a dispensary with no common ownership, orAffiliated Transferunder common ownership. The bare nameTransferis refused with 400 andTransfer Type Name not specified.A lab license has no type that qualifies for an outgoing licensed shipment, so it cannot create a wholesale manifest.
Sources and how to cite this page
- Rhode Island sandbox transfer-lifecycle probes, 2026-04-24 and 2026-07-26: creating a template, reading it back, every dispatch verb, the manifest PDF endpoint (the SeedLink transfers module and its probe scripts).
- Rhode Island production reads of GET /transfers/v2/outgoing, its deliveries and delivery packages, 2026-06-04 and 2026-07-29, read-only.
- Rhode Island sandbox and production writes against a dispatched transfer and a transferred package, 2026-09-03, plus one cultivator’s adjustment in METRC Connect read back through the API the same day.
- SeedLink METRC field guide (docs/METRC.md), section Transfers & Manifests: transfer types, transfer lifecycle, manifest and order reconciliation, manifest PDF endpoint, transferred-package pricing, remediation transfers. The transfer-types probe and the June 2026 dispatch divergence are recorded there without a day.
SeedLink, "A METRC transfer template becomes a manifest only when a person dispatches it in METRC Connect: Rhode Island exposes no dispatch endpoint", observed 2026-09-03, revised 2026-09-20, https://www.seedlink.net/guides/metrc/transfer-template-to-manifest
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/transfer-template-to-manifest/data.json
Related
- 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
- 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
- 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
- All metrc field guides for rhode island
- Methodology: what SeedLink publishes and what it does not