Webhook API for LIMS Systems
Important
The Webhook API provides a different type of authentication and doesn’t require a LIMS system to implement OAuth2 as described in Authentication.
Overview
By working with Test Labs to receive digital versions of COAs, Lucid Green can unlock significant benefit, optimization, and accuracy to Brand Compliance and Manufacturing teams when approving and integrating lab certified COA test result data into regulatory labeling on products.
At a high level, this integration would enable Brands that are customers of Lucid Green and utilize an integrated LIMS to configure their LIMS account with a Lucid Green provided webhook (for explanation of this technology, see https://sendgrid.com/blog/whats-webhook/) URL. Once configured, whenever a COA is added to that Brand’s state-specific LIMS account, the LIMS would deliver that COA using a JSON format payload containing all data contained in the COA to the configured webhook URL.
This type of integration is very light-weight for LIMS providers to implement, and has the added benefit of ensuring that the Brand is in control of turning this feature on and off within their own LIMS account. Additionally, Lucid Green would work with the integrated LIMS to define the JSON format for the COA payload, or would be able to consume a pre-existing JSON payload that a LIMS provider has already developed. Either way, Lucid Green is responsible for processing and interpreting the JSON payload data and filling out the appropriate internal data structures, which the LIMS provider wouldn’t need to worry about.
Configuring LIMS System for COA Delivery to Lucid Green
The first step of the integration is for the LIMS system to enable a Brand to configure their LIMS account with a Lucid Green provided webhook URL. This URL is unique to that Brand (to ensure that a LIMS that is hosting multiple Lucid Green integrations can differentiate COA json payload delivery by Brand), and may be unique to a Lab.
The webhook URL should have a structure similar to:
https://app.lucidgreen.io/api/<version>/lims/<lims-integration-key>/
Example LucidSource Testing Environment Webhook URL
https://source-test.lucidgreen.io/api/v1.4/lims/YYVRTaTVsLWugmz95HPoDt/
Example LucidSource Production Environment Webhook URL
https://source.lucidgreen.io/api/v1.4/lims/YYVRTaTVsLWugmz95HPoDt/
Authenticated by sending the following header:
Header
Authorization: Token <token>
The body should be a JSON document as described below.
COA Data Structure
The COA json payload should contain the following information:
data version (LIMS versioning in case data structure needs to change to add/remove/modify JSON format)
data source (LIMS name and identifier, so Lucid Green can identify which data format translator to use when interpreting JSON payload)
unique LIMS COA identifier (to differentiate different COA records, or identify when a redelivery of an already delivered COA occurs)
brand name, identifiers
test lab name, identifiers, signatory information, address, licenses
batch information and identifiers
tested sample information (including weight, format, type, strain, etc.)
receipt and test dates in UTC timezone
tests run
pdf format COA download url
compound test results, split by terpenes and cannabinoids, also including moisture, pesticides, solvents, microbials, mycotoxins, water activity, foreign matter, metals, homogeneity (all as appropriate given tests executed, null or not present if test not run)
compound results should be broken down into name, value, units, digits of significance, limit allowed, LoD/LoQ, and any notes added by test lab
The exact format of the JSON payload will be agreed upon in advance, and Lucid Green can easily accept pre-existing JSON payload formats that may already have been developed by the LIMS.
Compound/Analyte Values
When reporting the testing result for a specific compound or analyte, the following structure can be used.
{
"name": "cbd",
"value": "1.234567",
"unit": "%",
"limit": "5",
"lod": "0.1234567",
"loq": "0.1234567",
"percent_value": "1.234567",
"value_per_serving": "2.3456",
"unit_per_serving": "mg"
}
Field Definitions
- name:
the standard name for the compound / analyte or test used. This name must remain the same for that specific test across all submitted COAs. Lucid Green will map the provided name to our internal representation for that compound / analyte / test |
- value:
the decimal value of the result. If the result is reported as either ND or <LOQ or <LOD, then please use those strings as the value (i.e.
"value": "<LOQ")- unit:
the units for the value is reported. This should be one of
%,mg/g,µg/g,ppm,ppb,g,mg,lbs,oz,l,ml,aw,ph,cfu/g. If value is ND or <LOQ or <LOD, then unit should be left blank.- limit
lod
loq: the decimal value for the various limits for the test performed. Include only those limits that are relevant and appropriate (i.e. don’t report
0or""forloqifloqisn’t relevant for a given result; in that case don’t include a key forloqin the JSON structure at all).- percent_value:
the conversion of the reported value and unit into a percentage measurement. This is important especially for values reported in units that are not concentrations. If value is reported in
%units, this field can be left out.- value_per_serving
unit_per_serving: the conversion of the reported value and unit into the amount per serving, if known. Units are the same as the unit field above. These fields are optional but strongly recommended.
COA Webhook Delivery
Upon creation of a COA in a LIMS for a Brand that has configured Lucid Green integration via webhook, the LIMS system should (as soon as possible within the LIMS system) generate the JSON payload and perform an HTTPS POST of the JSON payload to the configured webhook.
There are a few possible outcomes of this action that the LIMS system should handle, (almost) all of which should provide an HTTP response code:
Response Codes
- NO CONNECTION:
If the url is for some reason not able to be connected to (such as a network outage on either Lucid Green’s or the LIMS side). LIMS should retry to send immediately, then fail and retry a little later (1-3 hours later)
- SUCCESS:
200or201response code. No further action as JSON payload has been successfully received.- REDIRECT:
301or302. LIMS system should follow redirect and post to redirect URL.- NOT ALLOWED:
400or other400-series response code. LIMS should fail the webhook and not retry.- GENERAL ERROR:
500-series response code. There’s a temporary issue that Lucid Green is experiencing. LIMS should fail current sending but retry a little later (1-3 hours later)
Re-sending a COA
As a convenience to Brands, and to enable backloading of data, the LIMS system should provide a button or other setting on each COA record in the Brand-facing UI to trigger sending of a COA via webhook to Lucid Green. This should enable a Brand to send certain historical COAs to Lucid Green (as enabled by the data available in the LIMS), and should also allow a Brand to re-send already sent COAs to Lucid Green if either the LIMS provider or Lucid Green need to refresh data provided to Lucid Green.
Integration Timeline and Workflow
To fully implement the LIMS Webhook API and allow a Testing Laboratory to deliver COA data for Brands to LucidSource, the following workflow should be followed:
LIMS Provider reviews documentation
Lucid Green sets up shared Slack channel for engineering teams to coordinate
LIMS Provider sends example structured data / COA content in the form that is expected to be sent via the LIMS Webhook API
LIMS Provider implements LIMS Webhook API integration (est. time 1-2 weeks)
Simultaneous to (4), Lucid Green implements a translator to convert LIMS Provider structured data into Lucid Source format (est. time 1-2 weeks)
Lucid Green provides testing environment LIMS
Authorization Tokenwith a few testable LIMSIntegration KeysLIMS Provider and Lucid Green test integration in testing environment to validate LIMS Webhook API usage and translator functionality (est. time 1 day)
Lucid Green certifies LIMS integration and provides production environment LIMS
Authorization Token
Example JSON Payload
An example JSON payload is provided below. It should be taken as guidance, and should be used to work through the process of developing an official JSON payload with Lucid Green that includes all tests and their corresponding analytes.
{
"id": "ABC123",
"brand": {
"id": "ABC123",
"name": "ABC123"
},
"lab": {
"id": "ABC123",
"name": "ABC123"
},
"coa_pdf_download_link": "https://path-to-certificate/ABC123.pdf",
"status": "Complete",
"last_modified": "2020-01-01T01:01:01.000000Z",
"sample": {
"id": "ABC123",
"regulator_id": "ABC123",
"batch_id": "ABC123",
"batch_regulator_id": "ABC123",
"produced_on": "2020-01-01T01:01:01.000000Z",
"received_on": "2020-01-01T01:01:01.000000Z",
"tested_on": "2020-01-01T01:01:01.000000Z",
"reported_on": "2020-01-01T01:01:01.000000Z",
"strain": "Brand Strain",
"type": "Chocolate",
"package_size": {
"value": 10.1,
"unit": "g"
},
"serving_size": {
"value": 8.3,
"unit": "g"
},
"serving_per_package": 1.2
},
"tests_performed": [
{
"name": "Microbials",
"status": "pass"
},
{
"name": "Pesticides",
"status": "pass"
}
],
"notes": "Lorem ipsum...",
"results": {
"tested_on": "2020-01-01T01:01:01.000000Z",
"reported_on": "2020-01-01T01:01:01.000000Z",
"signatory": {
"name": "John Doe",
"title": "Title"
},
"cannabinoids": {
"status": "pass",
"tested_on": "2020-01-01T01:01:01.000000Z",
"compounds": [
{
"name": "cbd",
"value": "1.234567",
"unit": "%",
"limit": "5",
"lod": "0.1234567",
"loq": "0.1234567",
"percent_value": "1.234567",
"value_per_serving": "2.3456",
"unit_per_serving": "mg"
},
{
"name": "total_thc",
"value": "1.234567",
"unit": "%",
"limit": "5",
"lod": "0.1234567",
"loq": "0.1234567",
"percent_value": "1.234567",
"value_per_serving": "2.3456",
"unit_per_serving": "mg"
}
]
},
"terpenes": {
"status": "pass",
"tested_on": "2020-01-01T01:01:01.000000Z",
"compounds": [
{
"name": "limonene",
"value": "0.1234567",
"unit": "mg/g",
"limit": "0.8000",
"lod": "0.1234567",
"loq": "0.1234567",
"percent_value": "1.234567",
"value_per_serving": "2.3456",
"unit_per_serving": "mg"
}
]
},
"moisture": {},
"pesticides": {},
"solvents": {},
"microbials": {},
"mycotoxins": {},
"water_activity": {},
"foreign_matter": {},
"homogeneity": {},
"metals": {}
}
}