Troubleshooting

Quick fixes for the most common problems. If something here doesn't match your symptom, every API response carries an x-request-id header — share it when you contact support and we can pull the exact log line.

The widget doesn't appear on my site

  1. Open your browser DevTools and look for a request to widget.customerhero.app/v1/loader.js. If it's blocked, your Content Security Policy is rejecting the script — see the CSP section in the Widget guide.
  2. Check the script tag has the right data-chatbot-id and a data-api-base that matches your org's region (US or EU).
  3. Confirm the chatbot is published — draft chatbots don't expose a widget.
  4. If the loader 200s but no bubble shows, look for ad blockers and tracking-prevention extensions. They occasionally block chat widgets even when CSP is fine.

The widget loads but every message fails

The most common cause is a mismatched data-api-base. An EU-region chatbot can only talk to eu.api.customerhero.app; sending requests to the US host returns 404. Copy the snippet straight from Chatbot → Embed — it always contains the right host.

A data source ingested but the bot doesn't know about it

  1. Open the data source detail page and confirm the Status is Ready, not Processing or Failed. Failed sources usually show the upstream error in the row.
  2. Look at the chunk count. If a 50-page PDF produced 0 chunks, the parser probably couldn't extract text (scanned PDFs without OCR are the typical culprit).
  3. Try the question in Chatbot → Test, then click any cited chunk to confirm retrieval is finding it. If no chunks are cited, lower minScore or raise topK in retrieval tuning.
  4. For URL sources, confirm the page is publicly fetchable. Login walls, geo-blocks, and aggressive bot protection (e.g. Cloudflare "I'm under attack") all cause empty ingestions.

The bot makes up answers

  • Switch the preset to Accurate. It instructs the model to refuse rather than improvise when retrieval comes back empty.
  • Add an explicit refusal rule to the system prompt: "If the answer isn't in the provided context, say you don't know and offer to connect a human."
  • Raise minScore in retrieval tuning so weak matches don't make it into context.
  • Check the analytics tab for low-confidence conversations — those are usually where the bot is improvising. Add Q&A data sources to fill the specific gaps.

Webhooks aren't being delivered

  1. Open Settings → Webhooks → Activity. It shows the response code and body for the last 1,000 deliveries — usually enough to see whether your endpoint returned 5xx or your firewall returned a TCP reset.
  2. Verify your endpoint completes within 10 seconds. Long handlers that block on database writes are the most common cause of timeouts.
  3. If signature verification is failing, check you're using the raw request body, not a re-serialized JSON object — a single whitespace difference breaks the HMAC.
  4. Use the Replay button on a failed delivery to retry without waiting for the automatic retry window.

API calls return 401 unexpectedly

  • Confirm the key hasn't been revoked. The audit log shows every revocation with the user who triggered it.
  • Check the host. A US-region key won't authenticate against eu.api.customerhero.app and vice versa.
  • Make sure the header is exactly Authorization: Bearer sk_live_… with a single space after Bearer. Some clients silently drop the header if it's malformed.

API calls return 403 unexpectedly

A 403 means you authenticated successfully but lack the role (admin vs agent) or scope (API key) for the operation. The response body's error field tells you exactly which scope is missing — add it to your key under Settings → API keys and try again. See the API keys & scopes guide for the full list.

API calls return 402

You hit a plan limit or ran out of credits. The response body includes a stable code field that tells you which limit. Resolve it under Settings → Billing — see Plans, limits & credits for the full list of codes.

Still stuck?

Send the x-request-id from the failing response to support and we can pull the exact log line — usually faster than guessing from symptoms.