# Webhooks

> Signed chat, contact and order events to your own endpoint.

Source: https://anystoreai.com/docs/marketing/webhooks/  
Last updated: 2026-10-22

Webhooks send chat, contact and order events to your own HTTPS address, signed with a secret. Go to **Integrations > Webhooks**. On Growth and Pro. One endpoint covers every store on your account. Only the account owner can change it.

## Connect

1. **Enter your endpoint URL.** Any public HTTPS address. Private and internal addresses aren't allowed, and redirects aren't followed.
2. **Pick the events** to send and select **Connect**. We send a test event straight away.
3. **Copy the signing secret.** It's shown once. Select **New secret** to make another one. The old one stops working at once.

## Events

| Event | Sent when |
|---|---|
| conversation.started | A shopper sends their first message |
| contact.captured | A shopper gives their email |
| conversation.handoff_requested | A shopper asks to talk to a person |
| conversation.needs_review | A chat is flagged for review |
| conversation.rated | A shopper rates the chat |
| newsletter.signup | A shopper confirms a newsletter signup |
| cart.created | The assistant builds a cart. Shopify stores only |
| order.attributed | A paid order comes from a chat. Shopify stores only |

Each event has the same outer fields as the [Zapier events](https://anystoreai.com/docs/marketing/zapier/#what-an-event-looks-like): id, type, created_at, store and data.

## Check the signature

Every request has these headers:

- **X-AnyStore-Signature**: sha256= and the HMAC-SHA256 of the raw request body, made with your signing secret.
- **X-AnyStore-Event**: the event type.
- **X-AnyStore-Delivery**: a unique id. Use it to skip an event you already handled.

```js
import crypto from "node:crypto";

function isValid(rawBody, header, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return header.length === expected.length && crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
```

## Delivery

- Answer with a 2xx status within 10 seconds.
- If your endpoint doesn't, we try again after 1, 5 and 30 minutes and 2 hours. Events still waiting after 3 days are dropped.
- Select **Send test event** any time to check your endpoint.

## If something goes wrong

- **Needs attention** shows when events stop reaching your endpoint, and the account owner gets an email.
- Turn off **Send events** to pause without losing the setup. The card shows **Paused**.
- **Disconnect** stops events. Any still waiting to be sent are dropped.
