# Webhooks not arriving

Find out why a project or form webhook isn't reaching your app, from a filtered or paused endpoint to a failing signature check, and fix each cause.

When a webhook doesn't reach your app, the endpoint's delivery log usually says why. Webhooks are on Premium and Business, and the workspace owner and the project's Admins can see them.

These are the webhooks that send your testimonials to your own app. If a Smart Invites webhook from your store isn't inviting customers, see [Smart Invites webhook not inviting customers](/help/troubleshooting/invite-webhook-not-inviting-customers).

## Check this first

Open the delivery log: open the project, click the gear icon (**Project Settings**) next to its name at the bottom of the sidebar, choose the **Developer** tab, then **Webhooks**. Click **Logs** on the endpoint. A form's webhook is listed there too, named **Form:** and the form's name.

Find the event you expected, by its **Event** and when it was **Created**, and read its **Status**:

| What you see                     | Go to                                                                                                                  |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| No delivery for the event at all | [If nothing was sent](#if-nothing-was-sent)                                                                            |
| **PENDING**                      | [If deliveries stay pending](#if-deliveries-stay-pending)                                                              |
| **FAILED**                       | [If deliveries fail](#if-deliveries-fail)                                                                              |
| **CANCELED**                     | Click **View**: **Cancel reason** says why, such as a new signing secret or URL. Click **Replay** to send it again.    |
| **SUCCEEDED**                    | Your endpoint answered with a 2xx status code, so the request arrived. Check your app's or automation tool's own logs. |

Click **View** on any delivery to open **Delivery details**: the payload, the URL it went to, the **Last error**, and your endpoint's response.

To check that your endpoint can be reached at all, click **Send test** on it. The result shows straight away, such as **Test delivered (200)** or the error your endpoint returned. Tests don't appear in the delivery log, and they work only while the endpoint is **ACTIVE**.

## If nothing was sent

ReTestimonial decides when an event happens which endpoints get it. Nothing is queued when:

- **The endpoint doesn't subscribe to that event.** Each change sends its own event: approving a testimonial sends `testimonial.approved`, not `testimonial.created`. Choose **Edit endpoint** in the endpoint's menu and tick the events you need. [Webhooks](/help/integrations/webhooks#events) lists when each one is sent.
- **The testimonial arrived through a file import or a review sync.** While **Include bulk imports and review sync events** is off, as it is for a new endpoint, the endpoint gets no event when an import or a sync brings testimonials in, or when an import is undone. What you do with one of them later (approve, edit, archive, delete) is always sent. Tick the setting in **Edit endpoint** if you want the arrivals too.
- **The event happened before the endpoint could get it.** Events aren't sent again later: an endpoint gets nothing from before it was added, before you ticked an event or the bulk imports setting, or from while it was **DISABLED** or **SUSPENDED (plan)**. **Replay** resends only deliveries that are already in the log.
- **It's a form's webhook.** It sends only `testimonial.submitted`, only for its own form's submissions, and only while **Enable webhook** is on in the form builder. Submissions that arrive while it's off are never sent. See [Send a form's submissions to a webhook](/help/integrations/form-webhooks).

## If deliveries stay pending

A **PENDING** delivery is waiting. Check the endpoint's status badge:

- **PAUSED:** events keep queuing, and **Queued while paused** in the **Delivery log** card counts them. Choose **Activate endpoint** in the endpoint's menu to send them.
- **SUSPENDED (plan):** your plan changed. See [If your plan changed](#if-your-plan-changed).
- **ACTIVE:** the delivery is waiting for its next try after a failure (after 1 minute, 10 minutes, then 1 hour), or for its turn. Each endpoint gets a limited number of deliveries an hour, so after a large import the rest wait; **Delivery details** then shows **Deferred**. They go out on their own.

## If deliveries fail

A delivery is marked **FAILED** after four attempts. The **HTTP** column and **Last error** in **Delivery details** say what went wrong:

- **An HTTP status code such as 401, 403 or 404.** Your endpoint answered, but refused the request. A 401 or 403 is usually your signature check: see the next section. A 404 or 405 means the URL is wrong, or the address doesn't accept `POST` requests.
- **The request timed out.** Your endpoint must answer within 10 seconds. Send the 2xx answer first and do slow work afterwards.
- **A redirect.** Redirects aren't followed and count as failures. Use the final address, for example with the right `https://`, `www` or trailing slash.
- **Could not resolve hostname** or **Hostname resolves to a private IP address.** The URL's domain must resolve to a public internet address. `localhost`, private networks and internal names are refused.
- **A firewall or bot protection** in front of your server can block the requests. Its response shows in **Delivery details**; allow requests to your webhook's address through it.

Once it's fixed, click **Retry** on a delivery, or **Replay** to resend all the failed and canceled ones. See [Set up a project webhook](/help/integrations/set-up-a-project-webhook#retry-or-replay-failed-deliveries).

## If your signature check rejects them

If your receiver checks the `X-Signature` header and rejects good requests:

- **Use the current secret.** After **Regenerate signing secret**, the old secret stops working at once and deliveries that were still waiting are canceled. Put the new secret in your receiver, then click **Replay**.
- **Use the whole secret**, including its `whsec_` prefix, as plain text.
- **Sign the raw body,** exactly as it arrived, before any JSON parsing.
- **Check the header's `t` for freshness, not the body's `timestamp`.** `timestamp` is when the event happened and stays the same on every retry, so a check on it rejects every retry as too old. After 15 failed attempts in a row, the endpoint is disabled.
- **Keep your server's clock in sync,** so fresh requests don't look old.

[Webhook signatures, headers and payloads](/help/integrations/verify-webhook-signatures) has a working example.

## If the endpoint was disabled

After 15 failed attempts in a row, an endpoint turns itself off: its badge says **DISABLED**, and **Auto-disabled after 15 consecutive failures**, with the last error, shows under it. The deliveries that were still waiting are canceled, the workspace owner gets an email, and the owner and the project's Admins get a notification.

If the first attempt of a delivery got through and your receiver turned the retries away as too old, it's checking the body's `timestamp`, which is the same on every retry: check the `t` in the `X-Signature` header instead (see [If your signature check rejects them](#if-your-signature-check-rejects-them)).

Fix your receiver first, then choose **Activate endpoint** in the endpoint's menu and click **Replay** to resend the canceled deliveries. Events from while it was disabled weren't queued, so they can't be replayed.

## If your plan changed

- **Your plan no longer includes webhooks.** Every endpoint is suspended, and the **Webhooks** tab shows **Developer Webhooks** with **Upgrade to unlock**. Your endpoints are listed under it as **Saved endpoints**, where you can delete one. They're kept, with their waiting deliveries.
- **Your plan allows fewer endpoints.** Your oldest endpoints keep working, and the newer ones show **SUSPENDED (plan)**.
- **After you upgrade,** suspended endpoints resume on their own when you next open the **Webhooks** tab, or at the next daily check, and send the deliveries that were waiting. You can't activate a suspended endpoint yourself.

To change plans, see [Plans and pricing](/help/account/plans-upgrades-and-cancelling).

## Still not arriving?

[Contact us](/contact) and include:

- the project's name and the endpoint's name;
- the event you expected, and when the change happened;
- the delivery's `id` from its payload in **Delivery details**, and its **Last error**, if there's a delivery.

## Next steps

- [Set up a project webhook](/help/integrations/set-up-a-project-webhook)
- [Webhook signatures, headers and payloads](/help/integrations/verify-webhook-signatures)
- [Webhooks](/help/integrations/webhooks)
