# Webhooks
URL: https://usememos.com/docs/integrations/webhooks

Memos can send webhooks when memos change. Webhooks are configured per user in the Settings page and can be edited or deleted later.

## Events [#events]

Webhooks are dispatched on:

* Memo created
* Memo updated
* Memo deleted
* Memo comment created

## Payload [#payload]

Memos sends a JSON payload containing `activityType`, `creator`, and the affected `memo`. Comment-created payloads include the parent relation so receivers can identify the conversation.

Refer to the [API reference](/docs/api) for the current webhook-related endpoints.

## Signing and verification [#signing-and-verification]

New webhooks receive a Standard Webhooks-compatible signing secret in the form `whsec_<base64>`. Copy it when the webhook is created and store it as a secret in the receiving service. You can reveal an existing secret later from the edit dialog; older unsigned webhooks can generate one there.

Signed deliveries include:

| Header              | Value                                   |
| ------------------- | --------------------------------------- |
| `webhook-id`        | Unique message ID beginning with `msg_` |
| `webhook-timestamp` | Unix timestamp in seconds               |
| `webhook-signature` | `v1,<base64 HMAC>`                      |

Verify the signature before parsing or acting on the payload:

1. Read the raw request body bytes.
2. Remove the `whsec_` prefix and Base64-decode the remaining secret.
3. Build the signed content as `<webhook-id>.<webhook-timestamp>.<raw-body>`.
4. Compute HMAC-SHA256 with the decoded secret and Base64-encode the result.
5. Compare `v1,<result>` with `webhook-signature` using a constant-time comparison.
6. Reject timestamps outside a small tolerance window and deduplicate `webhook-id` values to reduce replay risk.

Do not reserialize parsed JSON before verification; even an equivalent JSON representation produces a different signature.

## Delivery response [#delivery-response]

The receiver must return a `2xx` response with a JSON body whose `code` is `0`, for example:

```json
{ "code": 0 }
```

Non-`2xx` responses, invalid JSON, or a nonzero `code` are treated as delivery failures.

## Network safety [#network-safety]

Webhook URLs must use `http` or `https` and must resolve successfully when they are created or updated.

By default, Memos rejects webhook targets that resolve to reserved or private IP ranges, including loopback, RFC 1918 private networks, link-local addresses, and IPv6 local ranges. This protects the instance from server-side request forgery.

If your deployment intentionally sends webhooks to trusted services on a private network, start Memos with `--allow-private-webhooks` or set `MEMOS_ALLOW_PRIVATE_WEBHOOKS=true`. Keep this disabled for public or multi-user instances unless you control every webhook target.
