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

# Alchemy Setup

> Configure Alchemy for blockchain RPC and payment detection webhooks

Alchemy provides two things:

1. **RPC access** — reading chain state, fetching transaction receipts, submitting sweep transactions.
2. **Address Activity webhooks** — real-time notification when a payment arrives at a session's deposit address.

With webhooks enabled, payments are detected in under a second. Without them, the app falls back to polling.

## Credentials

You need two separate credentials from Alchemy:

| Credential            | Location in Alchemy dashboard                                            | Used for                       |
| --------------------- | ------------------------------------------------------------------------ | ------------------------------ |
| **API Key**           | Apps → your app → API Key                                                | RPC and data access            |
| **Notify Auth Token** | Data → Webhooks → **AUTH TOKEN** button (top-right of the webhooks list) | Creating and managing webhooks |

Direct link to the webhooks page: [`dashboard.alchemy.com/apps/latest/webhooks`](https://dashboard.alchemy.com/apps/latest/webhooks)

<Warning>
  The #1 setup mistake is using the API key as the auth token. They are different values. The API Key is per-app; the Notify Auth Token is account-wide.
</Warning>

<Note>
  **Can't find the AUTH TOKEN button?** It only appears once the webhooks page has at
  least one webhook — with zero webhooks Alchemy shows an empty "Create a webhook"
  prompt and hides the token. Click **Create Webhook**, pick **Address Activity**, choose
  any network and address, and save. The page then switches to the populated list and the
  **AUTH TOKEN** button appears in the top-right. You can delete that webhook afterward —
  the app creates and manages its own webhooks automatically. Note: **Security → Access
  Keys** is a *different* credential (JSON-RPC / NFT / Gas Manager) and does **not** work
  as the Notify Auth Token.
</Note>

## Dashboard setup

1. Sign in to your My Crypto Server dashboard.
2. Go to **Integrations → Alchemy**.
3. Enter your **API Key**, **Notify Auth Token**, and **Webhook Public URL** (your app's public HTTPS URL).
4. Toggle **Enabled** on and click **Save**.

That's all — there is **no provisioning step**. Webhooks are created and deleted on demand as sessions come and go (see [How it works](#how-it-works)).

<Note>
  Webhooks are created lazily, one per chain, only while a payment is in flight. You hold at most one webhook per chain with an active session — never all supported chains at once — so this stays comfortably under Alchemy's free-tier webhook limit and never leaves an empty webhook listening to chain-wide activity.
</Note>

## Inspecting webhooks

Webhooks come and go automatically. To see what currently exists:

```bash theme={null}
psql $DATABASE_URL -c "SELECT chain_id, kind, webhook_id FROM alchemy_webhooks;"
```

An empty result simply means no onchain session is active right now.

## How it works

* When a checkout session is created, its deposit address is added to that chain's Alchemy webhook — **creating the webhook (with the address already attached) if it doesn't exist yet**.
* When the customer sends funds, Alchemy POSTs to `/api/webhooks/alchemy` (EVM), `/api/webhooks/alchemy/solana`, or `/api/webhooks/alchemy/btc`.
* Each request is HMAC-SHA256 verified against the signing key stored in the `alchemy_webhooks` table.
* On session completion (paid, expired, or failed), the address is removed — and if it was the webhook's last address, **the webhook is deleted**.
* An hourly reconcile job re-asserts this from the database: it (re)creates any webhook a failed add missed and removes ones with no active sessions. The poller is the safety net throughout.

## Supported chains

| Chain                    | Webhook support  |
| ------------------------ | ---------------- |
| Ethereum (1, 11155111)   | Alchemy webhook  |
| Base (8453, 84532)       | Alchemy webhook  |
| Arbitrum (42161, 421614) | Alchemy webhook  |
| Optimism (10, 11155420)  | Alchemy webhook  |
| Polygon (137, 80002)     | Alchemy webhook  |
| Solana (101, 103)        | Alchemy webhook  |
| Bitcoin (8333, 38333)    | Alchemy webhook  |
| Other                    | Polling fallback |

## Troubleshooting

| Error                                     | Fix                                                                                                                                       |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| "Alchemy API key not configured"          | Set API Key under Integrations → Alchemy                                                                                                  |
| "Alchemy auth token not set"              | Set Notify Auth Token under Integrations → Alchemy                                                                                        |
| No AUTH TOKEN button in Alchemy dashboard | Create any webhook (Address Activity) first — the button is hidden until the webhooks page has one                                        |
| No webhook created for a session          | Confirm the integration is enabled and the Webhook Public URL is set (HTTPS, publicly reachable) — without it the app stays on the poller |
| 401 in webhook logs                       | Signing-key mismatch — the hourly reconcile self-heals; payments are still caught by the poller                                           |
| Webhooks not firing                       | Confirm public URL is reachable, check Alchemy delivery logs                                                                              |

## Disabling webhooks

Toggle the Alchemy integration off, or leave the auth token / public URL blank. The app will fall back to polling on all chains — slower but fully functional.
