Embeddable Compliance Widget

The HempData compliance widget lets you embed a real-time legal status badge on any website. It shows visitors whether a hemp product is legal in their state using color-coded indicators. Available on Professional and Enterprise tiers.

POST /v1/widget/check

Server-side compliance check endpoint. Use this if you want to build your own UI instead of using the embed script.

Request Body

FieldTypeRequiredDescription
substancestringYesSubstance identifier (e.g., delta-9-thc, cbd)
product_typestringYesProduct type (e.g., edibles, topicals)
statestringYesTwo-letter state code

Request Example

curl -X POST "https://api.hempdataapi.com/v1/widget/check" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "substance": "delta-9-thc",
    "product_type": "edibles",
    "state": "CO"
  }'

Response Example

{
  "success": true,
  "data": {
    "state": "CO",
    "state_name": "Colorado",
    "substance": "delta-9-thc",
    "product_type": "edibles",
    "legal_status": "legal_with_restrictions",
    "badge_color": "yellow",
    "headline": "Legal with Restrictions",
    "summary": "Delta-9 THC edibles are legal in Colorado for adults 21+ with licensed retail sale.",
    "restrictions": [
      "Must be 21 or older to purchase",
      "Maximum 10mg THC per serving",
      "Maximum 100mg THC per package",
      "Must be purchased from a licensed retailer"
    ],
    "age_gate_required": true,
    "minimum_age": 21,
    "confidence": 0.94,
    "last_verified": "2026-03-18T06:00:00Z",
    "regulation_id": "reg_a1b2c3d4-5678-9012-abcd-ef3456789012"
  },
  "meta": {
    "request_id": "req_widget_001"
  },
  "errors": []
}

Badge Colors

ColorCSS ClassMeaning
greenhd-badge--greenLegal — Product is fully legal in this state
yellowhd-badge--yellowRestricted — Legal with conditions (age, licensing, limits)
redhd-badge--redProhibited — Product is not legal in this state

Script Tag Embed

Add the widget to any page with a single <script> tag and a container element.

Basic Usage

<!-- Widget container -->
<div id="hempdata-widget"></div>

<!-- Widget script -->
<script
  src="https://cdn.hempdataapi.com/widget/v1/hempdata-widget.js"
  data-api-key="YOUR_PUBLIC_API_KEY"
  data-substance="delta-9-thc"
  data-product-type="edibles"
  data-state="CO"
></script>

With Auto-Detect State

Let the widget automatically detect the visitor's state via IP geolocation:

<div id="hempdata-widget"></div>

<script
  src="https://cdn.hempdataapi.com/widget/v1/hempdata-widget.js"
  data-api-key="YOUR_PUBLIC_API_KEY"
  data-substance="delta-9-thc"
  data-product-type="edibles"
  data-auto-detect-state="true"
></script>

Script Tag Attributes

AttributeRequiredDescription
data-api-keyYesYour public API key (different from your server API key; safe to expose in client-side code)
data-substanceYesSubstance to check (e.g., delta-9-thc, cbd)
data-product-typeYesProduct type to check (e.g., edibles, topicals)
data-stateNoTwo-letter state code. If omitted, use data-auto-detect-state.
data-auto-detect-stateNoSet to "true" to detect state via IP geolocation. Ignored if data-state is set.

Age Gate Modal

When a compliance check returns age_gate_required: true, the widget displays a modal asking the visitor to confirm their age before showing the product page.

Default Behavior

  1. Widget loads and performs the compliance check.
  2. If age_gate_required is true, an overlay modal appears asking: "Are you [minimum_age] or older?"
  3. If the visitor clicks Yes, the modal closes and the badge is displayed.
  4. If the visitor clicks No, they are shown a message that the product is not available to them.
  5. The age confirmation is stored in localStorage for 24 hours to avoid repeated prompts.

Customizing the Age Gate

<script
  src="https://cdn.hempdataapi.com/widget/v1/hempdata-widget.js"
  data-api-key="YOUR_PUBLIC_API_KEY"
  data-substance="delta-9-thc"
  data-product-type="edibles"
  data-auto-detect-state="true"
  data-age-gate-title="Age Verification Required"
  data-age-gate-message="You must be at least {age} years old to view this product."
  data-age-gate-confirm="I am {age} or older"
  data-age-gate-deny="I am under {age}"
  data-age-gate-denied-url="/age-restricted"
></script>

The {age} placeholder is replaced with the actual minimum age from the compliance check.


CSS Customization

The widget uses CSS custom properties (variables) for full visual customization. Override them on the #hempdata-widget container or globally.

All CSS Custom Properties

#hempdata-widget {
  /* Badge colors */
  --hd-green-bg: #16a34a;
  --hd-green-text: #ffffff;
  --hd-green-border: #15803d;

  --hd-yellow-bg: #eab308;
  --hd-yellow-text: #1a1a1a;
  --hd-yellow-border: #ca8a04;

  --hd-red-bg: #dc2626;
  --hd-red-text: #ffffff;
  --hd-red-border: #b91c1c;

  /* Badge layout */
  --hd-badge-padding: 12px 16px;
  --hd-badge-border-radius: 8px;
  --hd-badge-font-size: 14px;
  --hd-badge-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --hd-badge-font-weight: 600;
  --hd-badge-max-width: 400px;
  --hd-badge-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

  /* Badge icon */
  --hd-icon-size: 20px;
  --hd-icon-gap: 8px;

  /* Restrictions list */
  --hd-restrictions-font-size: 12px;
  --hd-restrictions-color: #555555;
  --hd-restrictions-margin-top: 8px;
  --hd-restrictions-line-height: 1.5;

  /* Confidence indicator */
  --hd-confidence-show: block; /* set to 'none' to hide */
  --hd-confidence-font-size: 11px;
  --hd-confidence-color: #888888;

  /* Last verified timestamp */
  --hd-verified-show: block; /* set to 'none' to hide */
  --hd-verified-font-size: 10px;
  --hd-verified-color: #aaaaaa;

  /* Age gate modal */
  --hd-modal-overlay-bg: rgba(0, 0, 0, 0.6);
  --hd-modal-bg: #ffffff;
  --hd-modal-text-color: #1a1a1a;
  --hd-modal-border-radius: 12px;
  --hd-modal-padding: 32px;
  --hd-modal-max-width: 480px;
  --hd-modal-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  --hd-modal-title-font-size: 20px;
  --hd-modal-message-font-size: 16px;
  --hd-modal-button-confirm-bg: #16a34a;
  --hd-modal-button-confirm-text: #ffffff;
  --hd-modal-button-deny-bg: #e5e7eb;
  --hd-modal-button-deny-text: #374151;
  --hd-modal-button-border-radius: 6px;
  --hd-modal-button-padding: 12px 24px;
  --hd-modal-button-font-size: 14px;

  /* Powered-by footer */
  --hd-footer-show: block; /* set to 'none' to hide on Enterprise tier */
  --hd-footer-font-size: 10px;
  --hd-footer-color: #cccccc;
}

Example: Dark Theme

#hempdata-widget {
  --hd-green-bg: #22c55e;
  --hd-green-text: #000000;
  --hd-yellow-bg: #facc15;
  --hd-yellow-text: #000000;
  --hd-red-bg: #ef4444;
  --hd-red-text: #000000;
  --hd-badge-shadow: 0 1px 3px rgba(255, 255, 255, 0.05);
  --hd-restrictions-color: #cccccc;
  --hd-confidence-color: #999999;
  --hd-verified-color: #777777;
  --hd-modal-bg: #1f2937;
  --hd-modal-text-color: #f3f4f6;
  --hd-modal-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}

Widget Events

The widget emits custom DOM events on the container element for integration with your application:

const widget = document.getElementById('hempdata-widget');

widget.addEventListener('hempdata:loaded', (e) => {
  console.log('Widget loaded:', e.detail);
  // e.detail.legal_status, e.detail.badge_color, etc.
});

widget.addEventListener('hempdata:age-confirmed', (e) => {
  console.log('User confirmed age:', e.detail.minimum_age);
});

widget.addEventListener('hempdata:age-denied', () => {
  console.log('User denied age requirement');
});

widget.addEventListener('hempdata:error', (e) => {
  console.error('Widget error:', e.detail.message);
});

Multiple Widgets on One Page

Use unique container IDs and the data-container attribute:

<div id="widget-edibles"></div>
<div id="widget-topicals"></div>

<script
  src="https://cdn.hempdataapi.com/widget/v1/hempdata-widget.js"
  data-api-key="YOUR_PUBLIC_API_KEY"
  data-container="widget-edibles"
  data-substance="delta-9-thc"
  data-product-type="edibles"
  data-auto-detect-state="true"
></script>

<script
  src="https://cdn.hempdataapi.com/widget/v1/hempdata-widget.js"
  data-api-key="YOUR_PUBLIC_API_KEY"
  data-container="widget-topicals"
  data-substance="cbd"
  data-product-type="topicals"
  data-auto-detect-state="true"
></script>