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"
}
| Field | Type | Required | Notes |
|---|---|---|---|
question | string | yes | 1–2000 chars |
jurisdiction | string | no | 2–4 char state/territory code (case-insensitive); narrows retrieval |
substance | string | no | exact 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
| Field | Type | Notes | |
|---|---|---|---|
data.answer | string | Cited, factual answer. Numbered citations refer to data.citations[i-1]. | |
data.citations[] | array | Up to 5 regulation summaries used to ground the answer. Always non-empty when confidence != "insufficient_context". | |
data.citations[].score | number | Cosine similarity, 0–1, from nomic-embed-text retrieval. | |
data.confidence | enum | "high" (top score ≥ 0.6) · "moderate" (0.4–0.6) · "insufficient_context" (< 0.4 or no hits) | |
data.model_used | enum \ | null | "local" (default · flint-default on Harrius) · "claude" (compliance pillar) · "minimax" (fallback) · null (insufficient_context) |
data.latency_ms | number | End-to-end embed + retrieve + generate. | |
data.disclaimer | string | Always 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
- Default → local
flint-default(free) - 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.
- 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
| Status | code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing/invalid body, question empty, or question > 2000 chars |
| 503 | EMBED_FAILED | Embedding service unreachable |
| 503 | RETRIEVAL_FAILED | Qdrant unreachable |
| 503 | GENERATION_FAILED | Local and MiniMax both failed on a non-compliance question |
| 503 | COMPLIANCE_TIER_FAILED | Claude 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_idround-trips to a real row in theregulationstable. 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.