Payment not being detected
Payment not being detected
When a customer pays but the session status stays
pending, the most likely cause is a misconfigured or missing Alchemy integration.Check your Alchemy integration:- Open Dashboard → Integrations → Alchemy and confirm the integration is enabled.
- Verify that
ALCHEMY_API_KEYandALCHEMY_AUTH_TOKENare set correctly in your environment variables. - Click Provision Webhooks to register Alchemy Address Activity webhooks for each chain. This step is required after the first deploy and after adding new chains.
- The
toaddress matches the session’saddressfield exactly - The token and chain match what was requested
- The transaction has reached the required number of confirmations (default: 3)
Session shows underpaid
Session shows underpaid
The
underpaid status means the customer sent less than the required amount. The session does not auto-resolve — it stays in underpaid regardless of elapsed time.Resolution options:- Contact the customer. They may be able to send a top-up transaction to the same deposit address, but note that the session may have already expired.
- If the session has expired, create a new session for the remaining difference and redirect the customer to it.
- If the payment amount was incorrect on your side (e.g., a currency conversion issue), void the old session and create a new one for the correct amount.
The
underpaid status is a terminal state by design — it requires a merchant decision. Crypto Checkout does not automatically credit partial payments because doing so could enable payment griefing attacks.Session expired before payment confirmed
Session expired before payment confirmed
The default session TTL is 5 minutes. If a customer pays after the session expires, the following behaviour applies:
- Within the grace window (default: 10 minutes): the session transitions to
paid_late. Treat this as a successful payment — the funds were received. - After the grace window: the session is permanently
expired. The on-chain transaction exists but is not automatically linked to the session.
- Open the session in Dashboard → Sessions.
- Use the Check payment button to force an on-chain scan. Even for expired sessions, this can detect and link a late payment.
- If the scan confirms the funds arrived, fulfil the order manually and update your internal records.
401 Unauthorized
401 Unauthorized
403 Forbidden
403 Forbidden
A
Fix: Generate a new API key in Dashboard → API Keys with the correct scopes selected. You cannot add scopes to an existing key — create a new one and revoke the old key once you have updated your environment.
403 response means the API key is valid but does not have the required scope for the operation you are attempting.Available scopes:| Scope | Grants access to |
|---|---|
sessions:read | Retrieve and list checkout sessions |
sessions:write | Create checkout sessions |
links:read | Retrieve and list payment links |
links:write | Create, update, and delete payment links |
webhooks:read | Retrieve and list webhook endpoints |
webhooks:write | Create, delete, and test webhook endpoints |
events:read | Retrieve and list events |
customers:read | Retrieve and list customers |
customers:write | Create and update customers |
Webhook not being delivered
Webhook not being delivered
If
session.paid events are not reaching your endpoint, work through this checklist:1. Confirm the endpoint URL is publicly reachable.
Your Crypto Checkout server must be able to open an outbound HTTPS connection to your webhook URL. If you are developing locally, use ngrok http 8256 or cloudflared tunnel to expose your dev server.2. Check the delivery log.
Open Dashboard → Webhooks → [your endpoint] → Delivery log. Each attempt shows the HTTP status code, response body, and error message returned by your server.3. Understand the retry schedule.
Failed deliveries are retried up to 6 times over approximately 31 hours using exponential backoff. If all 6 attempts fail, the delivery is marked failed and no further retries occur.4. Check your endpoint’s response.
Your handler must return a 2xx status code within the timeout window. Any other status code (including 3xx redirects) counts as a failure. Ensure your handler calls res.sendStatus(200) (or equivalent) before performing any slow operations.5. Send a test event.
Use the Test button on the endpoint detail page (or the API) to send a synthetic session.paid event. This is the fastest way to verify your handler is reachable and responding correctly:Sweep failed
Sweep failed
A sweep failure means Crypto Checkout received the payment but could not forward the funds to your payout wallet. Check Dashboard → Payouts for the specific error message.Common causes:
- Insufficient gas wallet balance — for EVM chains, the gas wallet (the wallet that signs the sweep transaction) needs ETH (or POL on Polygon) to pay gas fees. Add a small amount of the native token to cover gas.
- ERC-20 token sweeps — sweeping USDC, USDT, or other ERC-20 tokens requires the gas wallet to hold ETH (or the chain’s native token) even though the asset being swept is an ERC-20. Ensure the gas wallet has enough native token to cover the token approval and transfer gas.
- RPC error — a transient failure from the Alchemy RPC node. The sweep will be retried automatically; check Dashboard → Payouts again after a few minutes.
- Wrong payout address format — verify your payout addresses in Settings → Wallet. EVM addresses must be valid checksummed hex; Solana addresses must be valid base58 public keys.
Signature verification failing
Signature verification failing
Webhook signature verification failures are almost always caused by one of these issues:1. Not using the raw request body.
You must compute the HMAC over the raw bytes received from the network — do not JSON-parse and re-serialize the body, and do not let a body-parser middleware decode it first.2. Using the wrong secret.
The secret for signature verification is the webhook endpoint secret — the value shown once when you create the endpoint in Dashboard → Webhooks. It is not your API key. If you lost the secret, delete the endpoint and create a new one.3. Stale timestamp.
Deliveries more than 5 minutes old are rejected to protect against replay attacks. Ensure your server clock is synchronised (NTP) and that you are not buffering or delaying webhook processing.4. Accidental body re-encoding.
Some frameworks (e.g., AWS API Gateway, certain reverse proxies) may base64-encode or otherwise transform the request body. If you are behind such a proxy, decode the body back to its original byte representation before verifying.Manual verification (Node.js, no SDK):
Additional resources
Signature verification
Full reference for HMAC signature verification, including test vectors.
Payouts
Understanding sweep transactions and payout statuses.
Session lifecycle
Every session status and the conditions that trigger each transition.