Submit test results for a sample. The payload surface is deliberately large so
that it can describe any assay, but you only need to send what was actually
tested - never include compounds that were not tested.
Results may be submitted while the sample's order is in any valid status, but
every result is stored as a DRAFT and stays invisible to the client until the
sample is published or its order moves to the completed stage. Set
publish_data to true to publish the results, together with any draft CoA and
CoA additions, as soon as they are submitted.
Each request replaces all previous test result data for the sample, so always
submit the complete set of results in one call.
Request payload
test_results is a single JSON-encoded object. Build it with every tested
category, then serialize it to a string and send it as the test_results form
field.
{
"categories": {
"cannabinoids": {
"info_fields": {
"input_units": "%",
"report_units": "%",
"date_tested": "2026-08-14",
"status": 1
},
"compounds": [
{"name": "thca", "value": "21.34", "lod": "0.01", "loq": "0.03"},
{"name": "d9_thc", "value": "0.68", "lod": "0.01", "loq": "0.03"}
]
}
}
}Any compound returned by GET /compounds may be listed, within its own
category. Setting "skip_coa": true alongside categories submits the data
without generating a CoA.
Compound object
name and value are required; every other key is optional metadata, reported
in the same units as value unless noted otherwise.
name- compound key for what was tested.value- the test result, as a string, e.g."1.02".lod- limit of detection.loq- limit of quantitation.limit- value above which this test fails.limitrangelow/limitrangehigh- bounds when the value is restricted to a range.max- upper limit of quantitation.stdev- standard deviation of the sample replicate results, between 0 and 1.rsd- relative standard deviation of the analyte values.rpd- relative percent difference of the analyte values.spike- spike recovery for the analyte.purity_percent- purity percentage for the analyte.qualifiers- testing qualifiers, where the regulator defines them.regulatornotes- notes posted to state traceability systems such as METRC, BioTrack
or Leaf.option_limit_greater_than_or_equal- treatlimitas "greater than or equal to"
rather than "greater than".
General rules
- All test values are numeric but must be submitted as strings, so that JSON
encoding and decoding cannot lose precision. Sending bare numbers will likely produce
inaccurate data. - Percentages are numbers between 0 and 100: report 23.1% as
23.1, not0.231. - Statuses are integer IDs:
1passed,2failed,3completed, meaning the assay
could neither pass nor fail. input_unitsandreport_unitsare required ininfo_fieldsfor every category
exceptgeneral, and must come from that category's allowed units.unit_weightis required whenever a unit field for the category ismg/unit, and
ml_weightwhenever one ismg/ml. Both drive mass-to-mass unit conversions, so a
conversion that needs one and does not get it fails. When testing a cookie, send the
weight of a whole cookie; when testing a liquid, send the weight of one millilitre.footnotecarries anything that should accompany the assay on the CoA - the
definition of total THC and total CBD, dry weight versus wet weight, or other
extraordinary QC data.
Error codes
A failed submission returns 400 with an error_code, plus error_field and
error_category where they apply.
invalid_sample_id- no sample found with the requested id.invalid_order_status- the sample's order cannot accept test results.unknown_compound- an unknown compound was submitted.duplicate_compound- a compound was given twice.conversion_error- a result value could not be converted.missing_required_field- a required field is missing.invalid_field- a field or category had the wrong type, or the category is unknown.invalid_date- an invalid date was given; dates areYYYY-MM-DD.suspicious_date- a date much older than expected (before 2012) was given.invalid_status- an invalid value was given for a status field.invalid_unit- a category was reported in an unsupported unit.invalid_data- any other validation failure;error_fieldanderror_categorymay
be absent.
Info fields
Shared info fields
Every assay category below accepts these. The general category accepts only
footnote, notes, notes_2 through notes_10, signatory_name,
signatory_title and signature from this list.
analytical_batch_id/analytical_batch_id_2- optional analytical batch IDs for QC
samples.date_prepared- date the sample was prepared for this assay.date_tested- date the sample was tested for this assay.digits- number of digits to display on the certificate of analysis; see
digits_method.digits_method-roundrounds todigitsdecimal places,significantrounds to
digitssignificant figures.footnote- footnote to accompany this assay.input_units- units the data is being submitted in, from the category's allowed
units.report_units- the primary units displayed on the certificate of analysis.secondary_report_units- the secondary units displayed on the certificate of
analysis.notes,notes_2...notes_10- optional testing notes for this assay.signatory_name/signatory_title- lab employee to appear on the certificate of
analysis.signature- URL of the signature image for the report.status- pass or fail integer ID from the status enum.
QC sample IDs
Every category except nutrients and general also accepts these optional QC
sample identifiers: qc_sample_id, qc_sample_dup_id, qc_sample_trip_id,
qc_blank_id, qc_blank_dup_id, qc_blank_trip_id, qc_lcs_id,
qc_lcs_dup_id, qc_lcs_trip_id, qc_spike_id, qc_spike_dup_id,
qc_spike_trip_id and qc_control_study_id.
Regulator passthrough fields
Categories carry extra metrc_* info fields that feed state traceability
systems. Their suffix determines what they hold:
_status- pass or fail integer ID from the status enum._regulatornotes- notes posted to the state traceability system, for example METRC
or BioTrack._value- an explicit value for the named field in the state system._bool- a0/1flag.
Only send the fields for the regulator the lab reports to.
Categories
Each category below lists its allowed units, the defaults applied when a field
is omitted, and the info fields it accepts on top of the shared ones. The API
also accepts alkaloids, dna, endotoxins, flavonoids, miscellaneous,
peptides, ph and shelflife, which follow the same structure but have no
published option set.
cannabinoids
cannabinoidsAllowed units: %, mg/container, mg/g, mg/ml, mg/serving, mg/unit, ppb,
ppm
Defaults: input_units = %, report_units = %, digits = 2, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
container_description: Description of container (eg. bottle, box, tin)dry_weight: weight of aliquot after dryingmethod: testing method, eg GC-FID or HPLCmetrc_mi_potency_value: optional value for the 'Potency' field in Metrcmetrc_mi_total_thc_status: DEPRECATEDmetrc_mi_total_thc_value: DEPRECATEDmetrc_mn_other_adc_value: value for the 'Other ADC (mg/g) Full Panel ' field in
Metrc. value should be in mg/servingmetrc_mn_thc_purity_value: value for the 'THC Purity (% or mg/g)' field in Metrcmetrc_or_cbd_pct_rsd_value: Percent Relative Standard Deviation value for state
traceability systemmetrc_or_cbd_rpd_value: Relative Percent Difference value for state traceability
systemmetrc_or_d8_thc_pct_rsd_value: Percent Relative Standard Deviation value for state
traceability systemmetrc_or_d8_thc_rpd_value: Relative Percent Difference value for state traceability
systemmetrc_or_thc_pct_rsd_value: Percent Relative Standard Deviation value for state
traceability systemmetrc_or_thc_rpd_value: Relative Percent Difference value for state traceability
systemml_weight: the weight in grams of 1ml of sample when any unit fields are 'mg/ml'reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)servings_per_container: Number of servings per containertotalcbd_outsidelimitrangetotalthc_outsidelimitrangeunit_description: definition of one unit when any unit fields are 'mg/unit'unit_weight: the weight in grams of the whole unit submitted for sampling when any
unit fields are 'mg/unit'units_per_serving: Number of units per servingwet_weight: weight of aliquot as received
Regulator passthrough fields, following the suffix conventions above:
metrc_co_d9_thc_status, metrc_me_total_thc_mg_package_status,
metrc_me_total_thc_mg_serving_status, metrc_mi_potency_regulatornotes,
metrc_mi_potency_status, metrc_mi_total_cbd_regulatornotes,
metrc_mi_total_thc_regulatornotes, metrc_mn_other_adc_regulatornotes,
metrc_mn_other_adc_status, metrc_mn_thc_purity_regulatornotes,
metrc_mn_thc_purity_status, metrc_mn_total_cannabinoids_regulatornotes,
metrc_mn_total_cannabinoids_status, metrc_mn_total_cbd_regulatornotes,
metrc_mn_total_cbd_status, metrc_mn_total_thc_regulatornotes,
metrc_mn_total_thc_status, metrc_mt_total_cbd_regulatornotes,
metrc_mt_total_cbd_status, metrc_mt_total_thc_regulatornotes,
metrc_mt_total_thc_status, metrc_oh_total_cbd_regulatornotes,
metrc_oh_total_cbd_status, metrc_oh_total_thc_regulatornotes,
metrc_oh_total_thc_status, metrc_or_cbd_pct_rsd_regulatornotes,
metrc_or_cbd_pct_rsd_status, metrc_or_cbd_rpd_regulatornotes,
metrc_or_cbd_rpd_status, metrc_or_d8_thc_pct_rsd_regulatornotes,
metrc_or_d8_thc_pct_rsd_status, metrc_or_d8_thc_rpd_regulatornotes,
metrc_or_d8_thc_rpd_status, metrc_or_potency_control_study_regulatornotes,
metrc_or_potency_control_study_status,
metrc_or_potency_process_validation_regulatornotes,
metrc_or_potency_process_validation_status, metrc_or_potency_regulatornotes,
metrc_or_potency_status, metrc_or_thc_pct_rsd_regulatornotes,
metrc_or_thc_pct_rsd_status, metrc_or_thc_rpd_regulatornotes,
metrc_or_thc_rpd_status, metrc_or_total_cbd_regulatornotes,
metrc_or_total_thc_regulatornotes, metrc_or_total_thc_status.
foreign_matter
foreign_matterAllowed units: %, mg/lb
Defaults: input_units = %, report_units = %, digits = 2, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
metrc_mi_foreign_organic_matter_value: value for the 'Foreign organic matter' field
in Metrc.reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)
Regulator passthrough fields, following the suffix conventions above:
metrc_mi_foreign_organic_matter_regulatornotes,
metrc_nv_visual_inspection_regulatornotes.
homogeneity
homogeneityAllowed units: %, mg/unit
Defaults: input_units = %, report_units = %, digits = 0, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)unit_weight: the weight in grams of the whole unit submitted for sampling when any
unit fields are 'mg/unit'
metals
metalsAllowed units: mg/g, ppb, ppm
Defaults: input_units = ppb, report_units = ppb, digits = 0, digits_method
= round
Accepts the shared QC sample-ID fields.
Additional info fields:
metrc_mi_metals_value: optional value for the 'Metals' field in Metrcreported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)
Regulator passthrough fields, following the suffix conventions above:
metrc_mi_metals_regulatornotes, metrc_mi_metals_status,
metrc_or_metals_regulatornotes, metrc_or_metals_status.
microbials
microbialsAllowed units: cfu, cfu/g, cfu/m^3, cfu/ml, cfu/plate, cq, mpn/g
Defaults: input_units = cfu/g, report_units = cfu/g, digits = 0,
digits_method = round
Accepts the shared QC sample-ID fields.
Additional info fields:
dry_weight: weight of aliquot after dryingmetrc_co_microbials_value: optional value for the 'Microbials' field in Metrcmetrc_mi_microbials_infused_bool: boolean true/false flag (0=false/1=true) to denote
if the sample is an infused productmetrc_mi_microbials_value: optional value for the 'Microbials' field in Metrcmetrc_nv_microbials_value: value for the 'Microbials' field in Metrcml_weight: the weight in grams of 1ml of sample when any unit fields are 'mg/ml'reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)unit_weight: the weight in grams of the whole unit submitted for sampling when any
unit fields are 'mg/unit'wet_weight: weight of aliquot as received
Regulator passthrough fields, following the suffix conventions above:
metrc_co_microbials_regulatornotes, metrc_co_microbials_status,
metrc_mi_microbials_regulatornotes, metrc_mi_microbials_status,
metrc_nv_microbials_regulatornotes, metrc_nv_microbials_status,
metrc_or_microbials_regulatornotes, metrc_or_microbials_status,
metrc_or_microbiological_process_validation_regulatornotes,
metrc_or_microbiological_process_validation_status.
moisture
moistureAllowed units: %
Defaults: input_units = %, report_units = %, digits = 1, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
dry_weight: weight of aliquot after dryingreported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)wet_weight: weight of aliquot as received
nutrients
nutrientsAllowed units: %, mg/container, mg/g, mg/ml, mg/serving, mg/unit, ppb,
ppm
Defaults: input_units = ppm, report_units = ppm, digits = 2, digits_method
= round
Additional info fields:
dry_weight: weight of aliquot after dryingml_weight: the weight in grams of 1ml of sample when any unit fields are 'mg/ml'servings_per_container: Number of servings per containerunit_weight: the weight in grams of the whole unit submitted for sampling when any
unit fields are 'mg/unit'units_per_serving: Number of units per servingwet_weight: weight of aliquot as received
mycotoxins
mycotoxinsAllowed units: mg/g, ppb, ppm
Defaults: input_units = ppb, report_units = ppb, digits = 2, digits_method
= round
Accepts the shared QC sample-ID fields.
Additional info fields:
metrc_mi_mycotoxins_value: optional value for the 'Mycotoxins' field in Metrcreported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)
Regulator passthrough fields, following the suffix conventions above:
metrc_mi_mycotoxins_regulatornotes, metrc_mi_mycotoxins_status,
metrc_or_mycotoxins_regulatornotes, metrc_or_mycotoxins_status.
pesticides
pesticidesAllowed units: mg/g, ppb, ppm
Defaults: input_units = ppm, report_units = ppm, digits = 3, digits_method
= round
Accepts the shared QC sample-ID fields.
Additional info fields:
dry_weight: weight of aliquot after dryingmetrc_co_other_pesticide_value: the sum of all pesticide detections in ppm excluding
Abamectin, Azoxystrobin, Bifenazate, Etoxazole, Imazalil, Imidacloprid, Malathion,
Myclobutanil, Permethrin, Spinosad, Spiromesifen, Spirotetramat, and Tebuconazolemetrc_co_pesticide_value: the total sum of all pesticides detected in ppmmetrc_mi_pesticides_chemical_residue_value: optional value for the 'Chemical
Residue' field in Metrcmetrc_or_limited_batch_pesticide_testing_regulatornotes: DEPRECATED: notes to be
posted to state traceability systems (e.g. METRC or BioTrack)reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)volume: volume of the aliquot in the solutionwet_weight: weight of aliquot as received
Regulator passthrough fields, following the suffix conventions above:
metrc_co_other_pesticide_regulatornotes, metrc_co_other_pesticide_status,
metrc_co_pesticide_regulatornotes, metrc_co_pesticide_status,
metrc_mi_pesticides_chemical_residue_regulatornotes,
metrc_mi_pesticides_chemical_residue_status,
metrc_or_pesticides_control_study_regulatornotes,
metrc_or_pesticides_control_study_status,
metrc_or_pesticides_process_validation_regulatornotes,
metrc_or_pesticides_process_validation_status, metrc_or_pesticides_regulatornotes,
metrc_or_pesticides_status.
solvents
solventsAllowed units: %, mg/g, ppb, ppm
Defaults: input_units = ppm, report_units = ppm, digits = 3, digits_method
= round
Accepts the shared QC sample-ID fields.
Additional info fields:
dry_weight: weight of aliquot after dryingmetrc_co_solvents_other_value: the sum of all residual solvent detections in ppm
excluding Benzene, Butanes, Heptanes, Hexane, Toluene, and Total Xylenesmetrc_co_solvents_remediated_bool: boolean true/false flag (0=false/1=true) to
denote if the sample is from a batch made from remediated productmetrc_co_solvents_residual_regulatornotes: DEPRECATED: notes to be posted to state
traceability systems (e.g. METRC or BioTrack)metrc_co_solvents_residual_status: DEPRECATED: pass or fail integer ID from the
status enummetrc_mi_solvents_residual_value: optional value for the 'Residual Solvents' field
in Metrcmetrc_or_solvents_pct_rsd_value: value for the 'Solvents (RPD)' field in Metrcmetrc_or_solvents_rpd_value: Relative Percent Difference value for state
traceability systemreported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)wet_weight: weight of aliquot as received
Regulator passthrough fields, following the suffix conventions above:
metrc_co_solvents_other_regulatornotes, metrc_co_solvents_other_status,
metrc_mi_solvents_residual_regulatornotes, metrc_mi_solvents_residual_status,
metrc_or_solvents_control_study_regulatornotes,
metrc_or_solvents_control_study_status, metrc_or_solvents_pct_rsd_regulatornotes,
metrc_or_solvents_pct_rsd_status,
metrc_or_solvents_process_validation_regulatornotes,
metrc_or_solvents_process_validation_status, metrc_or_solvents_regulatornotes,
metrc_or_solvents_rpd_regulatornotes, metrc_or_solvents_rpd_status,
metrc_or_solvents_status.
terpenes
terpenesAllowed units: %, mg/container, mg/g, mg/ml, mg/serving, mg/unit, ppb,
ppm
Defaults: input_units = %, report_units = %, digits = 2, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
container_description: Description of container (eg. bottle, box, tin)dry_weight: weight of aliquot after dryingml_weight: the weight in grams of 1ml of sample when any unit fields are 'mg/ml'reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)servings_per_container: Number of servings per containertotalterpenes_outsidelimitrangeunit_description: definition of one unit when any unit fields are 'mg/unit'unit_weight: the weight in grams of the whole unit submitted for sampling when any
unit fields are 'mg/unit'units_per_serving: Number of units per servingvolume: volume of the aliquot in the solutionwet_weight: weight of aliquot as received
water_activity
water_activityAllowed units: aw
Defaults: input_units = aw, report_units = aw, digits = 5, digits_method =
round
Accepts the shared QC sample-ID fields.
Additional info fields:
reported_as_wet: optional flag for if numbers are reported including moisture weight
(wet) or converted (dry)
general
generalAllowed units: none. This category carries no numeric results.
Additional info fields:
amended: has the data been amendedamended_notes: optional notes detailing the amendment to the lab datametrc_co_contaminants_regulatornotes: DEPRECATED: notes to be posted to state
traceability systems (e.g. METRC or BioTrack)metrc_co_contaminants_status: DEPRECATED: pass or fail integer ID from the status
enummetrc_nv_subcontract_testing_value: DEPRECATEDmetrc_ok_retest_all_value: value for the 'Retest (All)' field in Metrcmetrc_ok_subcontract_all_value: DEPRECATEDretest_idretest_sample_id
Regulator passthrough fields, following the suffix conventions above:
metrc_or_r_and_d_test_regulatornotes, metrc_or_subcontracted_test_regulatornotes,
metrc_or_tic_regulatornotes.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||