Webhooks API

Webhooks allow you to receive real-time HTTP POST notifications when regulations change. This is an Enterprise tier feature ($499/mo).

POST /v1/webhooks

Register a new webhook subscription.

Request Body

FieldTypeRequiredDescription
endpoint_urlstringYesThe HTTPS URL to receive webhook payloads. Must use https://.
filtersobjectNoOptional filters to scope which events trigger this webhook.
filters.statesarrayNoArray of state codes (e.g., ["CO", "CA"]). If omitted, all states.
filters.substancesarrayNoArray of substance IDs. If omitted, all substances.
filters.product_typesarrayNoArray of product type IDs. If omitted, all product types.
filters.event_typesarrayNoArray of event types to subscribe to. If omitted, all events.
descriptionstringNoOptional description for this subscription.

Request Example

curl -X POST "https://api.hempdataapi.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint_url": "https://yourapp.com/webhooks/hempdata",
    "filters": {
      "states": ["CO", "CA", "TX", "FL", "NY"],
      "substances": ["delta-9-thc", "delta-8-thc"],
      "event_types": ["legal_status_changed", "new_regulation"]
    },
    "description": "Monitor THC regulation changes in key sales states"
  }'

Response Example

{
  "success": true,
  "data": {
    "id": "whk_a1b2c3d4e5f6",
    "endpoint_url": "https://yourapp.com/webhooks/hempdata",
    "filters": {
      "states": ["CO", "CA", "TX", "FL", "NY"],
      "substances": ["delta-9-thc", "delta-8-thc"],
      "event_types": ["legal_status_changed", "new_regulation"]
    },
    "description": "Monitor THC regulation changes in key sales states",
    "signing_secret": "whsec_live_k8J2mN4pQ7rT1vX3zA5cE8gI0lO2qU4wY6bD9fH",
    "status": "active",
    "created_at": "2026-03-18T10:00:00Z"
  },
  "meta": {
    "request_id": "req_whk_001"
  },
  "errors": []
}

Important: The signing_secret is only returned once, at creation time. Store it securely — you will need it to verify webhook signatures.


GET /v1/webhooks

List all webhook subscriptions for your account.

Request Example

curl -X GET "https://api.hempdataapi.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "success": true,
  "data": [
    {
      "id": "whk_a1b2c3d4e5f6",
      "endpoint_url": "https://yourapp.com/webhooks/hempdata",
      "filters": {
        "states": ["CO", "CA", "TX", "FL", "NY"],
        "substances": ["delta-9-thc", "delta-8-thc"],
        "event_types": ["legal_status_changed", "new_regulation"]
      },
      "description": "Monitor THC regulation changes in key sales states",
      "status": "active",
      "created_at": "2026-03-18T10:00:00Z",
      "last_triggered_at": "2026-03-18T14:30:00Z",
      "total_deliveries": 12,
      "failed_deliveries": 0
    }
  ],
  "meta": {
    "total": 1,
    "request_id": "req_whk_002"
  },
  "errors": []
}

DELETE /v1/webhooks/:id

Remove a webhook subscription.

Path Parameters

ParameterTypeDescription
idstringWebhook subscription ID (e.g., whk_a1b2c3d4e5f6)

Request Example

curl -X DELETE "https://api.hempdataapi.com/v1/webhooks/whk_a1b2c3d4e5f6" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "success": true,
  "data": {
    "id": "whk_a1b2c3d4e5f6",
    "deleted": true
  },
  "meta": {
    "request_id": "req_whk_003"
  },
  "errors": []
}

Webhook Payload Structure

When a matching event occurs, HempData sends an HTTP POST to your endpoint with this payload:

{
  "event_id": "evt_x1y2z3a4b5",
  "event_type": "legal_status_changed",
  "regulation_id": "reg_f1e2d3c4-5678-9012-abcd-ef3456789012",
  "jurisdiction": {
    "state": "TX",
    "state_name": "Texas"
  },
  "substance": "delta-8-thc",
  "product_type": "edibles",
  "before": {
    "legal_status": "legal_with_restrictions",
    "summary": "Delta-8 THC edibles permitted with labeling requirements.",
    "thc_limit": "No per-serving limit specified",
    "age_requirement": 21
  },
  "after": {
    "legal_status": "prohibited",
    "summary": "Delta-8 THC edibles prohibited following HB 1842 effective March 1, 2026.",
    "thc_limit": "N/A — prohibited",
    "age_requirement": null
  },
  "diff_summary": "legal_status: legal_with_restrictions -> prohibited; thc_limit: 'No per-serving limit specified' -> 'N/A — prohibited'",
  "plain_english_summary": "Texas has banned Delta-8 THC edibles effective March 1, 2026. If you sell these products in Texas, you must cease sales immediately.",
  "timestamp": "2026-03-01T06:15:00Z"
}

Payload Fields

FieldTypeDescription
event_idstringUnique event identifier
event_typestringType of change (see event types below)
regulation_idstringThe regulation that changed
jurisdictionobjectState code and name
substancestringAffected substance
product_typestringAffected product type
beforeobjectRegulation state before the change
afterobjectRegulation state after the change
diff_summarystringMachine-readable summary of changed fields
plain_english_summarystringHuman-readable explanation of the change and its business impact
timestampstringWhen the change was detected (ISO 8601)

Event Types

Event TypeDescription
legal_status_changedThe legal status changed (the most critical event)
details_updatedRegulatory details changed (limits, requirements, etc.)
new_regulationA new regulation entry was created
regulation_expiredA regulation reached its sunset date
bill_linkedA new pending bill was linked to a regulation
confidence_changedConfidence score changed significantly (>0.1 shift)

Signature Verification

Every webhook request includes an X-HempData-Signature header containing an HMAC-SHA256 signature. Always verify this signature before processing the payload.

How it Works

  1. HempData computes HMAC-SHA256(signing_secret, raw_request_body) and sends the hex-encoded result in the X-HempData-Signature header.
  2. Your server computes the same HMAC using the signing secret from webhook creation.
  3. Compare the two values using a constant-time comparison to prevent timing attacks.

Node.js Verification Example

const crypto = require('crypto');

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

// In your Express handler:
app.post('/webhooks/hempdata', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-hempdata-signature'];
  const isValid = verifyWebhookSignature(req.body, signature, process.env.HEMPDATA_WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  // Process the event...
  res.status(200).send('OK');
});

Python Verification Example

import hmac
import hashlib

def verify_webhook_signature(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode('utf-8'),
        raw_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Retry Schedule

If your endpoint returns a non-2xx status code or times out (30-second timeout), HempData retries with the following schedule:

AttemptDelay After Failure
11 minute
25 minutes
330 minutes
42 hours
512 hours
624 hours

After 6 failed attempts, the delivery is marked as failed. You can view failed deliveries in the dashboard and manually retry them.

If an endpoint accumulates 50 consecutive failed deliveries, the subscription is automatically paused. You will receive an email notification and can reactivate it from the dashboard after fixing the endpoint.


Best Practices

  1. Respond quickly — Return a 200 status code within 5 seconds. Process the payload asynchronously if needed.
  2. Verify signatures — Always validate the X-HempData-Signature header before trusting the payload.
  3. Handle duplicates — Use the event_id field to deduplicate, as retries may deliver the same event more than once.
  4. Use filters — Scope your subscriptions to only the states and substances you care about to reduce noise.
  5. Monitor health — Check the dashboard for failed deliveries and endpoint health.