Every error HempData returns comes with a stable code and a doc_url that deep-links to the matching row below. Handle codes, not messages — messages may be tuned; codes are contracts.
{
"success": false,
"data": null,
"meta": { "request_id": "req_...", "api_version": "v1" },
"errors": [
{
"code": "MONTHLY_QUOTA_EXCEEDED",
"message": "You've used all 10 product checks on the free tier this month.",
"doc_url": "https://api.hempdata.io/errors#error-MONTHLY_QUOTA_EXCEEDED"
}
]
}| Code | HTTP | What it means | How to recover | |
|---|---|---|---|---|
ENDPOINT_UNREACHABLE |
400 | We could not reach your webhook endpoint URL. | Verify the URL, DNS, and that the server accepts HTTPS POSTs from the public internet. | # |
ENDPOINT_VALIDATION_FAILED |
400 | The webhook-subscription test event to your endpoint returned a non-2xx. | Ensure your endpoint returns HTTP 200-299 for the test event. Log the request body to debug. | # |
HTTPS_REQUIRED |
400 | Webhook endpoints must use HTTPS. | Expose your endpoint over HTTPS (terminate TLS at your load balancer or use a tunnel such as ngrok for local development). | # |
INVALID_KEY_TYPE |
400 | An endpoint requiring a publishable key received a secret key (or vice-versa). | Use `hda_*_pk_*` for client-side widgets and `hda_*_sk_*` for server-side calls. | # |
INVALID_SIGNATURE |
400 | A webhook signature failed verification against the shared secret. | Check your webhook signing secret. Re-fetch it from the sender dashboard if you rotated it. | # |
INVALID_TIER |
400 | Billing checkout was requested with an unknown tier name. | Use one of: retailer, brand, enterprise. See hempdata.io/pricing. | # |
INVALID_URL |
400 | The provided `endpoint_url` is not a valid URL. | Send a fully-qualified HTTPS URL (include scheme + host). | # |
MISSING_ENDPOINT |
400 | Webhook subscription request did not include `endpoint_url`. | Send `endpoint_url` as a public HTTPS URL in the body. | # |
MISSING_FIELDS |
400 | Required fields are missing from the request body. | Re-read the reference for that endpoint and include every field marked required. | # |
MISSING_SIGNATURE |
400 | A webhook was received without the required signature header. | Send `Stripe-Signature` (or the documented signature header) with every webhook. Only HempData-originated webhooks should hit this endpoint. | # |
STATE_REQUIRED |
400 | The widget could not auto-detect a state and none was provided. | Pass `state` explicitly, or enable auto-detect with a verified origin. | # |
VALIDATION_ERROR |
400 | The request body or query parameters failed validation. | Inspect the `message` field for the specific path that failed, fix the field, and retry. | # |
DEMO_KEY_INVALID |
401 | The presented demo key is not the active playground demo key. | Only the published `hd_demo_public_*` key works. Sign up for a real key for your own app. | # |
MISSING_ADMIN_KEY |
401 | An `/ops/*` endpoint was called without the required admin shared secret. | Send `X-Admin-Key: <secret>`. `/ops/*` is for HempData operators only. | # |
UNAUTHORIZED |
401 | The API key is missing, malformed, or does not match any active key on file. | Send a valid key as `Authorization: Bearer hda_live_sk_...`. Generate or rotate a key at hempdata.io/dashboard. | # |
DEMO_ORIGIN_DENIED |
403 | A playground demo key was presented from an origin not on the allow-list. | Only the hempdata.io and api.hempdata.io playgrounds may use demo keys. Use your own key elsewhere. | # |
DEMO_PATH_DENIED |
403 | A playground demo key was used on a path demo keys are not authorized for. | Demo keys work only on a curated subset of read endpoints. Use your own key to access everything else. | # |
FORBIDDEN |
403 | The key is valid but the subscriber or key is deactivated, or the caller lacks access to the requested resource. | Reactivate the key in the dashboard, or contact support@hempdata.io if you expect access. | # |
NOT_FOUND |
404 | The endpoint, resource, or record you asked for does not exist. | Double-check the path and any IDs. Browse the /reference page for the current surface. | # |
ALREADY_EXISTS |
409 | A record with the given identifier (most often email) already exists. | Fetch the existing record or use a different identifier. For subscribers, log in instead of re-registering. | # |
DEMO_RATE_LIMITED |
429 | The public playground demo key exceeded its per-hour or per-day cap. | Sign up for a free account at hempdata.io/signup — your own key gets a real monthly quota. | # |
MONTHLY_QUOTA_EXCEEDED |
429 | You hit the monthly product-check or state-lookup cap for your tier. | Wait until the 1st of next month, or upgrade at hempdata.io/pricing. `resets_at` is in the error body. | # |
RATE_LIMITED |
429 | You exceeded the per-minute request limit for your tier. | Back off exponentially (start 1s, cap 60s) and honor `Retry-After`. Upgrade at hempdata.io/pricing for a higher limit. | # |
DEMO_MISCONFIGURED |
500 | The playground demo key is not configured on the server. | Contact support@hempdata.io — this is a server-side misconfiguration, not your request. | # |
HANDLER_ERROR |
500 | A webhook handler or internal function threw an uncaught error. | Retry the webhook per your sender’s retry policy. Send the `request_id` to support for investigation. | # |
INTERNAL_ERROR |
500 | An unhandled server error occurred. | Retry with exponential backoff. Send the `request_id` from the response to support@hempdata.io for investigation. | # |
PRICE_NOT_FOUND |
500 | No Stripe price exists for the requested tier + billing period. | Contact support@hempdata.io. Most often resolved by picking a different billing_period. | # |
PRODUCT_NOT_FOUND |
500 | The Stripe product catalogue is not configured on the server. | Contact support@hempdata.io — server-side setup issue. | # |
DEMO_DISABLED |
503 | The public playground is temporarily disabled on the server. | Retry later, or sign up for a real account — authenticated traffic is unaffected. | # |
DEMO_GLOBAL_CAPACITY |
503 | The playground demo hit its global hourly cap across all anonymous callers. | Try again in an hour, or sign up for a free account for your own capacity. | # |
DEMO_RATE_LIMIT_UNAVAILABLE |
503 | Demo rate-limiting depends on Redis; Redis is unreachable. | Retry in a moment. Authenticated callers with their own key are unaffected. | # |
OPS_DISABLED |
503 | The admin ops surface is disabled on this server. | Contact HempData. The public API is unaffected. | # |
SERVICE_UNAVAILABLE |
503 | A backing service (database or Redis) is temporarily unreachable. | Retry with exponential backoff. Check /status for live health. Contact support if it persists >5 min. | # |
Missing a code? Send the request_id from the error envelope to support@hempdata.io and we will document it.