{"title":"METRC serves the lab COA PDF for free in Rhode Island: one GET returns the raw PDF, and whether a document exists is a per-lab fact","url":"https://www.seedlink.net/guides/metrc/free-coas","json":"https://www.seedlink.net/guides/metrc/free-coas/data.json","question":"Can I get a COA PDF from the METRC API without paying a lab portal?","answer":"Yes: every row of GET /labtests/v2/results carries a LabTestResultDocumentFileId, and GET /labtests/v2/labtestdocument/{id}?licenseNumber= returns that lab document as raw PDF bytes, but the lab populates the id, and on 2026-07-25 one Rhode Island lab had attached a document to 12 of 12 tested packages while a second had attached one to 0 of 36.","environment":"Rhode Island production and sandbox","observed":"2026-07-25","revised":"2026-09-20","published":"2026-09-20","facts":[{"id":"document_id_field","value":"LabTestResultDocumentFileId is present on every row GET /labtests/v2/results returns, and it is populated by the lab, not by METRC","observed":"2026-07-25","source":"GET /labtests/v2/results across the three Rhode Island production cultivators connected to SeedLink, read-only probe"},{"id":"document_content_type","value":"GET /labtests/v2/labtestdocument/{id}?licenseNumber= returns raw application/pdf bytes, not the JSON-wrapped base64 that GET /transfers/v2/manifest/{id}/pdf returns","observed":"2026-07-25","source":"One live document fetched at one Rhode Island production cultivator facility, read-only probe"},{"id":"live_document_bytes","value":"327,580 bytes, beginning with the %PDF- signature","observed":"2026-07-25","source":"The same live document, one Rhode Island production cultivator facility; the byte count is the only identifier this page keeps"},{"id":"coverage_first_lab","value":"Packages tested by the first lab carried a document on 12 of 12 (100%)","observed":"2026-07-25","source":"GET /labtests/v2/results across the three connected Rhode Island production cultivators, rows grouped by the testing lab"},{"id":"coverage_second_lab","value":"Packages tested by the second lab carried a document on 0 of 36 (0%)","observed":"2026-07-25","source":"GET /labtests/v2/results across the three connected Rhode Island production cultivators, rows grouped by the testing lab"},{"id":"coverage_by_cultivator","value":"Per cultivator, tested packages carrying a document: 10 of 10, 0 of 16 and 2 of 22","observed":"2026-07-25","source":"The same rows grouped by cultivator instead of by lab"},{"id":"labs_in_the_sample","value":"Two labs between them had tested every package in the sample, across three cultivators","observed":"2026-07-25","source":"The same rows, distinct testing labs counted"},{"id":"shared_document_id","value":"Two packages of one item both pointed at the same document id","observed":"2026-07-25","source":"GET /labtests/v2/results for two sibling packages at one Rhode Island production cultivator facility"},{"id":"discovery_cost","value":"No additional request is needed to learn a document id: the results call already runs once per tested item for potency, so the only added request is the document fetch, made only when a package lacks a document","observed":"2026-07-25","source":"SeedLink’s own COA sync path as recorded in docs/METRC.md § COAs come from METRC for free, dated by the probe in that section"},{"id":"unit_thc_percent_null","value":"Item.UnitThcPercent is null on Rhode Island, so potency exists only in GET /labtests/v2/results, fetched per item and fanned out to sibling packages","observed":"2026-07-25","source":"SeedLink sync against Rhode Island production, recorded in docs/METRC.md § Retry-After, which carries no date of its own; dated here to the 2026-07-25 probe of the same results call, the nearest dated read in the same document"},{"id":"item_level_propagation","value":"Lab results propagate at item level: when a lab records results on an IsTestingSample package, every sibling package sharing ItemFromFacilityLicenseNumber plus Item.Id moves to TestPassed together, across facilities","observed":"2026-07-01","source":"Rhode Island sandbox lab pipeline, recorded in docs/METRC.md § Lab Testing, first bullet; month-only in the record (July 2026), first of the month standing in, not an observation"},{"id":"sandbox_propagation_count","value":"Testing 24 lab-resident samples flipped all 160 cultivator-side packages in one pass","observed":"2026-07-01","source":"Rhode Island sandbox, the same lab-side run; month-only in the record (July 2026), first of the month standing in, not an observation"},{"id":"deleted_document_returns_hourly","value":"A METRC-sourced document the cultivator deleted reappears on the next hourly sync unless the integration also remembers the METRC document id","observed":"2026-07-25","source":"SeedLink’s COA remove handler against its hourly sync, as recorded in docs/METRC.md § COAs come from METRC for free (the ownership table and the migration that added the id column)"}],"constants":[{"value":64,"why":"base64, the name of the encoding in the Authorization header example and in the DocumentFileBase64 field of the lab’s write call"},{"value":48,"why":"the sum of the two labs’ tested packages, 12 and 36: a worked total, not a separate observation"}],"faq":[{"question":"Does METRC charge for the lab document?","answer":"The document comes back through the same API and the same credential the cultivator already syncs with, and there is no lab portal in the path. On 2026-07-25 one GET returned 327,580 bytes of PDF at a Rhode Island production facility. This page says nothing about any lab’s own fees."},{"question":"Why do some tested packages have no document?","answer":"Because LabTestResultDocumentFileId is populated by the lab, not by METRC. On 2026-07-25 one Rhode Island lab had attached a document to 12 of 12 tested packages and a second lab to 0 of 36. Whether the second lab attaches documents later, or by another route, was not observed."},{"question":"Is the document response JSON?","answer":"No. GET /labtests/v2/labtestdocument/{id} returns raw application/pdf bytes, unlike GET /transfers/v2/manifest/{id}/pdf, which wraps its PDF in JSON as base64. Read the body as bytes and check the leading %PDF-."},{"question":"Do I need to fetch a document for every package?","answer":"No. Lab results propagate at item level, and on 2026-07-25 two packages of one item pointed at the same document id. Fetch once per item and store the reference on every sibling package."},{"question":"Which permissions and parameters does the document call need?","answer":"Per the METRC API reference, licenseNumber is required and the permissions are View Packages and Manage Packages Inventory, the same two the results call needs. The id goes in the path."},{"question":"What if the cultivator already uploaded their own COA for the package?","answer":"Never touch it. A file on record with no METRC document id is the cultivator’s own upload, and the sync leaves it alone. Only a package with no file and no recorded id gets a pull."},{"question":"What if the cultivator deletes the COA that came from METRC?","answer":"Respect the deletion. That is why the METRC document id is recorded at pull time: with it, a package with no file but a recorded id is left alone, and without it the next hourly sync pulls the same document again and the delete looks broken."},{"question":"Can the same call give me potency?","answer":"Yes, and on Rhode Island it is the only place potency lives: Item.UnitThcPercent is null, so the numbers exist only in GET /labtests/v2/results. The sync already makes that call once per tested item, which is why discovering a document id costs no extra request."}],"sources":["GET /labtests/v2/results and GET /labtests/v2/labtestdocument/{id} across the three Rhode Island production cultivators connected to SeedLink, read-only, 2026-07-25.","One live lab document fetched at one Rhode Island production cultivator facility, 2026-07-25: byte count and leading bytes recorded.","Rhode Island sandbox lab pipeline run: 24 lab-resident samples tested, 160 cultivator-side packages promoted; recorded without a date in docs/METRC.md § Lab Testing.","SeedLink METRC field guide (docs/METRC.md): sections COAs come from METRC for free, Lab Testing (first bullet), and the Retry-After note on where potency lives.","METRC API reference as recorded in the SeedLink repository (metrc-api-info/metrc-api-reference.md): GET /labtests/v2/results, GET /labtests/v2/labtestdocument/{id} and PUT /labtests/v2/labtestdocument."],"citation":"SeedLink, \"METRC serves the lab COA PDF for free in Rhode Island: one GET returns the raw PDF, and whether a document exists is a per-lab fact\", observed 2026-07-25, revised 2026-09-20, https://www.seedlink.net/guides/metrc/free-coas","methodology":"https://www.seedlink.net/methodology","publisher":"SeedLink"}