POST /v1/regulations/ask

Natural-language Q&A over the HempData regulation corpus. Embeds the question, retrieves the top-5 relevant regulations from the hempdata_regs vector collection, then generates a cited answer through a three-tier model router.

Status: alpha · added in K2 (Local AI Foundation, Wave A)

Auth & rate limit

  • Requires a HempData API key (same Authorization: Bearer <key> or

X-API-Key header as the rest of /v1/regulations/*).

  • Subject to the standard per-key rate limit and monthly quota.

Request

POST /v1/regulations/ask
Content-Type: application/json
Authorization: Bearer hda_live_sk_...
{
  "question": "What is Kentucky's hemp THC limit?",
  "jurisdiction": "KY",
  "substance": "delta-9 THC"
}
FieldTypeRequiredNotes
questionstringyes1–2000 chars
jurisdictionstringno2–4 char state/territory code (case-insensitive); narrows retrieval
substancestringnoexact match (case-sensitive) against the seeded substance value

Response — 200 OK

{
  "success": true,
  "data": {
    "answer": "Kentucky follows the federal 0.3% dry-weight THC limit for hemp [1].",
    "citations": [
      {
        "regulation_id": "11111111-1111-1111-1111-111111111111",
        "jurisdiction": "KY",
        "jurisdiction_name": "Kentucky",
        "substance": "delta-9 THC",
        "product_type": "hemp",
        "legal_status": "legal",
        "last_verified": "2026-05-01T00:00:00.000Z",
        "source_urls": ["https://kda.ky.gov/hemp"],
        "score": 0.78
      }
    ],
    "confidence": "high",
    "model_used": "local",
    "latency_ms": 2202,
    "disclaimer": "This is informational regulatory data, not legal advice. Always consult a qualified attorney for legal decisions."
  },
  "meta": { "api_version": "v1" },
  "errors": null
}

Fields

FieldTypeNotes
data.answerstringCited, factual answer. Numbered citations refer to data.citations[i-1].
data.citations[]arrayUp to 5 regulation summaries used to ground the answer. Always non-empty when confidence != "insufficient_context".
data.citations[].scorenumberCosine similarity, 0–1, from nomic-embed-text retrieval.
data.confidenceenum"high" (top score ≥ 0.6) · "moderate" (0.4–0.6) · "insufficient_context" (< 0.4 or no hits)
data.model_usedenum \null"local" (default · flint-default on Harrius) · "claude" (compliance pillar) · "minimax" (fallback) · null (insufficient_context)
data.latency_msnumberEnd-to-end embed + retrieve + generate.
data.disclaimerstringAlways present on every successful response. The endpoint returns regulatory data, not legal advice. Callers rendering answers to end users must display this disclaimer alongside the answer.

Insufficient context

When the top retrieval score falls below 0.4 (or zero hits), the endpoint returns confidence: "insufficient_context", empty citations, and a suggestion to narrow the query. The model is not invoked in this branch — we'd rather refuse than fabricate.

Routing policy

  1. Default → local flint-default (free)
  2. Compliance pillar → Claude Opus. Triggered when the question or any

retrieved chunk mentions H.R. 5371 enforcement, an FTC warning/case/consent action, an FDA warning letter, or FTC docket C-4739. Regex lives in src/lib/local-ai.ts → compliancePillarRegex.

  1. MiniMax M2.7 → fallback only. Used when the local tier fails and

the question is not compliance-routed. Compliance-routed questions do not fall through — we'd rather 503 than answer compliance with a weaker model.

Error responses

StatuscodeWhen
400VALIDATION_ERRORMissing/invalid body, question empty, or question > 2000 chars
503EMBED_FAILEDEmbedding service unreachable
503RETRIEVAL_FAILEDQdrant unreachable
503GENERATION_FAILEDLocal and MiniMax both failed on a non-compliance question
503COMPLIANCE_TIER_FAILEDClaude tier failed on a compliance-pillar question (no fallback)

Citation policy

  • Citations are returned even when the model declines to answer — they show

what the retriever surfaced so the caller can audit.

  • regulation_id round-trips to a real row in the regulations table. Use

GET /v1/regulations?state=… with the citation's jurisdiction to fetch the full structured fields.

  • The answer must cite chunks by number (e.g. [1]). The prompt

forbids un-cited claims and forbids speculation about effective dates not present in the chunks.