Submit test results

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 - treat limit as "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, not 0.231.
  • Statuses are integer IDs: 1 passed, 2 failed, 3 completed, meaning the assay
    could neither pass nor fail.
  • input_units and report_units are required in info_fields for every category
    except general, and must come from that category's allowed units.
  • unit_weight is required whenever a unit field for the category is mg/unit, and
    ml_weight whenever one is mg/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.
  • footnote carries 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 are YYYY-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_field and error_category may
    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 - round rounds to digits decimal places, significant rounds to
    digits significant 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 - a 0/1 flag.

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

Allowed 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 drying
  • method: testing method, eg GC-FID or HPLC
  • metrc_mi_potency_value: optional value for the 'Potency' field in Metrc
  • metrc_mi_total_thc_status: DEPRECATED
  • metrc_mi_total_thc_value: DEPRECATED
  • metrc_mn_other_adc_value: value for the 'Other ADC (mg/g) Full Panel ' field in
    Metrc. value should be in mg/serving
  • metrc_mn_thc_purity_value: value for the 'THC Purity (% or mg/g)' field in Metrc
  • metrc_or_cbd_pct_rsd_value: Percent Relative Standard Deviation value for state
    traceability system
  • metrc_or_cbd_rpd_value: Relative Percent Difference value for state traceability
    system
  • metrc_or_d8_thc_pct_rsd_value: Percent Relative Standard Deviation value for state
    traceability system
  • metrc_or_d8_thc_rpd_value: Relative Percent Difference value for state traceability
    system
  • metrc_or_thc_pct_rsd_value: Percent Relative Standard Deviation value for state
    traceability system
  • metrc_or_thc_rpd_value: Relative Percent Difference value for state traceability
    system
  • ml_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 container
  • totalcbd_outsidelimitrange
  • totalthc_outsidelimitrange
  • unit_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 serving
  • wet_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

Allowed 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

Allowed 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

Allowed 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 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_metals_regulatornotes, metrc_mi_metals_status,
metrc_or_metals_regulatornotes, metrc_or_metals_status.

microbials

Allowed 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 drying
  • metrc_co_microbials_value: optional value for the 'Microbials' field in Metrc
  • metrc_mi_microbials_infused_bool: boolean true/false flag (0=false/1=true) to denote
    if the sample is an infused product
  • metrc_mi_microbials_value: optional value for the 'Microbials' field in Metrc
  • metrc_nv_microbials_value: value for the 'Microbials' field in Metrc
  • ml_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

Allowed 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 drying
  • reported_as_wet: optional flag for if numbers are reported including moisture weight
    (wet) or converted (dry)
  • wet_weight: weight of aliquot as received

nutrients

Allowed 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 drying
  • ml_weight: the weight in grams of 1ml of sample when any unit fields are 'mg/ml'
  • servings_per_container: Number of servings per container
  • 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 serving
  • wet_weight: weight of aliquot as received

mycotoxins

Allowed 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 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_mycotoxins_regulatornotes, metrc_mi_mycotoxins_status,
metrc_or_mycotoxins_regulatornotes, metrc_or_mycotoxins_status.

pesticides

Allowed 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 drying
  • metrc_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 Tebuconazole
  • metrc_co_pesticide_value: the total sum of all pesticides detected in ppm
  • metrc_mi_pesticides_chemical_residue_value: optional value for the 'Chemical
    Residue' field in Metrc
  • metrc_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 solution
  • wet_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

Allowed 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 drying
  • metrc_co_solvents_other_value: the sum of all residual solvent detections in ppm
    excluding Benzene, Butanes, Heptanes, Hexane, Toluene, and Total Xylenes
  • metrc_co_solvents_remediated_bool: boolean true/false flag (0=false/1=true) to
    denote if the sample is from a batch made from remediated product
  • metrc_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 enum
  • metrc_mi_solvents_residual_value: optional value for the 'Residual Solvents' field
    in Metrc
  • metrc_or_solvents_pct_rsd_value: value for the 'Solvents (RPD)' field in Metrc
  • metrc_or_solvents_rpd_value: Relative Percent Difference value for state
    traceability system
  • reported_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

Allowed 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 drying
  • ml_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 container
  • totalterpenes_outsidelimitrange
  • unit_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 serving
  • volume: volume of the aliquot in the solution
  • wet_weight: weight of aliquot as received

water_activity

Allowed 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

Allowed units: none. This category carries no numeric results.

Additional info fields:

  • amended: has the data been amended
  • amended_notes: optional notes detailing the amendment to the lab data
  • metrc_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
    enum
  • metrc_nv_subcontract_testing_value: DEPRECATED
  • metrc_ok_retest_all_value: value for the 'Retest (All)' field in Metrc
  • metrc_ok_subcontract_all_value: DEPRECATED
  • retest_id
  • retest_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.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Path Params
string
required
Form Data
boolean
Defaults to false

Publish the results, and any draft CoA and CoA additions, as soon as they are stored. Defaults to false, which leaves everything in draft.

string

Publication date to record when publish_data is true. Defaults to the time of the request.

string
required

The results, as a JSON-encoded object. See the description above for its structure and for the fields each category accepts.

Headers
string

HMAC-SHA256 request signature. Required only when request signing is enabled for your API key — see the Request Signing guide.

string

Unix timestamp (seconds) of the request, required only when request signing is enabled for your API key. Requests older than 30 seconds are rejected.

Responses

Language
Credentials
Header
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json