# Troubleshooting

> How to fix the three common Whisperr setup problems, which are no events in the dashboard, no message drafts yet, and users who got no message.

This page covers the three places where a new install most often stalls. Each section starts with what to check first.

- [Events are not arriving](#events-are-not-arriving)
- [No drafts yet](#no-drafts-yet)
- [Why was nobody messaged?](#why-was-nobody-messaged)

## Events are not arriving

### Check the key

| What you see                             | Cause                                                       | Fix                                                     |
| ---------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------- |
| `401 missing_api_key`                    | The request has no key.                                     | Pass the key to the SDK, or send it in `X-API-Key`.     |
| `401 invalid_api_key`                    | The key is wrong or was revoked.                            | Copy a current key from **Settings → API keys**.        |
| `403 contact_change_requires_server_key` | An App key tried to change a user’s existing email address. | Send that change from your backend with the Server key. |

Use the **App** key (`wpk_…`) in web and mobile apps, and the **Server** key (`wrk_…`) in server SDKs. See [API keys](/guides/api-keys/).

When an SDK gets a `401` or `403`, it stops sending and keeps its queue. Retries do not help until the key is fixed.

Billing events sent with the App key are stored as events, but Whisperr does not use them as billing facts. Send payments and cancellations from your backend with the Server key, or connect [RevenueCat](/integrations/revenuecat/), [Superwall](/integrations/superwall/) or [Adapty](/integrations/adapty/).

### Check the endpoint

The SDKs send to `https://api.whisperr.net` by default. If you set a custom base URL, for example a proxy, it must forward `/v1/events/batch` and `/v1/identify` unchanged. A wrong path gets `404 route_not_implemented`.

A `400` means the request is malformed, and the SDK drops it. The error `message` names the field, for example `event_type must be snake_case`. See [What does an error look like?](/api/overview/#what-does-an-error-look-like)

### Check that the SDK flushed

The SDKs batch events. The Web and Node.js SDKs send when 20 events are queued or every 10 seconds, whichever comes first.

- **Browser:** the Web SDK also sends when the page is hidden or closed. Events that did not get through stay queued and go out on the next load.
- **Server:** the Node.js queue lives in memory. In a script, a serverless function or a job that exits right away, call `await whisperr.flush()` before you return, or `await whisperr.shutdown()` before the process exits.

Each SDK page lists its own options and methods. Start from [Which SDK do I use?](/#sdks)

### Check that you call identify

Events sent before `identify` arrive under an anonymous id. Whisperr stores them, but it does not act on an anonymous visitor: it cannot reach them, and anonymous devices do not count as users. Call `identify` with your own user id as soon as the user signs in. Whisperr then moves the visitor’s earlier events to that user.

Server SDKs pass the user id on every call. Use the same id that your app passes to `identify`, so that both land on one timeline.

### See what arrived in the dashboard

A `202` answer means Whisperr stored the request. It processes it right after, normally within seconds. See [Accepted, then processed](/api/delivery/#accepted-then-processed).

Open **Data** in the dashboard:

- Until the first event arrives, the **Overview** tab shows “Waiting for your first event”.
- After that, each source shows when its last event arrived, or “Never sent”.
- **Missing** lists events that Whisperr expects and has not seen yet.
- **Not used** lists what Whisperr received but did not use: rejected requests and events, bot traffic, removed personal data and unknown event names.

Before your trial starts, the Data page shows which sources and events arrived. The list of single events and the rejected requests open when the trial starts. Until then, read the HTTP status or the SDK’s error callback.

## No drafts yet

The **Messages** page shows **No drafts yet** until Whisperr writes its first draft. These must be true first:

1. **Your code is connected.** Events arrive from an SDK, or a coding agent or the Whisperr GitHub App registered your events.
2. **Your plan is ready and your trial is on.** Whisperr builds your plan from your registered events. The setup step is **Review your plan and start your trial**. Whisperr writes no drafts before the trial starts. See [Pricing and trial](/guides/pricing-and-trial/).
3. **A user matches an intervention.** Whisperr writes a draft when an identified user matches one of your interventions, after an event or a scheduled check. The **Interventions** page lists them.

The Messages page opens only after the first two steps are done. Until then it shows “Opens after setup” and the steps that are still open. The same steps are on the **Home** page.

Users in the holdout group never get a draft. See [Holdout group](#holdout-group).

## Why was nobody messaged?

Whisperr decides for each user whether to send anything at all. Many users get nothing on purpose. To see why a user got no message, open **Messages**, then **Record**. Every decision about a message shows there with its outcome and its reason. Filter by **Outcome** and **Reason**.

| Outcome    | Meaning                                                                    |
| ---------- | -------------------------------------------------------------------------- |
| Would send | Whisperr wrote the message. It waits for your approval, or sending is off. |
| Sent       | The message went out through your provider.                                |
| Held       | Whisperr waited. It may send later.                                        |
| Skipped    | Whisperr did not send, for a reason in the next column.                    |
| Failed     | Sending failed.                                                            |
| Declined   | You declined the draft.                                                    |
| Not needed | The user did the thing on their own first.                                 |

The reasons below are the ones a new workspace meets most often. The dashboard shows the same sentences.

### Approval mode

New workspaces start in **You approve each**: “Each message waits here until you approve it.” Nothing goes out until you select **Approve** on the message in **Messages**. The queue shows these messages as **To approve**.

**Approve** works only once messages can go out: a push or email provider is connected and sending is on. The sending control on the Messages page shows the first thing that stops sending, for example “Connect email or push to send.”

The option **Sends on its own** shows “We turn this on with you.” You cannot switch a new workspace to sending without approval yourself.

If **Pause all messages** is on, the reason is “You paused sending to customers.” Whisperr keeps writing drafts while sending is paused.

### Quiet hours

Reason: “Quiet hours for this person.”

Whisperr does not send during quiet hours in each person’s own time. A new workspace uses 21:00 to 08:00. The message is held, not dropped, and goes out after quiet hours end. Change the window in **Settings → Message rules**, under **When people get messages**. The rules open when your trial starts.

Whisperr reads the person’s time zone from the `timezone` trait. The client SDKs send it from the device. Without it, Whisperr uses UTC, so a server-only install should send `timezone` in `traits`. See [Identify users](/api/identify/).

### Holdout group

Reason: “In the comparison group. We never message them.”

Whisperr keeps a share of users in a holdout group and never messages them. Comparing them with the users who got messages is how the **Impact** page shows what the messages changed. Each user stays in the same group. A workspace in **Drafts only** holds nobody out.

### No consent or no way to reach the user

| Reason                                        | Fix                                                                                                  |
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| ”Has not agreed to get these messages.”       | Whisperr has no opt-in for the channel. See [Contact consent](/concepts/consent/).                   |
| ”Opted out of this channel.”                  | The user opted out. See [Contact consent](/concepts/consent/) for who can opt them in again.         |
| ”No device or address can reach this person.” | No push token and no email address. Send the address or token with `identify`.                       |
| ”No address for this channel.”                | The user has no address for the chosen channel.                                                      |
| ”Turned off notifications on their phone.”    | The user denied push permission.                                                                     |
| ”We don’t know who this person is yet.”       | The user was never identified. See [Check that you call identify](#check-that-you-call-identify).    |
| ”No provider is connected for this channel.”  | Connect a [push](/integrations/push-providers/) or [email](/integrations/email-providers/) provider. |
| ”Verify your email sender to send.”           | Finish the sender check for your [email provider](/integrations/email-providers/).                   |

### Deliberate decisions

These reasons mean Whisperr chose not to send, to protect the user and your channel:

| Reason                                             | Meaning                                                         |
| -------------------------------------------------- | --------------------------------------------------------------- |
| ”Got a message recently, so we waited.”            | The user got a message a short time ago.                        |
| ”Reached the message limit for this period.”       | The user reached a limit on messages per channel or per period. |
| ”Getting many messages, so we held back.”          | The user got many messages, so Whisperr spaces them out.        |
| ”Another message for this person was more useful.” | Two interventions matched, and the other one went first.        |
| ”They did it on their own. No message needed.”     | The user did what the message was for before it went out.       |
| ”Waited too long, so we dropped it.”               | The draft waited past its time limit.                           |

### Plan and limits

| Reason                             | Fix                                                                                                                     |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| ”Your plan needs attention.”       | No trial or paid plan is on, or a payment failed. Open **Settings → Plan**.                                             |
| ”Your limit of people is reached.” | The **People limit** you set on the Messages page is reached. Raise or clear it in the sending control, under **More**. |

A user with no row in the record had no decision about a message in that period: no intervention matched them.

## Common questions

### Why do my events not show up in Whisperr?

Check the key first: a request without a key gets 401 missing_api_key, and a wrong or revoked key gets 401 invalid_api_key. Then check that the SDK flushed its queue: the Web and Node SDKs send after 20 events or every 10 seconds, and a short-lived script must call flush() before it exits.

### Why does Whisperr write no message drafts?

Whisperr writes drafts only after your plan is ready and your trial or paid plan is on. Then it writes a draft when a user matches an intervention. The Messages page lists the setup steps that are still open.

### Why did Whisperr not message a user?

Open Messages, then Record. Every decision about a message shows there with its outcome (Would send, Sent, Held, Skipped, Failed, Declined or Not needed) and the reason in one sentence, such as Quiet hours for this person.

### Does Whisperr send messages without my approval?

Not in a new workspace. New workspaces start in You approve each: every message waits on the Messages page until you approve it.

Source: https://docs.whisperr.net/guides/troubleshooting/
