Lab Testing¶
These endpoints are for testing labs. Only a license whose facility type is a testing laboratory can see the Lab Samples grid or record results, and Metrc offers them in Maine and Missouri. To read results as a grower or processor, use GET /v2/packages/labresults?packageId= instead.
| Endpoint | What it does |
|---|---|
GET /v2/packages/lab-samples | One row per recorded test on each sample the lab holds |
GET /v2/packages/labresults/record/inputs | The test types the lab can record, and what each requires |
GET /v2/packages/labresults/record/source-packages | Packages Metrc will record results for |
POST /v2/packages/labresults/document/file | Store a result PDF (Missouri) |
POST /v2/packages/labresults/record | Record results for sample packages |
GET /v2/packages/labresults/document/history?labTestResultId= | The documents uploaded for one result |
Recording and uploading are dry runs by default. Add submit=true to write to Metrc.
Recording results¶
Each result names a test type from the inputs endpoint. A test type whose requiresTestResult is true also needs a quantity.
import requests
API = "https://api.trackandtrace.tools"
HEADERS = {"Authorization": f"Bearer {ACCESS_TOKEN}"}
PARAMS = {"licenseNumber": "LAB00001"}
test_types = requests.get(
f"{API}/v2/packages/labresults/record/inputs", params=PARAMS, headers=HEADERS
).json()["labTestTypes"]
thc = next(t for t in test_types if t["name"].startswith("THC"))
requests.post(
f"{API}/v2/packages/labresults/record",
params={**PARAMS, "submit": "true"},
json=[
{
"packageId": 12345,
"resultDate": "2026-10-23",
"results": [{"labTestTypeId": thc["id"], "quantity": 21.5, "passed": True}],
}
],
headers=HEADERS,
)
Record a result for every test in the lab test batches the sample requires. Once recorded, the sample and the package it was cut from both read TestPassed or TestFailed in labTestingStateName. Tests that are informational only, such as Missouri's "R&D/Voluntary Testing" batches, leave both reading NotSubmitted.
Attaching a document (Missouri)¶
Upload the PDF first, then send the documentFileId it answers with alongside the results.
with open("coa.pdf", "rb") as pdf:
document_file_id = requests.post(
f"{API}/v2/packages/labresults/document/file",
params={**PARAMS, "submit": "true"},
files={"file": ("coa.pdf", pdf, "application/pdf")},
headers=HEADERS,
).json()["documentFileId"]
Each result in GET /v2/packages/labresults?packageId= carries a labTestResultId. Pass it to the document history endpoint to list every document uploaded for that result, then download one with GET /v2/packages/labresults/document?packageId=&labTestResultDocumentFileId=, using the history row's documentFileId.