> ## Documentation Index
> Fetch the complete documentation index at: https://docs.setaside.money/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction webhooks

> Send new transaction details to your own HTTPS endpoint, with custom authentication headers.

Transaction webhooks send new transaction details to an HTTPS URL you control. Use them to connect Set Aside Money to an automation or another service. Deliveries continue while your browser is closed.

## Set up a webhook

1. In the web app, open **Settings → Transaction webhooks**.
2. Choose **Add webhook**, enter a name, and enter your public HTTPS destination.
3. Add any **Custom headers** required by the destination.
4. Save the webhook and copy its signing secret. This secret is shown only once.
5. Choose **Send test**, then **Refresh status** to check the response.

A queued test has not necessarily been delivered. A successful delivery receives an HTTP `2xx` response from the destination. Test events contain a synthetic example purchase and do not create a transaction.

Each webhook belongs to its creator in the selected personal or joint Set Aside Money account. Other joint-account members cannot manage it. Delivery requires the creator to remain an account member and the account's subscription to remain active. Web settings are available on all active plans.

## Custom authentication headers

Enter the header name and its complete value in separate fields. For example:

| Header name | Header value |
| - | - |
| `Authorization` | `Bearer YOUR_DESTINATION_TOKEN` |
| `X-Api-Key` | `YOUR_DESTINATION_API_KEY` |

Use the authentication format required by your destination. Set Aside Money sends the value you enter; it does not add `Bearer ` or another authentication prefix.

<Note>
  Header values are encrypted and hidden after saving. The webhook list displays names only, such as `authorization`. Lowercase names are normal because HTTP header names are case-insensitive. A blank value field when you reopen **Headers** does not mean the saved value was deleted.
</Note>

To replace headers, choose **Headers**, enter the complete set and re-enter every value you want to keep. Remove every row and save to clear all custom headers. Replacement applies to future delivery attempts, including pending retries, without changing the webhook's paused or active state.

Custom headers are sent with both real transaction events and synthetic tests. Header values are never returned in list, creation, or update responses.

You can configure up to 20 headers, with at most 128 characters per name, 4096 characters per value, and 8192 bytes in total. Names must be unique regardless of case. Line breaks and overrides of delivery, signing, or HTTP transport headers are rejected. Reserved names include `Host`, `Content-Type`, `Content-Length`, `Connection`, `webhook-*`, `X-Set-Aside-*`, and `X-MCP-Subscription-Id`.

For developer requests, limits, payloads, and signature verification, see the [webhook API reference](/api-reference/webhooks).

## Create through MCP

The `create_webhook` tool accepts `name`, `url`, optional `headers`, and `confirm`. It requires an MCP connection with `mcp.write` permission.

Preview first:

```json theme={null}
{
  "name": "My automation",
  "url": "https://example.com/webhook",
  "headers": {
    "Authorization": "Bearer YOUR_DESTINATION_TOKEN"
  },
  "confirm": false
}
```

The preview shows the destination and header names while hiding values. After explicit approval, call the same tool with the same settings and `"confirm": true`. Save the signing secret returned once on creation.

<Note>
  The current MCP tool creates webhooks. To change headers on an existing webhook, use **Headers** in web settings or the REST `PATCH` endpoint in the [API reference](/api-reference/webhooks). MCP tools for listing, updating, and testing existing transaction webhooks are not currently implemented.
</Note>

## When events arrive

Webhooks send newly observed pending or booked transactions. Initial bank history, updates, and pending-to-posted replacements do not produce additional events. Bank timing depends on provider availability and the next sync.

## Retries and troubleshooting

Delivery is at least once, with no ordering guarantee. Timeouts, network failures, HTTP `408`, `429`, and `5xx` retry up to eight total attempts. Backoff begins at 30 seconds and doubles, capped at one hour. Other non-`2xx` responses are terminal for that event. HTTP `410` also pauses the webhook.

Redirects are not followed. Destinations must resolve to public addresses; private, loopback, and link-local addresses are refused.

### HTTP 401 or 403

The destination rejected the request. A displayed header name confirms that a header is configured, but does not prove that its value is valid for the destination.

Check that the header value uses the destination's required authentication scheme, token, and permissions. For bearer authentication, enter `Bearer YOUR_DESTINATION_TOKEN` as the value, without repeating `Authorization:`. Replace the headers if necessary, then send a new test and refresh status. A previous failed event is not automatically retried after a `401` or `403`.

### No deliveries

Confirm the webhook is active, the creator is still an account member, and the account has an active subscription. Check that the relevant bank account remains subscribed and visible. Initial history does not trigger events. Use **Send test** to test the destination separately from bank-sync timing.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.