---
title: "Check one product/substance in one state"
method: GET
path: "/v1/compliance/check"
tags: ["Compliance"]
---

# Check one product/substance in one state

`GET /v1/compliance/check`

## Request

- Base URL: `https://api.hempdata.io`
- URL: `https://api.hempdata.io/v1/compliance/check`
- Auth: HTTP bearer

Single state + substance + product type in, legal answer out — with a sources[] provenance chain and a verification block indicating which parts trace to canonical verified data.

## Query parameters

- `state` string, required
- `substance` string, required
- `product_type` string, required

## Response `200`

Compliance answer

- ApiResponseComplianceCheck
  - `success` boolean, required
  - `data` ComplianceCheckResult, required
    - `state` string, required: Two-letter jurisdiction code
    - `state_name` string, nullable
    - `substance` string, required
    - `product_type` string, required
    - `legal_status` 'legal' | 'legal_with_restrictions' | 'gray_area' | 'prohibited' | 'unknown', required: 'unknown' is returned only when no regulation row matches AND the substance is not one the canonical verdict names. When the canon settles the state + substance it answers (source: "canon"); when the canon is unsettled on it the answer is gray_area with the canon's own not-settled line.
    - `effective_status` string, nullable: Status after applying the federal H.R. 5371 timeline overlay
    - `summary` string, nullable
    - `confidence_score` number, nullable: 0..1 — always a JSON number, never a string
    - `last_verified` string, date-time, nullable
    - `thc_limit_pct_dryweight` number, nullable
    - `thc_limit_mg_per_serving` number, nullable
    - `thc_limit_mg_per_container` number, nullable
    - `age_restriction` number, nullable
    - `sources` ComplianceSource[], required
      - `type` 'federal_law' | 'federal_rule' | 'state_statute' | 'agency_rule' | 'case_law' | 'bill_pending' | 'fda_action' | 'carrier_policy', required
      - `citation` string, required
      - `publisher` string, required
      - `url` string, nullable
      - `retrieved_at` string, date-time, nullable
      - `license` string
      - `confidence` number, nullable
      - `attorney_reviewed` boolean
    - `verification` ComplianceVerification: How this answer traces to canonical, human-reviewed verified data. status=verified means the jurisdiction carries a canonical posture fact (statute-cited, primary-sourced). Treat unverified figures as orientation, not a compliance decision.
      - `status` 'verified' | 'unverified', required
      - `fact_id` string, nullable: Canonical fact id (matches docs/REGULATORY_FACTS.md heading)
      - `statute` string, nullable: Statute citation backing the jurisdiction's verified posture
      - `last_verified` string, nullable: ISO date of the most recent human verification against primary sources
      - `primary_sources` string[], required: Primary-source URLs grounding the fact
      - `thc_limit_source` 'verified' | 'db', required: verified = mg caps reconciled against the canonical verified state limits
      - `legal_status_source` 'canon_overlay' | 'db', required: canon_overlay = legal status raised by the canonical verdict / prohibition map; db = the stored value stands
    - `disclaimer` string, required
    - `attribution` string
    - `legal_status_source` 'canon_overlay' | 'db': canon_overlay = the canonical substance verdict raised the stored status (a row is never served less strict than canon); db = the stored value stands (not a claim of human review).
    - `prose_source` 'canon': Present when the narrative fields (plain_english / summary / summary_140_chars / summary_paragraph) were replaced by the canonical verdict line + verbatim rule basis + fact id, because the canonical verdict decided this row and the stored text contradicted it.
    - `source` 'canon': Present only on a row assembled at read time from HempData's verified facts because the regulations table has no row for this state + substance. Such a row has id null, is a substance-level verdict (product-form rules are not evaluated — see state_rule) and is never written to the table.
    - `canon_fact_id` string, nullable: The verified fact id behind a canon verdict / canon prose.
    - `canon_verdict` string: The verdict line /v1/answer prints for this state + substance (canon rows only).
    - `canon_scope` 'substance_level': Canon rows answer for the substance; product-form rules are in state_rule, not evaluated.
    - `state_rule` string, nullable: The state's verified fact (canonical phrasing), verbatim.
    - `canon_form_note` string: Set when a product-form rule in the state's fact (e.g. beverage-specific limits) is not evaluated by a substance-level canon row; the row is then served 'restricted', never 'legal'.
    - `canon_verdict_source` 'canon' | 'fallback_map' | 'unsettled': How the canonical verdict reached the status on a canon row: canon = a verified fact settles it; fallback_map = HempData's audited prohibition review; unsettled = the canon declines to settle it (served gray_area — not permission).
  - `meta` object, nullable
  - `errors` unknown

## Other responses

- `400`: Per-field validation error
- `401`: Missing or invalid API key
- `429`: Rate limit or monthly quota exceeded

---

[API](https://skmtc.dev/hempdata/apis/hempdata-api.md) · [All operations](https://skmtc.dev/hempdata/apis/hempdata-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hempdata/apis/hempdata-api/revisions/2c2946badd40?raw)
